@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.
@@ -1,7 +1,7 @@
1
1
  import { DomainData } from './domain-data.interface';
2
2
  export interface UpdateOrganizationOptions {
3
3
  organization: string;
4
- name: string;
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: string;
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.19.0';
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 = process === null || process === void 0 ? void 0 : process.env.WORKOS_API_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 = (_a = this.options.clientId) !== null && _a !== void 0 ? _a : process === null || process === void 0 ? void 0 : process.env.WORKOS_CLIENT_ID;
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;
package/package.json CHANGED
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "7.19.0",
2
+ "version": "7.21.0",
3
3
  "name": "@workos-inc/node",
4
4
  "author": "WorkOS",
5
5
  "description": "A Node wrapper for the WorkOS API",
@@ -67,4 +67,4 @@
67
67
  "default": "./lib/index.js"
68
68
  }
69
69
  }
70
- }
70
+ }