@workos-inc/node 7.69.2 → 7.71.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. package/lib/organizations/interfaces/index.d.ts +0 -1
  2. package/lib/organizations/interfaces/index.js +0 -1
  3. package/lib/organizations/organizations.d.ts +1 -1
  4. package/lib/organizations/organizations.js +1 -1
  5. package/lib/sso/interfaces/connection-type.enum.d.ts +1 -0
  6. package/lib/sso/interfaces/connection-type.enum.js +1 -0
  7. package/lib/user-management/fixtures/list-user-feature-flags.json +33 -0
  8. package/lib/user-management/fixtures/list-users.json +2 -1
  9. package/lib/user-management/fixtures/user.json +1 -0
  10. package/lib/user-management/interfaces/authenticate-with-session-cookie.interface.d.ts +2 -0
  11. package/lib/user-management/interfaces/authentication-response.interface.d.ts +1 -1
  12. package/lib/user-management/interfaces/create-organization-membership-options.interface.d.ts +2 -0
  13. package/lib/user-management/interfaces/identity.interface.d.ts +2 -2
  14. package/lib/user-management/interfaces/index.d.ts +1 -0
  15. package/lib/user-management/interfaces/index.js +1 -0
  16. package/lib/user-management/interfaces/list-user-feature-flags-options.interface.d.ts +4 -0
  17. package/lib/user-management/interfaces/list-user-feature-flags-options.interface.js +2 -0
  18. package/lib/user-management/interfaces/organization-membership.interface.d.ts +2 -0
  19. package/lib/user-management/interfaces/update-organization-membership-options.interface.d.ts +2 -0
  20. package/lib/user-management/interfaces/update-user-options.interface.d.ts +2 -0
  21. package/lib/user-management/interfaces/user.interface.d.ts +2 -0
  22. package/lib/user-management/serializers/create-organization-membership-options.serializer.js +1 -0
  23. package/lib/user-management/serializers/organization-membership.serializer.js +1 -11
  24. package/lib/user-management/serializers/update-organization-membership-options.serializer.js +1 -0
  25. package/lib/user-management/serializers/update-user-options.serializer.js +1 -0
  26. package/lib/user-management/serializers/user.serializer.js +1 -0
  27. package/lib/user-management/session.js +4 -2
  28. package/lib/user-management/session.spec.js +4 -2
  29. package/lib/user-management/user-management.d.ts +3 -1
  30. package/lib/user-management/user-management.js +9 -1
  31. package/lib/user-management/user-management.spec.js +135 -0
  32. package/lib/workos.js +1 -1
  33. package/package.json +1 -1
  34. /package/lib/{organizations → feature-flags}/interfaces/feature-flag.interface.d.ts +0 -0
  35. /package/lib/{organizations → feature-flags}/interfaces/feature-flag.interface.js +0 -0
  36. /package/lib/{organizations → feature-flags}/serializers/feature-flag.serializer.d.ts +0 -0
  37. /package/lib/{organizations → feature-flags}/serializers/feature-flag.serializer.js +0 -0
@@ -1,6 +1,5 @@
1
1
  export * from './create-organization-options.interface';
2
2
  export * from './domain-data.interface';
3
- export * from './feature-flag.interface';
4
3
  export * from './list-organization-feature-flags-options.interface';
5
4
  export * from './list-organizations-options.interface';
6
5
  export * from './organization.interface';
@@ -16,7 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./create-organization-options.interface"), exports);
18
18
  __exportStar(require("./domain-data.interface"), exports);
19
- __exportStar(require("./feature-flag.interface"), exports);
20
19
  __exportStar(require("./list-organization-feature-flags-options.interface"), exports);
21
20
  __exportStar(require("./list-organizations-options.interface"), exports);
22
21
  __exportStar(require("./organization.interface"), exports);
@@ -1,7 +1,7 @@
1
1
  import { AutoPaginatable } from '../common/utils/pagination';
2
2
  import { WorkOS } from '../workos';
3
3
  import { CreateOrganizationOptions, CreateOrganizationRequestOptions, ListOrganizationsOptions, Organization, UpdateOrganizationOptions } from './interfaces';
4
- import { FeatureFlag } from './interfaces/feature-flag.interface';
4
+ import { FeatureFlag } from '../feature-flags/interfaces/feature-flag.interface';
5
5
  import { RoleList } from '../roles/interfaces';
6
6
  import { ListOrganizationRolesOptions } from './interfaces/list-organization-roles-options.interface';
7
7
  import { ListOrganizationFeatureFlagsOptions } from './interfaces/list-organization-feature-flags-options.interface';
@@ -25,7 +25,7 @@ const pagination_1 = require("../common/utils/pagination");
25
25
  const serializers_1 = require("./serializers");
26
26
  const fetch_and_deserialize_1 = require("../common/utils/fetch-and-deserialize");
27
27
  const role_serializer_1 = require("../roles/serializers/role.serializer");
