@workos-inc/node 7.75.0 → 7.76.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.
- package/lib/audit-logs/audit-logs.js +2 -2
- package/lib/common/crypto/crypto-provider.d.ts +6 -0
- package/lib/common/crypto/crypto-provider.spec.js +37 -0
- package/lib/common/crypto/node-crypto-provider.d.ts +1 -0
- package/lib/common/crypto/node-crypto-provider.js +3 -0
- package/lib/common/crypto/subtle-crypto-provider.d.ts +1 -0
- package/lib/common/crypto/subtle-crypto-provider.js +14 -0
- package/lib/directory-sync/directory-sync.spec.js +5 -3
- package/lib/directory-sync/interfaces/directory-user.interface.d.ts +2 -0
- package/lib/directory-sync/serializers/directory-user.serializer.js +2 -0
- package/lib/sso/interfaces/profile.interface.d.ts +2 -0
- package/lib/sso/serializers/profile.serializer.js +1 -0
- package/lib/sso/sso.spec.js +5 -0
- package/lib/workos.js +1 -1
- package/package.json +1 -1
|
@@ -10,7 +10,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
10
10
|
};
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.AuditLogs = void 0;
|
|
13
|
-
const crypto_1 = require("crypto");
|
|
14
13
|
const serializers_1 = require("./serializers");
|
|
15
14
|
class AuditLogs {
|
|
16
15
|
constructor(workos) {
|
|
@@ -19,7 +18,8 @@ class AuditLogs {
|
|
|
19
18
|
createEvent(organization, event, options = {}) {
|
|
20
19
|
return __awaiter(this, void 0, void 0, function* () {
|
|
21
20
|
// Auto-generate idempotency key if not provided
|
|
22
|
-
const optionsWithIdempotency = Object.assign(Object.assign({}, options), { idempotencyKey: options.idempotencyKey ||
|
|
21
|
+
const optionsWithIdempotency = Object.assign(Object.assign({}, options), { idempotencyKey: options.idempotencyKey ||
|
|
22
|
+
`workos-node-${this.workos.getCryptoProvider().randomUUID()}` });
|
|
23
23
|
yield this.workos.post('/audit_logs/events', {
|
|
24
24
|
event: (0, serializers_1.serializeCreateAuditLogEventOptions)(event),
|
|
25
25
|
organization_id: organization,
|
|
@@ -62,4 +62,10 @@ export declare abstract class CryptoProvider {
|
|
|
62
62
|
* @returns A Uint8Array containing the random bytes
|
|
63
63
|
*/
|
|
64
64
|
abstract randomBytes(length: number): Uint8Array;
|
|
65
|
+
/**
|
|
66
|
+
* Generates a random UUID v4 string.
|
|
67
|
+
*
|
|
68
|
+
* @returns A UUID v4 string in the format xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
|
|
69
|
+
*/
|
|
70
|
+
abstract randomUUID(): string;
|
|
65
71
|
}
|
|
@@ -54,4 +54,41 @@ describe('CryptoProvider', () => {
|
|
|
54
54
|
expect(nodeCryptoProvider.secureCompare(signature, 'foo')).toEqual(subtleCryptoProvider.secureCompare(signature, 'foo'));
|
|
55
55
|
}));
|
|
56
56
|
});
|
|
57
|
+
describe('when generating UUIDs', () => {
|
|
58
|
+
const UUID_V4_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
59
|
+
it('generates valid UUID v4 format for NodeCryptoProvider', () => {
|
|
60
|
+
const nodeCryptoProvider = new node_crypto_provider_1.NodeCryptoProvider();
|
|
61
|
+
const uuid = nodeCryptoProvider.randomUUID();
|
|
62
|
+
expect(uuid).toMatch(UUID_V4_REGEX);
|
|
63
|
+
});
|
|
64
|
+
it('generates valid UUID v4 format for SubtleCryptoProvider', () => {
|
|
65
|
+
const subtleCryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
|
|
66
|
+
const uuid = subtleCryptoProvider.randomUUID();
|
|
67
|
+
expect(uuid).toMatch(UUID_V4_REGEX);
|
|
68
|
+
});
|
|
69
|
+
it('generates unique UUIDs', () => {
|
|
70
|
+
const nodeCryptoProvider = new node_crypto_provider_1.NodeCryptoProvider();
|
|
71
|
+
const subtleCryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
|
|
72
|
+
const uuids = new Set([
|
|
73
|
+
nodeCryptoProvider.randomUUID(),
|
|
74
|
+
nodeCryptoProvider.randomUUID(),
|
|
75
|
+
subtleCryptoProvider.randomUUID(),
|
|
76
|
+
subtleCryptoProvider.randomUUID(),
|
|
77
|
+
]);
|
|
78
|
+
expect(uuids.size).toBe(4);
|
|
79
|
+
});
|
|
80
|
+
it('SubtleCryptoProvider falls back when crypto.randomUUID is unavailable', () => {
|
|
81
|
+
const originalRandomUUID = globalThis.crypto.randomUUID;
|
|
82
|
+
// @ts-ignore - intentionally removing for test
|
|
83
|
+
delete globalThis.crypto.randomUUID;
|
|
84
|
+
try {
|
|
85
|
+
const subtleCryptoProvider = new subtle_crypto_provider_1.SubtleCryptoProvider();
|
|
86
|
+
const uuid = subtleCryptoProvider.randomUUID();
|
|
87
|
+
expect(uuid).toMatch(UUID_V4_REGEX);
|
|
88
|
+
}
|
|
89
|
+
finally {
|
|
90
|
+
globalThis.crypto.randomUUID = originalRandomUUID;
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
});
|
|
57
94
|
});
|
|
@@ -16,4 +16,5 @@ export declare class NodeCryptoProvider extends CryptoProvider {
|
|
|
16
16
|
}>;
|
|
17
17
|
decrypt(ciphertext: Uint8Array, key: Uint8Array, iv: Uint8Array, tag: Uint8Array, aad?: Uint8Array): Promise<Uint8Array>;
|
|
18
18
|
randomBytes(length: number): Uint8Array;
|
|
19
|
+
randomUUID(): string;
|
|
19
20
|
}
|
|
@@ -105,5 +105,8 @@ class NodeCryptoProvider extends crypto_provider_1.CryptoProvider {
|
|
|
105
105
|
randomBytes(length) {
|
|
106
106
|
return new Uint8Array(crypto.randomBytes(length));
|
|
107
107
|
}
|
|
108
|
+
randomUUID() {
|
|
109
|
+
return crypto.randomUUID();
|
|
110
|
+
}
|
|
108
111
|
}
|
|
109
112
|
exports.NodeCryptoProvider = NodeCryptoProvider;
|
|
@@ -19,4 +19,5 @@ export declare class SubtleCryptoProvider extends CryptoProvider {
|
|
|
19
19
|
}>;
|
|
20
20
|
decrypt(ciphertext: Uint8Array, key: Uint8Array, iv: Uint8Array, tag: Uint8Array, aad?: Uint8Array): Promise<Uint8Array>;
|
|
21
21
|
randomBytes(length: number): Uint8Array;
|
|
22
|
+
randomUUID(): string;
|
|
22
23
|
}
|
|
@@ -113,6 +113,20 @@ class SubtleCryptoProvider extends crypto_provider_1.CryptoProvider {
|
|
|
113
113
|
crypto.getRandomValues(bytes);
|
|
114
114
|
return bytes;
|
|
115
115
|
}
|
|
116
|
+
randomUUID() {
|
|
117
|
+
if (typeof crypto !== 'undefined' &&
|
|
118
|
+
typeof crypto.randomUUID === 'function') {
|
|
119
|
+
return crypto.randomUUID();
|
|
120
|
+
}
|
|
121
|
+
// Fallback for environments without crypto.randomUUID
|
|
122
|
+
const bytes = this.randomBytes(16);
|
|
123
|
+
// tslint:disable-next-line:no-bitwise
|
|
124
|
+
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
|
|
125
|
+
// tslint:disable-next-line:no-bitwise
|
|
126
|
+
bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant
|
|
127
|
+
const hex = Array.from(bytes, (b) => byteHexMapping[b]).join('');
|
|
128
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
129
|
+
}
|
|
116
130
|
}
|
|
117
131
|
exports.SubtleCryptoProvider = SubtleCryptoProvider;
|
|
118
132
|
// Cached mapping of byte to hex representation. We do this once to avoid re-
|
|
@@ -120,7 +120,7 @@ describe('DirectorySync', () => {
|
|
|
120
120
|
created_at: '2021-10-27 15:21:50.640959',
|
|
121
121
|
updated_at: '2021-12-13 12:15:45.531847',
|
|
122
122
|
};
|
|
123
|
-
const
|
|
123
|
+
const userWithRoles = {
|
|
124
124
|
object: 'directory_user',
|
|
125
125
|
id: 'directory_user_456',
|
|
126
126
|
customAttributes: {
|
|
@@ -145,6 +145,7 @@ describe('DirectorySync', () => {
|
|
|
145
145
|
state: 'active',
|
|
146
146
|
username: 'jonsnow',
|
|
147
147
|
role: { slug: 'super_admin' },
|
|
148
|
+
roles: [{ slug: 'super_admin' }],
|
|
148
149
|
createdAt: '2021-10-27 15:21:50.640959',
|
|
149
150
|
updatedAt: '2021-12-13 12:15:45.531847',
|
|
150
151
|
};
|
|
@@ -173,6 +174,7 @@ describe('DirectorySync', () => {
|
|
|
173
174
|
state: 'active',
|
|
174
175
|
username: 'jonsnow',
|
|
175
176
|
role: { slug: 'super_admin' },
|
|
177
|
+
roles: [{ slug: 'super_admin' }],
|
|
176
178
|
created_at: '2021-10-27 15:21:50.640959',
|
|
177
179
|
updated_at: '2021-12-13 12:15:45.531847',
|
|
178
180
|
};
|
|
@@ -409,11 +411,11 @@ describe('DirectorySync', () => {
|
|
|
409
411
|
const subject = yield workos.directorySync.getUser('dir_usr_123');
|
|
410
412
|
expect(subject).toEqual(userWithGroup);
|
|
411
413
|
}));
|
|
412
|
-
describe('with
|
|
414
|
+
describe('with roles', () => {
|
|
413
415
|
it(`requests a Directory User`, () => __awaiter(void 0, void 0, void 0, function* () {
|
|
414
416
|
(0, test_utils_1.fetchOnce)(userWithRoleResponse);
|
|
415
417
|
const subject = yield workos.directorySync.getUser('directory_user_456');
|
|
416
|
-
expect(subject).toEqual(
|
|
418
|
+
expect(subject).toEqual(userWithRoles);
|
|
417
419
|
}));
|
|
418
420
|
});
|
|
419
421
|
});
|
|
@@ -33,6 +33,7 @@ export interface DirectoryUser<TCustomAttributes extends object = DefaultCustomA
|
|
|
33
33
|
jobTitle: string | null;
|
|
34
34
|
state: 'active' | 'inactive';
|
|
35
35
|
role?: RoleResponse;
|
|
36
|
+
roles?: RoleResponse[];
|
|
36
37
|
createdAt: string;
|
|
37
38
|
updatedAt: string;
|
|
38
39
|
}
|
|
@@ -68,6 +69,7 @@ export interface DirectoryUserResponse<TCustomAttributes extends object = Defaul
|
|
|
68
69
|
job_title: string | null;
|
|
69
70
|
state: 'active' | 'inactive';
|
|
70
71
|
role?: RoleResponse;
|
|
72
|
+
roles?: RoleResponse[];
|
|
71
73
|
created_at: string;
|
|
72
74
|
updated_at: string;
|
|
73
75
|
}
|
|
@@ -18,6 +18,7 @@ const deserializeDirectoryUser = (directoryUser) => ({
|
|
|
18
18
|
jobTitle: directoryUser.job_title,
|
|
19
19
|
state: directoryUser.state,
|
|
20
20
|
role: directoryUser.role,
|
|
21
|
+
roles: directoryUser.roles,
|
|
21
22
|
createdAt: directoryUser.created_at,
|
|
22
23
|
updatedAt: directoryUser.updated_at,
|
|
23
24
|
});
|
|
@@ -40,6 +41,7 @@ const deserializeUpdatedEventDirectoryUser = (directoryUser) => ({
|
|
|
40
41
|
jobTitle: directoryUser.job_title,
|
|
41
42
|
state: directoryUser.state,
|
|
42
43
|
role: directoryUser.role,
|
|
44
|
+
roles: directoryUser.roles,
|
|
43
45
|
createdAt: directoryUser.created_at,
|
|
44
46
|
updatedAt: directoryUser.updated_at,
|
|
45
47
|
previousAttributes: directoryUser.previous_attributes,
|
|
@@ -11,6 +11,7 @@ export interface Profile<CustomAttributesType extends UnknownRecord> {
|
|
|
11
11
|
firstName?: string;
|
|
12
12
|
lastName?: string;
|
|
13
13
|
role?: RoleResponse;
|
|
14
|
+
roles?: RoleResponse[];
|
|
14
15
|
groups?: string[];
|
|
15
16
|
customAttributes?: CustomAttributesType;
|
|
16
17
|
rawAttributes?: {
|
|
@@ -27,6 +28,7 @@ export interface ProfileResponse<CustomAttributesType extends UnknownRecord> {
|
|
|
27
28
|
first_name?: string;
|
|
28
29
|
last_name?: string;
|
|
29
30
|
role?: RoleResponse;
|
|
31
|
+
roles?: RoleResponse[];
|
|
30
32
|
groups?: string[];
|
|
31
33
|
custom_attributes?: CustomAttributesType;
|
|
32
34
|
raw_attributes?: {
|
|
@@ -11,6 +11,7 @@ const deserializeProfile = (profile) => ({
|
|
|
11
11
|
firstName: profile.first_name,
|
|
12
12
|
lastName: profile.last_name,
|
|
13
13
|
role: profile.role,
|
|
14
|
+
roles: profile.roles,
|
|
14
15
|
groups: profile.groups,
|
|
15
16
|
customAttributes: profile.custom_attributes,
|
|
16
17
|
rawAttributes: profile.raw_attributes,
|
package/lib/sso/sso.spec.js
CHANGED
|
@@ -227,6 +227,7 @@ describe('SSO', () => {
|
|
|
227
227
|
role: {
|
|
228
228
|
slug: 'admin',
|
|
229
229
|
},
|
|
230
|
+
roles: [{ slug: 'admin' }],
|
|
230
231
|
groups: ['Admins', 'Developers'],
|
|
231
232
|
raw_attributes: {
|
|
232
233
|
email: 'foo@test.com',
|
|
@@ -268,6 +269,7 @@ describe('SSO', () => {
|
|
|
268
269
|
role: {
|
|
269
270
|
slug: 'admin',
|
|
270
271
|
},
|
|
272
|
+
roles: [{ slug: 'admin' }],
|
|
271
273
|
raw_attributes: {
|
|
272
274
|
email: 'foo@test.com',
|
|
273
275
|
first_name: 'foo',
|
|
@@ -304,6 +306,7 @@ describe('SSO', () => {
|
|
|
304
306
|
role: {
|
|
305
307
|
slug: 'admin',
|
|
306
308
|
},
|
|
309
|
+
roles: [{ slug: 'admin' }],
|
|
307
310
|
groups: ['Admins', 'Developers'],
|
|
308
311
|
raw_attributes: {
|
|
309
312
|
email: 'foo@test.com',
|
|
@@ -352,6 +355,7 @@ describe('SSO', () => {
|
|
|
352
355
|
role: {
|
|
353
356
|
slug: 'admin',
|
|
354
357
|
},
|
|
358
|
+
roles: [{ slug: 'admin' }],
|
|
355
359
|
raw_attributes: {
|
|
356
360
|
email: 'foo@test.com',
|
|
357
361
|
first_name: 'foo',
|
|
@@ -386,6 +390,7 @@ describe('SSO', () => {
|
|
|
386
390
|
role: {
|
|
387
391
|
slug: 'admin',
|
|
388
392
|
},
|
|
393
|
+
roles: [{ slug: 'admin' }],
|
|
389
394
|
groups: ['Admins', 'Developers'],
|
|
390
395
|
raw_attributes: {
|
|
391
396
|
email: 'foo@test.com',
|
package/lib/workos.js
CHANGED
|
@@ -33,7 +33,7 @@ const actions_1 = require("./actions/actions");
|
|
|
33
33
|
const vault_1 = require("./vault/vault");
|
|
34
34
|
const conflict_exception_1 = require("./common/exceptions/conflict.exception");
|
|
35
35
|
const parse_error_1 = require("./common/exceptions/parse-error");
|
|
36
|
-
const VERSION = '7.
|
|
36
|
+
const VERSION = '7.76.0';
|
|
37
37
|
const DEFAULT_HOSTNAME = 'api.workos.com';
|
|
38
38
|
const HEADER_AUTHORIZATION = 'Authorization';
|
|
39
39
|
const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
|
package/package.json
CHANGED