@workos-inc/node 7.19.0 → 7.21.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/organizations/interfaces/update-organization-options.interface.d.ts +2 -2
- package/lib/organizations/organizations.spec.js +0 -2
- package/lib/user-management/user-management.d.ts +7 -0
- package/lib/user-management/user-management.js +19 -0
- package/lib/user-management/user-management.spec.js +95 -0
- package/lib/workos.js +9 -4
- package/package.json +2 -2
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DomainData } from './domain-data.interface';
|
|
2
2
|
export interface UpdateOrganizationOptions {
|
|
3
3
|
organization: string;
|
|
4
|
-
name
|
|
4
|
+
name?: string;
|
|
5
5
|
domainData?: DomainData[];
|
|
6
6
|
/**
|
|
7
7
|
* @deprecated If you need to allow sign-ins from any email domain, contact support@workos.com.
|
|
@@ -13,7 +13,7 @@ export interface UpdateOrganizationOptions {
|
|
|
13
13
|
domains?: string[];
|
|
14
14
|
}
|
|
15
15
|
export interface SerializedUpdateOrganizationOptions {
|
|
16
|
-
name
|
|
16
|
+
name?: string;
|
|
17
17
|
domain_data?: DomainData[];
|
|
18
18
|
/**
|
|
19
19
|
* @deprecated If you need to allow sign-ins from any email domain, contact support@workos.com.
|
|
@@ -216,11 +216,9 @@ describe('Organizations', () => {
|
|
|
216
216
|
domainData: [
|
|
217
217
|
{ domain: 'example.com', state: interfaces_1.DomainDataState.Verified },
|
|
218
218
|
],
|
|
219
|
-
name: 'Test Organization 2',
|
|
220
219
|
});
|
|
221
220
|
expect((0, test_utils_1.fetchBody)()).toEqual({
|
|
222
221
|
domain_data: [{ domain: 'example.com', state: 'verified' }],
|
|
223
|
-
name: 'Test Organization 2',
|
|
224
222
|
});
|
|
225
223
|
expect(subject.id).toEqual('org_01EHT88Z8J8795GZNQ4ZP1J81T');
|
|
226
224
|
expect(subject.name).toEqual('Test Organization 2');
|
|
@@ -87,5 +87,12 @@ export declare class UserManagement {
|
|
|
87
87
|
getLogoutUrl({ sessionId }: {
|
|
88
88
|
sessionId: string;
|
|
89
89
|
}): string;
|
|
90
|
+
/**
|
|
91
|
+
* getLogoutUrlFromSessionCookie takes in session cookie data, unseals the cookie, decodes the JWT claims,
|
|
92
|
+
* and uses the session ID to generate the logout URL.
|
|
93
|
+
*
|
|
94
|
+
* Use this over `getLogoutUrl` if you'd like to the SDK to handle session cookies for you.
|
|
95
|
+
*/
|
|
96
|
+
getLogoutUrlFromSessionCookie({ sessionData, cookiePassword, }: SessionHandlerOptions): Promise<string>;
|
|
90
97
|
getJwksUrl(clientId: string): string;
|
|
91
98
|
}
|
|
@@ -500,6 +500,25 @@ class UserManagement {
|
|
|
500
500
|
}
|
|
501
501
|
return `${this.workos.baseURL}/user_management/sessions/logout?session_id=${sessionId}`;
|
|
502
502
|
}
|
|
503
|
+
/**
|
|
504
|
+
* getLogoutUrlFromSessionCookie takes in session cookie data, unseals the cookie, decodes the JWT claims,
|
|
505
|
+
* and uses the session ID to generate the logout URL.
|
|
506
|
+
*
|
|
507
|
+
* Use this over `getLogoutUrl` if you'd like to the SDK to handle session cookies for you.
|
|
508
|
+
*/
|
|
509
|
+
getLogoutUrlFromSessionCookie({ sessionData, cookiePassword = process.env.WORKOS_COOKIE_PASSWORD, }) {
|
|
510
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
511
|
+
const authenticationResponse = yield this.authenticateWithSessionCookie({
|
|
512
|
+
sessionData,
|
|
513
|
+
cookiePassword,
|
|
514
|
+
});
|
|
515
|
+
if (!authenticationResponse.authenticated) {
|
|
516
|
+
const { reason } = authenticationResponse;
|
|
517
|
+
throw new Error(`Failed to extract session ID for logout URL: ${reason}`);
|
|
518
|
+
}
|
|
519
|
+
return this.getLogoutUrl({ sessionId: authenticationResponse.sessionId });
|
|
520
|
+
});
|
|
521
|
+
}
|
|
503
522
|
getJwksUrl(clientId) {
|
|
504
523
|
if (!clientId) {
|
|
505
524
|
throw TypeError('clientId must be a valid clientId');
|
|
@@ -1536,6 +1536,101 @@ describe('UserManagement', () => {
|
|
|
1536
1536
|
expect(url).toBe('https://api.workos.com/user_management/sessions/logout?session_id=123456');
|
|
1537
1537
|
});
|
|
1538
1538
|
});
|
|
1539
|
+
describe('getLogoutUrlFromSessionCookie', () => {
|
|
1540
|
+
beforeEach(() => {
|
|
1541
|
+
// Mock createRemoteJWKSet
|
|
1542
|
+
jest
|
|
1543
|
+
.spyOn(jose, 'createRemoteJWKSet')
|
|
1544
|
+
.mockImplementation((_url, _options) => {
|
|
1545
|
+
// This function simulates the token verification process
|
|
1546
|
+
const verifyFunction = (_protectedHeader, _token) => {
|
|
1547
|
+
return Promise.resolve({
|
|
1548
|
+
type: 'public',
|
|
1549
|
+
});
|
|
1550
|
+
};
|
|
1551
|
+
// Return an object that includes the verify function and the additional expected properties
|
|
1552
|
+
return {
|
|
1553
|
+
__call__: verifyFunction,
|
|
1554
|
+
coolingDown: false,
|
|
1555
|
+
fresh: false,
|
|
1556
|
+
reloading: false,
|
|
1557
|
+
reload: jest.fn().mockResolvedValue(undefined),
|
|
1558
|
+
jwks: () => undefined,
|
|
1559
|
+
};
|
|
1560
|
+
});
|
|
1561
|
+
});
|
|
1562
|
+
it('throws an error when the cookie password is undefined', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1563
|
+
yield expect(workos.userManagement.getLogoutUrlFromSessionCookie({
|
|
1564
|
+
sessionData: 'session_cookie',
|
|
1565
|
+
})).rejects.toThrow('Cookie password is required');
|
|
1566
|
+
}));
|
|
1567
|
+
it('returns authenticated = false when the session cookie is empty', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1568
|
+
yield expect(workos.userManagement.getLogoutUrlFromSessionCookie({
|
|
1569
|
+
sessionData: '',
|
|
1570
|
+
cookiePassword: 'secret',
|
|
1571
|
+
})).rejects.toThrowError(new Error('Failed to extract session ID for logout URL: no_session_cookie_provided'));
|
|
1572
|
+
}));
|
|
1573
|
+
it('returns authenticated = false when session cookie is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1574
|
+
yield expect(workos.userManagement.getLogoutUrlFromSessionCookie({
|
|
1575
|
+
sessionData: 'thisisacookie',
|
|
1576
|
+
cookiePassword: 'secret',
|
|
1577
|
+
})).rejects.toThrowError(new Error('Failed to extract session ID for logout URL: invalid_session_cookie'));
|
|
1578
|
+
}));
|
|
1579
|
+
it('returns authenticated = false when session cookie cannot be unsealed', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1580
|
+
const cookiePassword = 'alongcookiesecretmadefortestingsessions';
|
|
1581
|
+
const sessionData = yield (0, iron_session_1.sealData)({
|
|
1582
|
+
accessToken: 'abc123',
|
|
1583
|
+
refreshToken: 'def456',
|
|
1584
|
+
user: {
|
|
1585
|
+
object: 'user',
|
|
1586
|
+
id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS',
|
|
1587
|
+
email: 'test@example.com',
|
|
1588
|
+
},
|
|
1589
|
+
}, { password: cookiePassword });
|
|
1590
|
+
yield expect(workos.userManagement.getLogoutUrlFromSessionCookie({
|
|
1591
|
+
sessionData,
|
|
1592
|
+
cookiePassword: 'secretpasswordwhichisalsolongbutnottherightone',
|
|
1593
|
+
})).rejects.toThrowError(new Error('Failed to extract session ID for logout URL: invalid_session_cookie'));
|
|
1594
|
+
}));
|
|
1595
|
+
it('returns authenticated = false when the JWT is invalid', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1596
|
+
jest.spyOn(jose, 'jwtVerify').mockImplementationOnce(() => {
|
|
1597
|
+
throw new Error('Invalid JWT');
|
|
1598
|
+
});
|
|
1599
|
+
const cookiePassword = 'alongcookiesecretmadefortestingsessions';
|
|
1600
|
+
const sessionData = yield (0, iron_session_1.sealData)({
|
|
1601
|
+
accessToken: 'abc123',
|
|
1602
|
+
refreshToken: 'def456',
|
|
1603
|
+
user: {
|
|
1604
|
+
object: 'user',
|
|
1605
|
+
id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS',
|
|
1606
|
+
email: 'test@example.com',
|
|
1607
|
+
},
|
|
1608
|
+
}, { password: cookiePassword });
|
|
1609
|
+
yield expect(workos.userManagement.getLogoutUrlFromSessionCookie({
|
|
1610
|
+
sessionData,
|
|
1611
|
+
cookiePassword,
|
|
1612
|
+
})).rejects.toThrowError(new Error('Failed to extract session ID for logout URL: invalid_jwt'));
|
|
1613
|
+
}));
|
|
1614
|
+
it('returns the logout URL for the session when provided a valid JWT', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
1615
|
+
jest
|
|
1616
|
+
.spyOn(jose, 'jwtVerify')
|
|
1617
|
+
.mockResolvedValue({});
|
|
1618
|
+
const cookiePassword = 'alongcookiesecretmadefortestingsessions';
|
|
1619
|
+
const sessionData = yield (0, iron_session_1.sealData)({
|
|
1620
|
+
accessToken: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.ewogICJzdWIiOiAiMTIzNDU2Nzg5MCIsCiAgIm5hbWUiOiAiSm9obiBEb2UiLAogICJpYXQiOiAxNTE2MjM5MDIyLAogICJzaWQiOiAic2Vzc2lvbl8xMjMiLAogICJvcmdfaWQiOiAib3JnXzEyMyIsCiAgInJvbGUiOiAibWVtYmVyIiwKICAicGVybWlzc2lvbnMiOiBbInBvc3RzOmNyZWF0ZSIsICJwb3N0czpkZWxldGUiXQp9.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c',
|
|
1621
|
+
refreshToken: 'def456',
|
|
1622
|
+
user: {
|
|
1623
|
+
object: 'user',
|
|
1624
|
+
id: 'user_01H5JQDV7R7ATEYZDEG0W5PRYS',
|
|
1625
|
+
email: 'test@example.com',
|
|
1626
|
+
},
|
|
1627
|
+
}, { password: cookiePassword });
|
|
1628
|
+
yield expect(workos.userManagement.getLogoutUrlFromSessionCookie({
|
|
1629
|
+
sessionData,
|
|
1630
|
+
cookiePassword,
|
|
1631
|
+
})).resolves.toEqual(`https://api.workos.test/user_management/sessions/logout?session_id=session_123`);
|
|
1632
|
+
}));
|
|
1633
|
+
});
|
|
1539
1634
|
describe('getJwksUrl', () => {
|
|
1540
1635
|
it('returns the jwks url', () => {
|
|
1541
1636
|
const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
|
package/lib/workos.js
CHANGED
|
@@ -27,14 +27,13 @@ const bad_request_exception_1 = require("./common/exceptions/bad-request.excepti
|
|
|
27
27
|
const http_client_1 = require("./common/net/http-client");
|
|
28
28
|
const subtle_crypto_provider_1 = require("./common/crypto/subtle-crypto-provider");
|
|
29
29
|
const fetch_client_1 = require("./common/net/fetch-client");
|
|
30
|
-
const VERSION = '7.
|
|
30
|
+
const VERSION = '7.21.0';
|
|
31
31
|
const DEFAULT_HOSTNAME = 'api.workos.com';
|
|
32
32
|
const HEADER_AUTHORIZATION = 'Authorization';
|
|
33
33
|
const HEADER_IDEMPOTENCY_KEY = 'Idempotency-Key';
|
|
34
34
|
const HEADER_WARRANT_TOKEN = 'Warrant-Token';
|
|
35
35
|
class WorkOS {
|
|
36
36
|
constructor(key, options = {}) {
|
|
37
|
-
var _a;
|
|
38
37
|
this.key = key;
|
|
39
38
|
this.options = options;
|
|
40
39
|
this.auditLogs = new audit_logs_1.AuditLogs(this);
|
|
@@ -49,7 +48,10 @@ class WorkOS {
|
|
|
49
48
|
this.fga = new fga_1.FGA(this);
|
|
50
49
|
if (!key) {
|
|
51
50
|
// process might be undefined in some environments
|
|
52
|
-
this.key =
|
|
51
|
+
this.key =
|
|
52
|
+
typeof process !== 'undefined'
|
|
53
|
+
? process === null || process === void 0 ? void 0 : process.env.WORKOS_API_KEY
|
|
54
|
+
: undefined;
|
|
53
55
|
if (!this.key) {
|
|
54
56
|
throw new exceptions_1.NoApiKeyProvidedException();
|
|
55
57
|
}
|
|
@@ -57,7 +59,10 @@ class WorkOS {
|
|
|
57
59
|
if (this.options.https === undefined) {
|
|
58
60
|
this.options.https = true;
|
|
59
61
|
}
|
|
60
|
-
this.clientId =
|
|
62
|
+
this.clientId = this.options.clientId;
|
|
63
|
+
if (!this.clientId && typeof process !== 'undefined') {
|
|
64
|
+
this.clientId = process === null || process === void 0 ? void 0 : process.env.WORKOS_CLIENT_ID;
|
|
65
|
+
}
|
|
61
66
|
const protocol = this.options.https ? 'https' : 'http';
|
|
62
67
|
const apiHostname = this.options.apiHostname || DEFAULT_HOSTNAME;
|
|
63
68
|
const port = this.options.port;
|