28
- const feature_flag_serializer_1 = require("./serializers/feature-flag.serializer");
28
+ const feature_flag_serializer_1 = require("../feature-flags/serializers/feature-flag.serializer");
29
29
  class Organizations {
30
30
  constructor(workos) {
31
31
  this.workos = workos;
@@ -28,6 +28,7 @@ export declare enum ConnectionType {
28
28
  PingFederateSAML = "PingFederateSAML",
29
29
  PingOneSAML = "PingOneSAML",
30
30
  RipplingSAML = "RipplingSAML",
31
+ SalesforceOAuth = "SalesforceOAuth",
31
32
  SalesforceSAML = "SalesforceSAML",
32
33
  ShibbolethGenericSAML = "ShibbolethGenericSAML",
33
34
  ShibbolethSAML = "ShibbolethSAML",
@@ -32,6 +32,7 @@ var ConnectionType;
32
32
  ConnectionType["PingFederateSAML"] = "PingFederateSAML";
33
33
  ConnectionType["PingOneSAML"] = "PingOneSAML";
34
34
  ConnectionType["RipplingSAML"] = "RipplingSAML";
35
+ ConnectionType["SalesforceOAuth"] = "SalesforceOAuth";
35
36
  ConnectionType["SalesforceSAML"] = "SalesforceSAML";
36
37
  ConnectionType["ShibbolethGenericSAML"] = "ShibbolethGenericSAML";
37
38
  ConnectionType["ShibbolethSAML"] = "ShibbolethSAML";
@@ -0,0 +1,33 @@
1
+ {
2
+ "object": "list",
3
+ "data": [
4
+ {
5
+ "object": "feature_flag",
6
+ "id": "flag_01EHQMYV6MBK39QC5PZXHY59C5",
7
+ "name": "Advanced Dashboard",
8
+ "slug": "advanced-dashboard",
9
+ "description": "Enable advanced dashboard features",
10
+ "created_at": "2024-01-01T00:00:00.000Z",
11
+ "updated_at": "2024-01-01T00:00:00.000Z"
12
+ },
13
+ {
14
+ "object": "feature_flag",
15
+ "id": "flag_01EHQMYV6MBK39QC5PZXHY59C6",
16
+ "name": "Beta Features",
17
+ "slug": "beta-features",
18
+ "description": null,
19
+ "created_at": "2024-01-01T00:00:00.000Z",
20
+ "updated_at": "2024-01-01T00:00:00.000Z"
21
+ },
22
+ {
23
+ "object": "feature_flag",
24
+ "id": "flag_01EHQMYV6MBK39QC5PZXHY59C7",
25
+ "name": "Premium Support",
26
+ "slug": "premium-support",
27
+ "description": "Access to premium support features",
28
+ "created_at": "2024-01-01T00:00:00.000Z",
29
+ "updated_at": "2024-01-01T00:00:00.000Z"
30
+ }
31
+ ],
32
+ "list_metadata": {}
33
+ }
@@ -11,7 +11,8 @@
11
11
  "updated_at": "2023-07-18T02:07:19.911Z",
12
12
  "email_verified": true,
13
13
  "profile_picture_url": "https://example.com/profile_picture.jpg",
14
- "last_sign_in_at": "2023-07-18T02:07:19.911Z"
14
+ "last_sign_in_at": "2023-07-18T02:07:19.911Z",
15
+ "locale": "en-US"
15
16
  }
16
17
  ],
17
18
  "list_metadata": {
@@ -9,5 +9,6 @@
9
9
  "email_verified": true,
10
10
  "profile_picture_url": "https://example.com/profile_picture.jpg",
11
11
  "last_sign_in_at": "2023-07-18T02:07:19.911Z",
12
+ "locale": "en-US",
12
13
  "metadata": { "key": "value" }
13
14
  }
@@ -9,6 +9,7 @@ export interface AccessToken {
9
9
  sid: string;
10
10
  org_id?: string;
11
11
  role?: string;
12
+ roles?: string[];
12
13
  permissions?: string[];
13
14
  entitlements?: string[];
14
15
  feature_flags?: string[];
@@ -28,6 +29,7 @@ export type AuthenticateWithSessionCookieSuccessResponse = {
28
29
  sessionId: string;
29
30
  organizationId?: string;
30
31
  role?: string;
32
+ roles?: string[];
31
33
  permissions?: string[];
32
34
  entitlements?: string[];
33
35
  featureFlags?: string[];
@@ -1,7 +1,7 @@
1
1
  import { Impersonator, ImpersonatorResponse } from './impersonator.interface';
2
2
  import { OauthTokens, OauthTokensResponse } from './oauth-tokens.interface';
3
3
  import { User, UserResponse } from './user.interface';
4
- type AuthenticationMethod = 'SSO' | 'Password' | 'Passkey' | 'AppleOAuth' | 'GitHubOAuth' | 'GoogleOAuth' | 'MicrosoftOAuth' | 'MagicAuth' | 'Impersonation';
4
+ type AuthenticationMethod = 'SSO' | 'Password' | 'Passkey' | 'AppleOAuth' | 'GitHubOAuth' | 'GoogleOAuth' | 'MicrosoftOAuth' | 'SalesforceOAuth' | 'MagicAuth' | 'Impersonation';
5
5
  export interface AuthenticationResponse {
6
6
  user: User;
7
7
  organizationId?: string;
@@ -2,9 +2,11 @@ export interface CreateOrganizationMembershipOptions {
2
2
  organizationId: string;
3
3
  userId: string;
4
4
  roleSlug?: string;
5
+ roleSlugs?: string[];
5
6
  }
6
7
  export interface SerializedCreateOrganizationMembershipOptions {
7
8
  organization_id: string;
8
9
  user_id: string;
9
10
  role_slug?: string;
11
+ role_slugs?: string[];
10
12
  }
@@ -1,10 +1,10 @@
1
1
  export interface Identity {
2
2
  idpId: string;
3
3
  type: 'OAuth';
4
- provider: 'AppleOAuth' | 'GoogleOAuth' | 'GitHubOAuth' | 'MicrosoftOAuth';
4
+ provider: 'AppleOAuth' | 'GoogleOAuth' | 'GitHubOAuth' | 'MicrosoftOAuth' | 'SalesforceOAuth';
5
5
  }
6
6
  export interface IdentityResponse {
7
7
  idp_id: string;
8
8
  type: 'OAuth';
9
- provider: 'AppleOAuth' | 'GoogleOAuth' | 'GitHubOAuth' | 'MicrosoftOAuth';
9
+ provider: 'AppleOAuth' | 'GoogleOAuth' | 'GitHubOAuth' | 'MicrosoftOAuth' | 'SalesforceOAuth';
10
10
  }
@@ -26,6 +26,7 @@ export * from './list-auth-factors-options.interface';
26
26
  export * from './list-invitations-options.interface';
27
27
  export * from './list-organization-memberships-options.interface';
28
28
  export * from './list-sessions-options.interface';
29
+ export * from './list-user-feature-flags-options.interface';
29
30
  export * from './list-users-options.interface';
30
31
  export * from './magic-auth.interface';
31
32
  export * from './oauth-tokens.interface';
@@ -42,6 +42,7 @@ __exportStar(require("./list-auth-factors-options.interface"), exports);
42
42
  __exportStar(require("./list-invitations-options.interface"), exports);
43
43
  __exportStar(require("./list-organization-memberships-options.interface"), exports);
44
44
  __exportStar(require("./list-sessions-options.interface"), exports);
45
+ __exportStar(require("./list-user-feature-flags-options.interface"), exports);
45
46
  __exportStar(require("./list-users-options.interface"), exports);
46
47
  __exportStar(require("./magic-auth.interface"), exports);
47
48
  __exportStar(require("./oauth-tokens.interface"), exports);
@@ -0,0 +1,4 @@
1
+ import { PaginationOptions } from '../../common/interfaces';
2
+ export interface ListUserFeatureFlagsOptions extends PaginationOptions {
3
+ userId: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -10,6 +10,7 @@ export interface OrganizationMembership {
10
10
  createdAt: string;
11
11
  updatedAt: string;
12
12
  role: RoleResponse;
13
+ roles?: RoleResponse[];
13
14
  }
14
15
  export interface OrganizationMembershipResponse {
15
16
  object: 'organization_membership';
@@ -21,4 +22,5 @@ export interface OrganizationMembershipResponse {
21
22
  created_at: string;
22
23
  updated_at: string;
23
24
  role: RoleResponse;
25
+ roles?: RoleResponse[];
24
26
  }
@@ -1,6 +1,8 @@
1
1
  export interface UpdateOrganizationMembershipOptions {
2
2
  roleSlug?: string;
3
+ roleSlugs?: string[];
3
4
  }
4
5
  export interface SerializedUpdateOrganizationMembershipOptions {
5
6
  role_slug?: string;
7
+ role_slugs?: string[];
6
8
  }
@@ -9,6 +9,7 @@ export interface UpdateUserOptions {
9
9
  passwordHash?: string;
10
10
  passwordHashType?: PasswordHashType;
11
11
  externalId?: string;
12
+ locale?: string;
12
13
  metadata?: Record<string, string | null>;
13
14
  }
14
15
  export interface SerializedUpdateUserOptions {
@@ -20,5 +21,6 @@ export interface SerializedUpdateUserOptions {
20
21
  password_hash?: string;
21
22
  password_hash_type?: PasswordHashType;
22
23
  external_id?: string;
24
+ locale?: string;
23
25
  metadata?: Record<string, string | null>;
24
26
  }
@@ -7,6 +7,7 @@ export interface User {
7
7
  firstName: string | null;
8
8
  lastName: string | null;
9
9
  lastSignInAt: string | null;
10
+ locale: string | null;
10
11
  createdAt: string;
11
12
  updatedAt: string;
12
13
  externalId: string | null;
@@ -21,6 +22,7 @@ export interface UserResponse {
21
22
  first_name: string | null;
22
23
  last_name: string | null;
23
24
  last_sign_in_at: string | null;
25
+ locale: string | null;
24
26
  created_at: string;
25
27
  updated_at: string;
26
28
  external_id?: string;
@@ -5,5 +5,6 @@ const serializeCreateOrganizationMembershipOptions = (options) => ({
5
5
  organization_id: options.organizationId,
6
6
  user_id: options.userId,
7
7
  role_slug: options.roleSlug,
8
+ role_slugs: options.roleSlugs,
8
9
  });
9
10
  exports.serializeCreateOrganizationMembershipOptions = serializeCreateOrganizationMembershipOptions;
@@ -1,15 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deserializeOrganizationMembership = void 0;
4
- const deserializeOrganizationMembership = (organizationMembership) => ({
5
- object: organizationMembership.object,
6
- id: organizationMembership.id,
7
- userId: organizationMembership.user_id,
8
- organizationId: organizationMembership.organization_id,
9
- organizationName: organizationMembership.organization_name,
10
- status: organizationMembership.status,
11
- createdAt: organizationMembership.created_at,
12
- updatedAt: organizationMembership.updated_at,
13
- role: organizationMembership.role,
14
- });
4
+ const deserializeOrganizationMembership = (organizationMembership) => (Object.assign({ object: organizationMembership.object, id: organizationMembership.id, userId: organizationMembership.user_id, organizationId: organizationMembership.organization_id, organizationName: organizationMembership.organization_name, status: organizationMembership.status, createdAt: organizationMembership.created_at, updatedAt: organizationMembership.updated_at, role: organizationMembership.role }, (organizationMembership.roles && { roles: organizationMembership.roles })));
15
5
  exports.deserializeOrganizationMembership = deserializeOrganizationMembership;
@@ -3,5 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.serializeUpdateOrganizationMembershipOptions = void 0;
4
4
  const serializeUpdateOrganizationMembershipOptions = (options) => ({
5
5
  role_slug: options.roleSlug,
6
+ role_slugs: options.roleSlugs,
6
7
  });
7
8
  exports.serializeUpdateOrganizationMembershipOptions = serializeUpdateOrganizationMembershipOptions;
@@ -10,6 +10,7 @@ const serializeUpdateUserOptions = (options) => ({
10
10
  password_hash: options.passwordHash,
11
11
  password_hash_type: options.passwordHashType,
12
12
  external_id: options.externalId,
13
+ locale: options.locale,
13
14
  metadata: options.metadata,
14
15
  });
15
16
  exports.serializeUpdateUserOptions = serializeUpdateUserOptions;
@@ -12,6 +12,7 @@ const deserializeUser = (user) => {
12
12
  profilePictureUrl: user.profile_picture_url,
13
13
  lastName: user.last_name,
14
14
  lastSignInAt: user.last_sign_in_at,
15
+ locale: user.locale,
15
16
  createdAt: user.created_at,
16
17
  updatedAt: user.updated_at,
17
18
  externalId: (_a = user.external_id) !== null && _a !== void 0 ? _a : null,
@@ -61,12 +61,13 @@ class CookieSession {
61
61
  reason: interfaces_1.AuthenticateWithSessionCookieFailureReason.INVALID_JWT,
62
62
  };
63
63
  }
64
- const { sid: sessionId, org_id: organizationId, role, permissions, entitlements, feature_flags: featureFlags, } = (0, jose_1.decodeJwt)(session.accessToken);
64
+ const { sid: sessionId, org_id: organizationId, role, roles, permissions, entitlements, feature_flags: featureFlags, } = (0, jose_1.decodeJwt)(session.accessToken);
65
65
  return {
66
66
  authenticated: true,
67
67
  sessionId,
68
68
  organizationId,
69
69
  role,
70
+ roles,
70
71
  permissions,
71
72
  entitlements,
72
73
  featureFlags,
@@ -114,7 +115,7 @@ class CookieSession {
114
115
  this.cookiePassword = options.cookiePassword;
115
116
  }
116
117
  this.sessionData = authenticationResponse.sealedSession;
117
- const { sid: sessionId, org_id: organizationId, role, permissions, entitlements, feature_flags: featureFlags, } = (0, jose_1.decodeJwt)(authenticationResponse.accessToken);
118
+ const { sid: sessionId, org_id: organizationId, role, roles, permissions, entitlements, feature_flags: featureFlags, } = (0, jose_1.decodeJwt)(authenticationResponse.accessToken);
118
119
  // TODO: Returning `session` here means there's some duplicated data.
119
120
  // Slim down the return type in a future major version.
120
121
  return {
@@ -124,6 +125,7 @@ class CookieSession {
124
125
  sessionId,
125
126
  organizationId,
126
127
  role,
128
+ roles,
127
129
  permissions,
128
130
  entitlements,
129
131
  featureFlags,
@@ -119,7 +119,7 @@ describe('Session', () => {
119
119
  .spyOn(jose, 'jwtVerify')
120
120
  .mockResolvedValue({});
121
121
  const cookiePassword = 'alongcookiesecretmadefortestingsessions';
122
- const accessToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoZW50aWNhdGVkIjp0cnVlLCJpbXBlcnNvbmF0b3IiOnsiZW1haWwiOiJhZG1pbkBleGFtcGxlLmNvbSIsInJlYXNvbiI6InRlc3QifSwic2lkIjoic2Vzc2lvbl8xMjMiLCJvcmdfaWQiOiJvcmdfMTIzIiwicm9sZSI6Im1lbWJlciIsInBlcm1pc3Npb25zIjpbInBvc3RzOmNyZWF0ZSIsInBvc3RzOmRlbGV0ZSJdLCJlbnRpdGxlbWVudHMiOlsiYXVkaXQtbG9ncyJdLCJmZWF0dXJlX2ZsYWdzIjpbImRhcmstbW9kZSIsImJldGEtZmVhdHVyZXMiXSwidXNlciI6eyJvYmplY3QiOiJ1c2VyIiwiaWQiOiJ1c2VyXzAxSDVKUURWN1I3QVRFWVpERUcwVzVQUllTIiwiZW1haWwiOiJ0ZXN0QGV4YW1wbGUuY29tIn19.YVNjR8S2xGn2jAoLuEcBQNJ1_xY3OzjRE1-BK0zjfQE';
122
+ const accessToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoZW50aWNhdGVkIjp0cnVlLCJpbXBlcnNvbmF0b3IiOnsiZW1haWwiOiJhZG1pbkBleGFtcGxlLmNvbSIsInJlYXNvbiI6InRlc3QifSwic2lkIjoic2Vzc2lvbl8xMjMiLCJvcmdfaWQiOiJvcmdfMTIzIiwicm9sZSI6Im1lbWJlciIsInJvbGVzIjpbIm1lbWJlciIsImFkbWluIl0sInBlcm1pc3Npb25zIjpbInBvc3RzOmNyZWF0ZSIsInBvc3RzOmRlbGV0ZSJdLCJlbnRpdGxlbWVudHMiOlsiYXVkaXQtbG9ncyJdLCJmZWF0dXJlX2ZsYWdzIjpbImRhcmstbW9kZSIsImJldGEtZmVhdHVyZXMiXSwidXNlciI6eyJvYmplY3QiOiJ1c2VyIiwiaWQiOiJ1c2VyXzAxSDVKUURWN1I3QVRFWVpERUcwVzVQUllTIiwiZW1haWwiOiJ0ZXN0QGV4YW1wbGUuY29tIn19.TNUzJYn6lzLWFFsiWiKEgIshyUs-bKJQf1VxwNr1cGI';
123
123
  const sessionData = yield (0, iron_session_1.sealData)({
124
124
  accessToken,
125
125
  refreshToken: 'def456',
@@ -146,6 +146,7 @@ describe('Session', () => {
146
146
  sessionId: 'session_123',
147
147
  organizationId: 'org_123',
148
148
  role: 'member',
149
+ roles: ['member', 'admin'],
149
150
  permissions: ['posts:create', 'posts:delete'],
150
151
  entitlements: ['audit-logs'],
151
152
  featureFlags: ['dark-mode', 'beta-features'],
@@ -173,7 +174,7 @@ describe('Session', () => {
173
174
  }));
174
175
  describe('when the session data is valid', () => {
175
176
  it('returns a successful response with a sealed and unsealed session', () => __awaiter(void 0, void 0, void 0, function* () {
176
- const accessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJzdWIiOiAiMTIzNDU2Nzg5MCIsCiAgIm5hbWUiOiAiSm9obiBEb2UiLAogICJpYXQiOiAxNTE2MjM5MDIyLAogICJzaWQiOiAic2Vzc2lvbl8xMjMiLAogICJvcmdfaWQiOiAib3JnXzEyMyIsCiAgInJvbGUiOiAibWVtYmVyIiwKICAicGVybWlzc2lvbnMiOiBbInBvc3RzOmNyZWF0ZSIsICJwb3N0czpkZWxldGUiXQp9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c';
177
+ const accessToken = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyLCJzaWQiOiJzZXNzaW9uXzEyMyIsIm9yZ19pZCI6Im9yZ18xMjMiLCJyb2xlIjoibWVtYmVyIiwicm9sZXMiOlsibWVtYmVyIiwiYWRtaW4iXSwicGVybWlzc2lvbnMiOlsicG9zdHM6Y3JlYXRlIiwicG9zdHM6ZGVsZXRlIl19.N5zveP149QhRR5zNvzGJPiCX098uXaN8VM1_lwsMg4A';
177
178
  const refreshToken = 'def456';
178
179
  (0, test_utils_1.fetchOnce)({
179
180
  user: user_json_1.default,
@@ -216,6 +217,7 @@ describe('Session', () => {
216
217
  entitlements: undefined,
217
218
  permissions: ['posts:create', 'posts:delete'],
218
219
  role: 'member',
220
+ roles: ['member', 'admin'],
219
221
  sessionId: 'session_123',
220
222
  user: expect.objectContaining({
221
223
  email: 'test01@example.com',
@@ -2,8 +2,9 @@ import { createRemoteJWKSet } from 'jose';
2
2
  import { IronSessionProvider } from '../common/iron-session/iron-session-provider';
3
3
  import { AutoPaginatable } from '../common/utils/pagination';
4
4
  import { Challenge } from '../mfa/interfaces';
5
+ import { FeatureFlag } from '../feature-flags/interfaces/feature-flag.interface';
5
6
  import { WorkOS } from '../workos';
6
- import { AuthenticateWithCodeOptions, AuthenticateWithCodeAndVerifierOptions, AuthenticateWithMagicAuthOptions, AuthenticateWithPasswordOptions, AuthenticateWithRefreshTokenOptions, AuthenticateWithTotpOptions, AuthenticationResponse, CreateMagicAuthOptions, CreatePasswordResetOptions, CreateUserOptions, EmailVerification, EnrollAuthFactorOptions, ListAuthFactorsOptions, ListSessionsOptions, ListUsersOptions, MagicAuth, PasswordReset, ResetPasswordOptions, SendMagicAuthCodeOptions, SendPasswordResetEmailOptions, SendVerificationEmailOptions, Session, UpdateUserOptions, User, VerifyEmailOptions } from './interfaces';
7
+ import { AuthenticateWithCodeOptions, AuthenticateWithCodeAndVerifierOptions, AuthenticateWithMagicAuthOptions, AuthenticateWithPasswordOptions, AuthenticateWithRefreshTokenOptions, AuthenticateWithTotpOptions, AuthenticationResponse, CreateMagicAuthOptions, CreatePasswordResetOptions, CreateUserOptions, EmailVerification, EnrollAuthFactorOptions, ListAuthFactorsOptions, ListSessionsOptions, ListUsersOptions, ListUserFeatureFlagsOptions, MagicAuth, PasswordReset, ResetPasswordOptions, SendMagicAuthCodeOptions, SendPasswordResetEmailOptions, SendVerificationEmailOptions, Session, UpdateUserOptions, User, VerifyEmailOptions } from './interfaces';
7
8
  import { AuthenticateWithEmailVerificationOptions } from './interfaces/authenticate-with-email-verification-options.interface';
8
9
  import { AuthenticateWithOrganizationSelectionOptions } from './interfaces/authenticate-with-organization-selection.interface';
9
10
  import { AuthenticateWithSessionCookieFailedResponse, AuthenticateWithSessionCookieOptions, AuthenticateWithSessionCookieSuccessResponse, SessionCookieData } from './interfaces/authenticate-with-session-cookie.interface';
@@ -91,6 +92,7 @@ export declare class UserManagement {
91
92
  authenticationChallenge: Challenge;
92
93
  }>;
93
94
  listAuthFactors(options: ListAuthFactorsOptions): Promise<AutoPaginatable<Factor>>;
95
+ listUserFeatureFlags(options: ListUserFeatureFlagsOptions): Promise<AutoPaginatable<FeatureFlag>>;
94
96
  listSessions(userId: string, options?: ListSessionsOptions): Promise<AutoPaginatable<Session>>;
95
97
  deleteUser(userId: string): Promise<void>;
96
98
  getUserIdentities(userId: string): Promise<Identity[]>;
@@ -30,6 +30,7 @@ const oauth_exception_1 = require("../common/exceptions/oauth.exception");
30
30
  const fetch_and_deserialize_1 = require("../common/utils/fetch-and-deserialize");
31
31
  const pagination_1 = require("../common/utils/pagination");
32
32
  const serializers_1 = require("../mfa/serializers");
33
+ const feature_flag_serializer_1 = require("../feature-flags/serializers/feature-flag.serializer");
33
34
  const authenticate_with_session_cookie_interface_1 = require("./interfaces/authenticate-with-session-cookie.interface");
34
35
  const refresh_and_seal_session_data_interface_1 = require("./interfaces/refresh-and-seal-session-data.interface");
35
36
  const revoke_session_options_interface_1 = require("./interfaces/revoke-session-options.interface");
@@ -217,12 +218,13 @@ class UserManagement {
217
218
  reason: authenticate_with_session_cookie_interface_1.AuthenticateWithSessionCookieFailureReason.INVALID_JWT,
218
219
  };
219
220
  }
220
- const { sid: sessionId, org_id: organizationId, role, permissions, entitlements, feature_flags: featureFlags, } = (0, jose_1.decodeJwt)(session.accessToken);
221
+ const { sid: sessionId, org_id: organizationId, role, roles, permissions, entitlements, feature_flags: featureFlags, } = (0, jose_1.decodeJwt)(session.accessToken);
221
222
  return {
222
223
  authenticated: true,
223
224
  sessionId,
224
225
  organizationId,
225
226
  role,
227
+ roles,
226
228
  user: session.user,
227
229
  permissions,
228
230
  entitlements,
@@ -434,6 +436,12 @@ class UserManagement {
434
436
  return new pagination_1.AutoPaginatable(yield (0, fetch_and_deserialize_1.fetchAndDeserialize)(this.workos, `/user_management/users/${userId}/auth_factors`, factor_serializer_1.deserializeFactor, restOfOptions), (params) => (0, fetch_and_deserialize_1.fetchAndDeserialize)(this.workos, `/user_management/users/${userId}/auth_factors`, factor_serializer_1.deserializeFactor, params), restOfOptions);
435
437
  });
436
438
  }
439
+ listUserFeatureFlags(options) {
440
+ return __awaiter(this, void 0, void 0, function* () {
441
+ const { userId } = options, paginationOptions = __rest(options, ["userId"]);
442
+ return new pagination_1.AutoPaginatable(yield (0, fetch_and_deserialize_1.fetchAndDeserialize)(this.workos, `/user_management/users/${userId}/feature-flags`, feature_flag_serializer_1.deserializeFeatureFlag, paginationOptions), (params) => (0, fetch_and_deserialize_1.fetchAndDeserialize)(this.workos, `/user_management/users/${userId}/feature-flags`, feature_flag_serializer_1.deserializeFeatureFlag, params), paginationOptions);
443
+ });
444
+ }
437
445
  listSessions(userId, options) {
438
446
  return __awaiter(this, void 0, void 0, function* () {
439
447
  return new pagination_1.AutoPaginatable(yield (0, fetch_and_deserialize_1.fetchAndDeserialize)(this.workos, `/user_management/users/${userId}/sessions`, serializers_2.deserializeSession, options ? (0, serializers_2.serializeListSessionsOptions)(options) : undefined), (params) => (0, fetch_and_deserialize_1.fetchAndDeserialize)(this.workos, `/user_management/users/${userId}/sessions`, serializers_2.deserializeSession, params), options ? (0, serializers_2.serializeListSessionsOptions)(options) : undefined);
@@ -45,6 +45,7 @@ const list_factors_json_1 = __importDefault(require("./fixtures/list-factors.jso
45
45
  const list_invitations_json_1 = __importDefault(require("./fixtures/list-invitations.json"));
46
46
  const list_organization_memberships_json_1 = __importDefault(require("./fixtures/list-organization-memberships.json"));
47
47
  const list_sessions_json_1 = __importDefault(require("./fixtures/list-sessions.json"));
48
+ const list_user_feature_flags_json_1 = __importDefault(require("./fixtures/list-user-feature-flags.json"));
48
49
  const list_users_json_1 = __importDefault(require("./fixtures/list-users.json"));
49
50
  const magic_auth_json_1 = __importDefault(require("./fixtures/magic_auth.json"));
50
51
  const organization_membership_json_1 = __importDefault(require("./fixtures/organization-membership.json"));
@@ -83,6 +84,7 @@ describe('UserManagement', () => {
83
84
  lastName: 'User',
84
85
  emailVerified: true,
85
86
  lastSignInAt: '2023-07-18T02:07:19.911Z',
87
+ locale: 'en-US',
86
88
  });
87
89
  }));
88
90
  });
@@ -101,6 +103,7 @@ describe('UserManagement', () => {
101
103
  lastName: 'User',
102
104
  emailVerified: true,
103
105
  lastSignInAt: '2023-07-18T02:07:19.911Z',
106
+ locale: 'en-US',
104
107
  externalId,
105
108
  });
106
109
  }));
@@ -889,6 +892,39 @@ describe('UserManagement', () => {
889
892
  accessToken,
890
893
  });
891
894
  }));
895
+ it('returns the JWT claims when provided a valid JWT with multiple roles', () => __awaiter(void 0, void 0, void 0, function* () {
896
+ jest
897
+ .spyOn(jose, 'jwtVerify')
898
+ .mockResolvedValue({});
899
+ const cookiePassword = 'alongcookiesecretmadefortestingsessions';
900
+ const accessToken = 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJhdXRoZW50aWNhdGVkIjp0cnVlLCJpbXBlcnNvbmF0b3IiOnsiZW1haWwiOiJhZG1pbkBleGFtcGxlLmNvbSIsInJlYXNvbiI6InRlc3QifSwic2lkIjoic2Vzc2lvbl8xMjMiLCJvcmdfaWQiOiJvcmdfMTIzIiwicm9sZSI6ImFkbWluIiwicm9sZXMiOlsiYWRtaW4iLCJtZW1iZXIiXSwicGVybWlzc2lvbnMiOlsicG9zdHM6Y3JlYXRlIiwicG9zdHM6ZGVsZXRlIl0sImVudGl0bGVtZW50cyI6WyJhdWRpdC1sb2dzIl0sImZlYXR1cmVfZmxhZ3MiOlsiZGFyay1tb2RlIiwiYmV0YS1mZWF0dXJlcyJdLCJ1c2VyIjp7Im9iamVjdCI6InVzZXIiLCJpZCI6InVzZXJfMDFINUpRRFY3UjdBVEVZWkRFRzBXNVBSWVMiLCJlbWFpbCI6InRlc3RAZXhhbXBsZS5jb20ifX0.hsMptIB7PmbF5pxxtgTtCdUyOAhA11ZIAP-JY5zU5fE';
901
+ const sessionData = yield (0, iron_session_1.sealData)({
902
+ accessToken,
903
+ refreshToken: 'def456',
904
+ user: {
905
+ object: 'user',
906
+ id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS',
907
+ email: 'test@example.com',
908
+ },
909
+ }, { password: cookiePassword });
910
+ yield expect(workos.userManagement.authenticateWithSessionCookie({
911
+ sessionData,
912
+ cookiePassword,
913
+ })).resolves.toEqual({
914
+ authenticated: true,
915
+ sessionId: 'session_123',
916
+ organizationId: 'org_123',
917
+ role: 'admin',
918
+ roles: ['admin', 'member'],
919
+ permissions: ['posts:create', 'posts:delete'],
920
+ entitlements: ['audit-logs'],
921
+ featureFlags: ['dark-mode', 'beta-features'],
922
+ user: expect.objectContaining({
923
+ email: 'test@example.com',
924
+ }),
925
+ accessToken,
926
+ });
927
+ }));
892
928
  });
893
929
  describe('refreshAndSealSessionData', () => {
894
930
  it('throws an error when the cookie password is undefined', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -1208,6 +1244,21 @@ describe('UserManagement', () => {
1208
1244
  metadata: {},
1209
1245
  });
1210
1246
  }));
1247
+ it('updates user locale', () => __awaiter(void 0, void 0, void 0, function* () {
1248
+ (0, test_utils_1.fetchOnce)(user_json_1.default);
1249
+ const resp = yield workos.userManagement.updateUser({
1250
+ userId,
1251
+ locale: 'en-US',
1252
+ });
1253
+ expect((0, test_utils_1.fetchURL)()).toContain(`/user_management/users/${userId}`);
1254
+ expect((0, test_utils_1.fetchBody)()).toEqual({
1255
+ locale: 'en-US',
1256
+ });
1257
+ expect(resp).toMatchObject({
1258
+ id: userId,
1259
+ locale: 'en-US',
1260
+ });
1261
+ }));
1211
1262
  });
1212
1263
  describe('enrollAuthFactor', () => {
1213
1264
  it('sends an enrollAuthFactor request', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -1298,6 +1349,90 @@ describe('UserManagement', () => {
1298
1349
  });
1299
1350
  }));
1300
1351
  });
1352
+ describe('listUserFeatureFlags', () => {
1353
+ it('returns feature flags for the user', () => __awaiter(void 0, void 0, void 0, function* () {
1354
+ (0, test_utils_1.fetchOnce)(list_user_feature_flags_json_1.default);
1355
+ const { data, object, listMetadata } = yield workos.userManagement.listUserFeatureFlags({ userId });
1356
+ expect((0, test_utils_1.fetchURL)()).toContain(`/user_management/users/${userId}/feature-flags`);
1357
+ expect(object).toEqual('list');
1358
+ expect(listMetadata).toEqual({});
1359
+ expect(data).toHaveLength(3);
1360
+ expect(data).toEqual([
1361
+ {
1362
+ object: 'feature_flag',
1363
+ id: 'flag_01EHQMYV6MBK39QC5PZXHY59C5',
1364
+ name: 'Advanced Dashboard',
1365
+ slug: 'advanced-dashboard',
1366
+ description: 'Enable advanced dashboard features',
1367
+ createdAt: '2024-01-01T00:00:00.000Z',
1368
+ updatedAt: '2024-01-01T00:00:00.000Z',
1369
+ },
1370
+ {
1371
+ object: 'feature_flag',
1372
+ id: 'flag_01EHQMYV6MBK39QC5PZXHY59C6',
1373
+ name: 'Beta Features',
1374
+ slug: 'beta-features',
1375
+ description: null,
1376
+ createdAt: '2024-01-01T00:00:00.000Z',
1377
+ updatedAt: '2024-01-01T00:00:00.000Z',
1378
+ },
1379
+ {
1380
+ object: 'feature_flag',
1381
+ id: 'flag_01EHQMYV6MBK39QC5PZXHY59C7',
1382
+ name: 'Premium Support',
1383
+ slug: 'premium-support',
1384
+ description: 'Access to premium support features',
1385
+ createdAt: '2024-01-01T00:00:00.000Z',
1386
+ updatedAt: '2024-01-01T00:00:00.000Z',
1387
+ },
1388
+ ]);
1389
+ }));
1390
+ describe('with the before option', () => {
1391
+ it('forms the proper request to the API', () => __awaiter(void 0, void 0, void 0, function* () {
1392
+ (0, test_utils_1.fetchOnce)(list_user_feature_flags_json_1.default);
1393
+ const { data } = yield workos.userManagement.listUserFeatureFlags({
1394
+ userId,
1395
+ before: 'flag_before_id',
1396
+ });
1397
+ expect((0, test_utils_1.fetchSearchParams)()).toEqual({
1398
+ before: 'flag_before_id',
1399
+ order: 'desc',
1400
+ });
1401
+ expect((0, test_utils_1.fetchURL)()).toContain(`/user_management/users/${userId}/feature-flags`);
1402
+ expect(data).toHaveLength(3);
1403
+ }));
1404
+ });
1405
+ describe('with the after option', () => {
1406
+ it('forms the proper request to the API', () => __awaiter(void 0, void 0, void 0, function* () {
1407
+ (0, test_utils_1.fetchOnce)(list_user_feature_flags_json_1.default);
1408
+ const { data } = yield workos.userManagement.listUserFeatureFlags({
1409
+ userId,
1410
+ after: 'flag_after_id',
1411
+ });
1412
+ expect((0, test_utils_1.fetchSearchParams)()).toEqual({
1413
+ after: 'flag_after_id',
1414
+ order: 'desc',
1415
+ });
1416
+ expect((0, test_utils_1.fetchURL)()).toContain(`/user_management/users/${userId}/feature-flags`);
1417
+ expect(data).toHaveLength(3);
1418
+ }));
1419
+ });
1420
+ describe('with the limit option', () => {
1421
+ it('forms the proper request to the API', () => __awaiter(void 0, void 0, void 0, function* () {
1422
+ (0, test_utils_1.fetchOnce)(list_user_feature_flags_json_1.default);
1423
+ const { data } = yield workos.userManagement.listUserFeatureFlags({
1424
+ userId,
1425
+ limit: 3,
1426
+ });
1427
+ expect((0, test_utils_1.fetchSearchParams)()).toEqual({
1428
+ limit: '3',
1429
+ order: 'desc',
1430
+ });
1431
+ expect((0, test_utils_1.fetchURL)()).toContain(`/user_management/users/${userId}/feature-flags`);
1432
+ expect(data).toHaveLength(3);
1433
+ }));
1434
+ });
1435
+ });
1301
1436
  describe('listSessions', () => {
1302
1437
  it('sends a listSessions request', () => __awaiter(void 0, void 0, void 0, function* () {
1303
1438
  (0, test_utils_1.fetchOnce)(list_sessions_json_1.default);
package/lib/workos.js CHANGED
@@ -32,7 +32,7 @@ const actions_1 = require("./actions/actions");
32
32
  const vault_1 = require("./vault/vault");
33
33
  const conflict_exception_1 = require("./common/exceptions/conflict.exception");
34
34
  const parse_error_1 = require("./common/exceptions/parse-error");
35
- const VERSION = '7.69.2';
35
+ const VERSION = '7.71.0';
36
36
  const DEFAULT_HOSTNAME = 'api.workos.com';
37
37
  const HEADER_AUTHORIZATION = 'Authorization';
38
38
  const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "7.69.2",
2
+ "version": "7.71.0",
3
3
  "name": "@workos-inc/node",
4
4
  "author": "WorkOS",
5
5
  "description": "A Node wrapper for the WorkOS API",