### Install WorkOS Node.js Library Source: https://github.com/workos/workos-node/blob/main/README.md Install the WorkOS Node.js package using npm. ```bash npm install @workos-inc/node ``` -------------------------------- ### Authorization List Pagination After v9 Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md Example of authorization list endpoint usage in v9, demonstrating standardized pagination with explicit `order` parameter. ```typescript const page = await workos.authorization.listOrganizationMembershipRoleAssignments({ organizationMembershipId: 'om_123', order: 'desc', }); ``` -------------------------------- ### Authorization List Pagination Before v9 Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md Example of authorization list endpoint usage in v8, where some endpoints had different default pagination behavior. ```typescript const page = await workos.authorization.listRoleAssignments({ organizationMembershipId: 'om_123', }); // Some authorization list endpoints behaved differently from the rest // of the SDK when no explicit order was provided. ``` -------------------------------- ### Rename Organization Domains Methods Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md The `organizationDomains` methods have been renamed for greater explicitness. For example, `get` is now `getOrganizationDomain`. ```typescript const domain = await workos.organizationDomains.get('org_domain_123'); await workos.organizationDomains.verify('org_domain_123'); ``` ```typescript const domain = await workos.organizationDomains.getOrganizationDomain('org_domain_123'); await workos.organizationDomains.verifyOrganizationDomain('org_domain_123'); ``` -------------------------------- ### refreshAndSealSessionData() Replacement (v8) Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The `refreshAndSealSessionData()` method is removed. Use `loadSealedSession` to get a `CookieSession` object, then call its `refresh()` method. ```typescript // Use loadSealedSession to get a CookieSession, then call refresh() const session = workos.userManagement.loadSealedSession({ sessionData: encryptedSession, cookiePassword: 'secret', }); const result = await session.refresh({ organizationId: 'org_123' }); // result.sealedSession contains the new sealed session data ``` -------------------------------- ### Configure WorkOS with API Key (Directly) Source: https://github.com/workos/workos-node/blob/main/README.md Initialize the WorkOS client by providing the API key directly in the code. Ensure the API key is kept secret. ```typescript import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS('sk_1234'); ``` -------------------------------- ### Import WorkOS SDK in Node.js Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md Demonstrates how to import the WorkOS SDK using both ESM and CommonJS syntax. The SDK supports dual exports, so existing `require` statements should continue to work. ```typescript // ESM - works import { WorkOS } from '@workos-inc/node'; // CommonJS - still works const { WorkOS } = require('@workos-inc/node'); // Cloudflare Workers - use /worker import { WorkOS } from '@workos-inc/node/worker'; ``` -------------------------------- ### Initialize WorkOS for Public Client Mode Source: https://github.com/workos/workos-node/blob/main/README.md Initialize the WorkOS client with only a client ID for public clients (browser, mobile, CLI) where secrets cannot be securely stored. No API key is needed. ```typescript import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS({ clientId: 'client_...' }); // No API key needed ``` -------------------------------- ### Automatic PKCE Authentication Flow Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md Initialize WorkOS with a `clientId` for public clients and use `getAuthorizationUrlWithPKCE` to generate a URL. Store the `codeVerifier` and use it in `authenticateWithCode` after receiving the authorization code. ```typescript import { WorkOS } from '@workos-inc/node'; // Initialize with just clientId (no API key for public clients) const workos = new WorkOS({ clientId: 'client_123' }); // Generate authorization URL with PKCE const { url, state, codeVerifier } = await workos.userManagement.getAuthorizationUrlWithPKCE({ redirectUri: 'myapp://callback', provider: 'authkit', }); // Store codeVerifier securely (in-memory, secure storage, etc.) // Redirect user to url... // After user authenticates and you receive the code: const { accessToken, refreshToken, user } = await workos.userManagement.authenticateWithCode({ code: authCode, codeVerifier, // Use the codeVerifier from earlier }); ``` -------------------------------- ### Manual PKCE Generation Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md Generate PKCE `codeVerifier` and `codeChallenge` manually if you need more control over the authorization URL generation process. ```typescript // Generate PKCE manually const { codeVerifier, codeChallenge } = workos.pkce.generate(); // Use in authorization URL const url = workos.userManagement.getAuthorizationUrl({ redirectUri: 'myapp://callback', provider: 'authkit', codeChallenge, codeChallengeMethod: 'S256', }); ``` -------------------------------- ### Check Node.js Version Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md Use this command to check your current Node.js version. Ensure it is v20 or higher before migrating. ```bash # Check your Node version node --version # If below v20, upgrade Node.js first # https://nodejs.org/ ``` -------------------------------- ### Check Node.js Version Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md Verify your current Node.js version. v9 requires Node.js 22.11.0 or newer. ```bash node --version ``` -------------------------------- ### Generate Auth URL with PKCE (Public Client) Source: https://github.com/workos/workos-node/blob/main/README.md Generate an authorization URL with automatic PKCE for public clients. The `codeVerifier` must be stored securely on-device between the auth URL generation and callback handling. ```typescript // Generate auth URL with automatic PKCE const { url, codeVerifier } = await workos.userManagement.getAuthorizationUrlWithPKCE({ provider: 'authkit', redirectUri: 'myapp://callback', clientId: 'client_...', }); // After user authenticates, exchange code for tokens const { accessToken, refreshToken } = await workos.userManagement.authenticateWithCode({ code: authorizationCode, codeVerifier, clientId: 'client_...', }); ``` -------------------------------- ### Configure WorkOS with API Key (Environment Variable) Source: https://github.com/workos/workos-node/blob/main/README.md Set the WorkOS API key as an environment variable. This is the recommended method for server-side applications. ```sh WORKOS_API_KEY="sk_1234" ``` -------------------------------- ### Server-Side Authentication (No Changes) Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md If using the SDK server-side with an API key, the authentication process remains the same as in previous versions. ```typescript // Still works exactly the same const workos = new WorkOS({ apiKey: 'sk_...', clientId: 'client_123' }); const { accessToken, user } = await workos.userManagement.authenticateWithCode({ code: authCode, }); ``` -------------------------------- ### Create WorkOS Client with Type Safety Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md Use `createWorkOS()` for type safety in public vs. server apps. `new WorkOS()` can be used if compile-time enforcement is not needed. ```typescript import { createWorkOS } from '@workos-inc/node'; // Public client - TypeScript knows what's available const publicClient = createWorkOS({ clientId: 'client_123' }); publicClient.userManagement.getAuthorizationUrlWithPKCE({ ... }); // ✅ Works publicClient.userManagement.listUsers(); // ❌ TypeScript error - method doesn't exist // Confidential client - full API access const serverClient = createWorkOS({ apiKey: 'sk_...', clientId: 'client_123' }); serverClient.userManagement.listUsers(); // ✅ Works ``` -------------------------------- ### MFA: verifyFactor() replaced by verifyChallenge() Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The 'verifyFactor()' method for MFA has been removed. Use 'verifyChallenge()' instead, as it provides the same functionality. ```typescript const result = await workos.mfa.verifyFactor({ authenticationChallengeId: 'auth_challenge_123', code: '123456', }); ``` ```typescript const result = await workos.mfa.verifyChallenge({ authenticationChallengeId: 'auth_challenge_123', code: '123456', }); ``` -------------------------------- ### Migrate from Legacy FGA to Authorization Client Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md Replace calls to `workos.fga` with `workos.authorization`. There is no direct argument-for-argument mapping for all FGA concepts to the newer Authorization APIs. ```typescript workos.fga.check(...) -> workos.authorization.check(...) ``` ```typescript workos.fga.listResources(...) -> workos.authorization.listResources(...) ``` ```typescript workos.fga.getResource(...) -> workos.authorization.getResource(...) ``` -------------------------------- ### listOrganizationMemberships Parameter Requirements (v8) Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The `listOrganizationMemberships()` method now requires either `userId` or `organizationId` as a parameter. It can no longer be called without arguments. ```typescript // ✅ Specify userId OR organizationId const memberships = await workos.userManagement.listOrganizationMemberships({ userId: 'user_123', }); // OR const memberships = await workos.userManagement.listOrganizationMemberships({ organizationId: 'org_456', }); ``` -------------------------------- ### WorkOS SDK v8 Public API Usage Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md After migrating to v8, always use the public API for initialization and access. Deep imports from internal modules are no longer supported. ```typescript // ✅ Use the public API import { WorkOS } from '@workos-inc/node'; const workos = new WorkOS({ apiKey: 'sk_...' }); ``` -------------------------------- ### SSO Authorization URL Options: Discriminated Union Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md In v8, you must specify exactly one of 'connection', 'organization', or 'provider' for SSO authorization URLs. Specifying multiple options will result in a TypeScript error. ```typescript const url = workos.sso.getAuthorizationUrl({ connection: 'conn_123', organization: 'org_456', // Both allowed redirectUri: 'https://example.com/callback', }); ``` ```typescript const url = workos.sso.getAuthorizationUrl({ connection: 'conn_123', // OR organization OR provider (not multiple) redirectUri: 'https://example.com/callback', }); ``` ```typescript const url = workos.sso.getAuthorizationUrl({ connection: 'conn_123', organization: 'org_456', // ❌ TypeScript error redirectUri: 'https://example.com/callback', }); ``` -------------------------------- ### PKCE with Confidential Clients Source: https://github.com/workos/workos-node/blob/main/README.md Use PKCE with a server-side application that has an API key for defense in depth. Both the client secret and code verifier will be sent during authentication. ```typescript const workos = new WorkOS('sk_...'); // With API key // Use PKCE even with API key for additional security const { url, codeVerifier } = await workos.userManagement.getAuthorizationUrlWithPKCE({ provider: 'authkit', redirectUri: 'https://example.com/callback', clientId: 'client_...', }); // Both client_secret AND code_verifier will be sent const { accessToken } = await workos.userManagement.authenticateWithCode({ code: authorizationCode, codeVerifier, clientId: 'client_...', }); ``` -------------------------------- ### sendPasswordResetEmail() Replacement (v8) Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The deprecated `sendPasswordResetEmail()` method has been removed. Use `userManagement.createPasswordReset()` instead. ```typescript await workos.userManagement.createPasswordReset({ email: 'user@example.com' }); ``` -------------------------------- ### Update module paths for API key and MFA in v9 Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md Calls related to organization API keys and user multi-factor authentication have moved to new modules. ```typescript await workos.organizations.createOrganizationApiKey({ organizationId: 'org_123', name: 'CI key', }); ``` ```typescript await workos.apiKeys.createOrganizationApiKey({ organizationId: 'org_123', name: 'CI key', }); ``` ```typescript await workos.userManagement.enrollAuthFactor({ userId: 'user_123', type: 'totp', }); ``` ```typescript await workos.multiFactorAuth.createUserAuthFactor({ userId: 'user_123', type: 'totp', }); ``` -------------------------------- ### sendMagicAuthCode() Replacement (v8) Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The deprecated `sendMagicAuthCode()` method has been removed. Use `userManagement.createMagicAuth()` instead. ```typescript await workos.userManagement.createMagicAuth({ email: 'user@example.com' }); ``` -------------------------------- ### Normalize GithubOAuth to GitHubOAuth in v9 Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md The SDK now normalizes the `GithubOAuth` provider casing to `GitHubOAuth` for consistency with `getAuthorizationUrl`. Update comparisons to use the correct casing. ```typescript const identities = await workos.userManagement.getUserIdentities(userId); const github = identities.find((i) => i.provider === 'GithubOAuth'); ``` ```typescript const identities = await workos.userManagement.getUserIdentities(userId); const github = identities.find((i) => i.provider === 'GitHubOAuth'); // The provider value can now be passed directly to getAuthorizationUrl const url = workos.userManagement.getAuthorizationUrl({ provider: github.provider, redirectUri: 'https://example.com/callback', }); ``` -------------------------------- ### SSO Authorization URL Options: Domain Field Removal Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The deprecated 'domain' field for getAuthorizationUrl has been removed in v8. Use the 'organization' field instead. ```typescript const url = workos.sso.getAuthorizationUrl({ domain: 'example.com', // ❌ Removed redirectUri: 'https://example.com/callback', }); ``` ```typescript const url = workos.sso.getAuthorizationUrl({ organization: 'org_123', // Use organization instead redirectUri: 'https://example.com/callback', }); ``` -------------------------------- ### Rename Widgets getToken to createToken and Update Return Type Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md The `widgets.getToken` method is now `widgets.createToken` and its return type has changed from a string to an object containing a `token` property. ```typescript const token = await workos.widgets.getToken({ organizationId: 'org_123', userId: 'user_123', scopes: ['widgets:users-table:manage'], }); // token is a string ``` ```typescript const { token } = await workos.widgets.createToken({ organizationId: 'org_123', userId: 'user_123', scopes: ['widgets:users-table:manage'], }); // Destructure `token` from the response object ``` -------------------------------- ### Rename MFA and Admin Portal Accessors Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md Update client accessors from `workos.mfa` to `workos.multiFactorAuth` and `workos.portal` to `workos.adminPortal`. The underlying functionality remains the same. ```typescript await workos.mfa.enrollFactor({ type: 'totp', issuer: 'My App', user: 'user_123', }); await workos.portal.generateLink({ organization: 'org_123', intent: 'sso', }); ``` ```typescript await workos.multiFactorAuth.enrollFactor({ type: 'totp', issuer: 'My App', user: 'user_123', }); await workos.adminPortal.generateLink({ organization: 'org_123', intent: 'sso', }); ``` -------------------------------- ### Migrate userManagement module calls to v9 Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md Update calls to the `userManagement` module to their new locations and signatures in v9. ```typescript workos.userManagement.enrollAuthFactor(payload) ``` ```typescript workos.userManagement.listAuthFactors(options) ``` ```typescript workos.userManagement.listUserFeatureFlags(options) ``` -------------------------------- ### Organizations: Removed domains Field, Use domainData Instead Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The 'domains' field has been removed from CreateOrganizationOptions and UpdateOrganizationOptions. Use 'domainData' with a 'domain' and 'state' property instead. ```typescript await workos.organizations.createOrganization({ name: 'Acme Corp', domains: ['example.com'], // ❌ Removed }); ``` ```typescript await workos.organizations.createOrganization({ name: 'Acme Corp', domainData: [{ domain: 'example.com', state: 'verified' }], // ✅ Use domainData }); ``` -------------------------------- ### WorkOS SDK v7 Type Safety Issue Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md In v7, TypeScript allowed calling server-only methods on a public client initialized without an API key, leading to runtime errors. This is resolved in v8 with the type-safe client factory. ```typescript // v7 - Runtime error, but TypeScript allows it const workos = new WorkOS({ clientId: 'client_123' }); // No API key await workos.userManagement.listUsers(); // ❌ Fails at runtime ``` -------------------------------- ### Vault: Removed Deprecated Method Aliases Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md Deprecated method aliases like 'createSecret' have been removed in v8. Use the corresponding 'Object' methods (e.g., 'createObject') instead. ```typescript const secret = await workos.vault.createSecret({ name: 'api-key', value: 'sk_test_123', }); ``` ```typescript const object = await workos.vault.createObject({ name: 'api-key', value: 'sk_test_123', }); ``` -------------------------------- ### DirectoryUser Fields Before v8 Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md In v7, user fields like emails, username, and jobTitle were directly accessible on the user object. ```typescript const user = await workos.directorySync.getUser({ user: 'directory_user_123' }); console.log(user.emails); // Primary email console.log(user.username); // Username console.log(user.jobTitle); // Job title ``` -------------------------------- ### Migrate organizations module calls to v9 Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md Update calls to the `organizations` module to their new locations and signatures in v9. Note the signature change for `listOrganizationRoles`. ```typescript workos.organizations.listOrganizationRoles({ organizationId }) ``` ```typescript workos.organizations.listOrganizationFeatureFlags({ organizationId, ...options }) ``` ```typescript workos.organizations.listOrganizationApiKeys({ organizationId, ...options }) ``` ```typescript workos.organizations.createOrganizationApiKey({ organizationId, ...payload }) ``` -------------------------------- ### DirectoryUser Fields Moved to customAttributes (v8) Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md User fields like emails, username, and jobTitle are now located within `customAttributes` to align with the API structure. Access them using optional chaining. ```typescript const user = await workos.directorySync.getUser({ user: 'directory_user_123' }); console.log(user.customAttributes?.emails); // Array of emails console.log(user.customAttributes?.username); // Username console.log(user.customAttributes?.jobTitle); // Job title ``` -------------------------------- ### Removed getPrimaryEmail() Utility (v8) Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The `getPrimaryEmail()` helper function is removed in v8. Access the primary email directly from `customAttributes.emails` or create your own helper function. ```typescript // Option 1: Access directly const primaryEmail = user.customAttributes?.emails?.[0]; // Option 2: Create your own helper function getPrimaryEmail(user: DirectoryUser): string | undefined { return user.customAttributes?.emails?.[0]; } ``` -------------------------------- ### AuthorizationURLOptions context Field Removed (v8) Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The `context` field in `AuthorizationURLOptions` is no longer supported. Use the `state` parameter for client-side data instead. ```typescript const url = workos.userManagement.getAuthorizationUrl({ provider: 'authkit', redirectUri: 'https://example.com/callback', // Use state parameter for client-side data state: 'your-state-data', }); ``` -------------------------------- ### Rename API Key Validation Method Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md The `validateApiKey` method on the `apiKeys` client has been renamed to `createValidation`. ```typescript const result = await workos.apiKeys.validateApiKey({ value: 'sk_test_123', }); ``` ```typescript const result = await workos.apiKeys.createValidation({ value: 'sk_test_123', }); ``` -------------------------------- ### Organizations: OrganizationDomainState Enum Change Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The 'legacy_verified' state has been removed from the OrganizationDomainState enum in v8. Use 'verified' instead. ```typescript if (domain.state === 'legacy_verified') { // ❌ No longer exists // ... } ``` ```typescript if (domain.state === 'verified') { // ✅ Use 'verified' // ... } ``` -------------------------------- ### Organizations: Removed allowProfilesOutsideOrganization Field Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The 'allowProfilesOutsideOrganization' field has been removed from CreateOrganizationOptions and UpdateOrganizationOptions in v8. Use API settings instead. ```typescript await workos.organizations.createOrganization({ name: 'Acme Corp', allowProfilesOutsideOrganization: true, // ❌ Removed }); ``` ```typescript await workos.organizations.createOrganization({ name: 'Acme Corp', // Field removed - use API settings instead }); ``` -------------------------------- ### Events: dsync.deactivated Removed, Use dsync.deleted Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md The 'dsync.deactivated' event type has been removed in v8. Use 'dsync.deleted' instead to handle deactivated events. ```typescript if (event.event === 'dsync.deactivated') { // Handle deactivated event } ``` ```typescript if (event.event === 'dsync.deleted') { // ✅ Use dsync.deleted // Handle deleted event } ``` -------------------------------- ### Update listOrganizationRoles signature in v9 Source: https://github.com/workos/workos-node/blob/main/docs/V9_MIGRATION_GUIDE.md The `listOrganizationRoles` function signature changed from accepting an options object to a positional string argument for `organizationId`. ```typescript const roles = await workos.organizations.listOrganizationRoles({ organizationId: 'org_123', }); ``` ```typescript const roles = await workos.authorization.listOrganizationRoles('org_123'); ``` -------------------------------- ### Events: Organization Membership Events Removed Source: https://github.com/workos/workos-node/blob/main/docs/V8_MIGRATION_GUIDE.md Organization membership events like 'OrganizationMembershipAdded' and 'OrganizationMembershipRemoved' are not applicable in v8. Contact WorkOS support for migration guidance if you were using these events. ```typescript // Not applicable in v8 // if (event.event === 'OrganizationMembershipAdded') { // // ... // } ``` ```typescript // Not applicable in v8 // if (event.event === 'OrganizationMembershipRemoved') { // // ... // } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.