@workos-inc/node 7.68.0 → 7.69.1

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.
@@ -9,6 +9,8 @@ export interface SSOAuthorizationURLOptions {
9
9
  domainHint?: string;
10
10
  loginHint?: string;
11
11
  provider?: string;
12
+ providerQueryParams?: Record<string, string | boolean | number>;
13
+ providerScopes?: string[];
12
14
  redirectUri: string;
13
15
  state?: string;
14
16
  }
@@ -1,10 +1,13 @@
1
1
  import { UnknownRecord } from '../../common/interfaces/unknown-record.interface';
2
+ import { OauthTokens, OauthTokensResponse } from '../../user-management/interfaces/oauth-tokens.interface';
2
3
  import { Profile, ProfileResponse } from './profile.interface';
3
4
  export interface ProfileAndToken<CustomAttributesType extends UnknownRecord> {
4
5
  accessToken: string;
5
6
  profile: Profile<CustomAttributesType>;
7
+ oauthTokens?: OauthTokens;
6
8
  }
7
9
  export interface ProfileAndTokenResponse<CustomAttributesType extends UnknownRecord> {
8
10
  access_token: string;
9
11
  profile: ProfileResponse<CustomAttributesType>;
12
+ oauth_tokens?: OauthTokensResponse;
10
13
  }
@@ -1,9 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.deserializeProfileAndToken = void 0;
4
+ const oauth_tokens_serializer_1 = require("../../user-management/serializers/oauth-tokens.serializer");
4
5
  const profile_serializer_1 = require("./profile.serializer");
5
6
  const deserializeProfileAndToken = (profileAndToken) => ({
6
7
  accessToken: profileAndToken.access_token,
7
8
  profile: (0, profile_serializer_1.deserializeProfile)(profileAndToken.profile),
9
+ oauthTokens: (0, oauth_tokens_serializer_1.deserializeOauthTokens)(profileAndToken.oauth_tokens),
8
10
  });
9
11
  exports.deserializeProfileAndToken = deserializeProfileAndToken;
package/lib/sso/sso.d.ts CHANGED
@@ -7,7 +7,7 @@ export declare class SSO {
7
7
  constructor(workos: WorkOS);
8
8
  listConnections(options?: ListConnectionsOptions): Promise<AutoPaginatable<Connection>>;
9
9
  deleteConnection(id: string): Promise<void>;
10
- getAuthorizationUrl({ connection, clientId, domain, domainHint, loginHint, organization, provider, redirectUri, state, }: SSOAuthorizationURLOptions): string;
10
+ getAuthorizationUrl({ connection, clientId, domain, domainHint, loginHint, organization, provider, providerQueryParams, providerScopes, redirectUri, state, }: SSOAuthorizationURLOptions): string;
11
11
  getConnection(id: string): Promise<Connection>;
12
12
  getProfileAndToken<CustomAttributesType extends UnknownRecord = UnknownRecord>({ code, clientId, }: GetProfileAndTokenOptions): Promise<ProfileAndToken<CustomAttributesType>>;
13
13
  getProfile<CustomAttributesType extends UnknownRecord = UnknownRecord>({ accessToken, }: GetProfileOptions): Promise<Profile<CustomAttributesType>>;
package/lib/sso/sso.js CHANGED
@@ -8,21 +8,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.SSO = void 0;
16
+ const qs_1 = __importDefault(require("qs"));
13
17
  const fetch_and_deserialize_1 = require("../common/utils/fetch-and-deserialize");
14
18
  const pagination_1 = require("../common/utils/pagination");
15
19
  const serializers_1 = require("./serializers");
16
20
  const toQueryString = (options) => {
17
- const searchParams = new URLSearchParams();
18
- const keys = Object.keys(options).sort();
19
- for (const key of keys) {
20
- const value = options[key];
21
- if (value) {
22
- searchParams.append(key, value);
23
- }
24
- }
25
- return searchParams.toString();
21
+ return qs_1.default.stringify(options, {
22
+ arrayFormat: 'repeat',
23
+ // sorts the keys alphabetically to maintain backwards compatibility
24
+ sort: (a, b) => a.localeCompare(b),
25
+ // encodes space as + instead of %20 to maintain backwards compatibility
26
+ format: 'RFC1738',
27
+ });
26
28
  };
27
29
  class SSO {
28
30
  constructor(workos) {
@@ -38,7 +40,7 @@ class SSO {
38
40
  yield this.workos.delete(`/connections/${id}`);
39
41
  });
40
42
  }
41
- getAuthorizationUrl({ connection, clientId, domain, domainHint, loginHint, organization, provider, redirectUri, state, }) {
43
+ getAuthorizationUrl({ connection, clientId, domain, domainHint, loginHint, organization, provider, providerQueryParams, providerScopes, redirectUri, state, }) {
42
44
  if (!domain && !provider && !connection && !organization) {
43
45
  throw new Error(`Incomplete arguments. Need to specify either a 'connection', 'organization', 'domain', or 'provider'.`);
44
46
  }
@@ -52,6 +54,8 @@ class SSO {
52
54
  domain_hint: domainHint,
53
55
  login_hint: loginHint,
54
56
  provider,
57
+ provider_query_params: providerQueryParams,
58
+ provider_scopes: providerScopes,
55
59
  client_id: clientId,
56
60
  redirect_uri: redirectUri,
57
61
  response_type: 'code',
@@ -161,6 +161,54 @@ describe('SSO', () => {
161
161
  expect(url).toMatchInlineSnapshot(`"https://api.workos.com/sso/authorize?client_id=proj_123&connection=connection_123&login_hint=foo%40workos.com&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code&state=custom+state"`);
162
162
  });
163
163
  });
164
+ describe('with providerScopes', () => {
165
+ it('generates an authorize url with the provided provider scopes', () => {
166
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
167
+ const url = workos.sso.getAuthorizationUrl({
168
+ provider: 'Google',
169
+ providerScopes: ['profile', 'email', 'calendar'],
170
+ clientId: 'proj_123',
171
+ redirectUri: 'example.com/sso/workos/callback',
172
+ });
173
+ expect(url).toMatchSnapshot();
174
+ });
175
+ it('handles empty provider scopes array', () => {
176
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
177
+ const url = workos.sso.getAuthorizationUrl({
178
+ provider: 'Google',
179
+ providerScopes: [],
180
+ clientId: 'proj_123',
181
+ redirectUri: 'example.com/sso/workos/callback',
182
+ });
183
+ expect(url).toMatchInlineSnapshot(`"https://api.workos.com/sso/authorize?client_id=proj_123&provider=Google&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`);
184
+ });
185
+ });
186
+ describe('with providerQueryParams', () => {
187
+ it('generates an authorize url with the provided provider query params', () => {
188
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
189
+ const url = workos.sso.getAuthorizationUrl({
190
+ provider: 'Google',
191
+ providerQueryParams: {
192
+ custom_param: 'custom_value',
193
+ another_param: 123,
194
+ bool_param: true,
195
+ },
196
+ clientId: 'proj_123',
197
+ redirectUri: 'example.com/sso/workos/callback',
198
+ });
199
+ expect(url).toMatchInlineSnapshot(`"https://api.workos.com/sso/authorize?client_id=proj_123&provider=Google&provider_query_params%5Banother_param%5D=123&provider_query_params%5Bbool_param%5D=true&provider_query_params%5Bcustom_param%5D=custom_value&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`);
200
+ });
201
+ it('handles empty provider query params', () => {
202
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
203
+ const url = workos.sso.getAuthorizationUrl({
204
+ provider: 'Google',
205
+ providerQueryParams: {},
206
+ clientId: 'proj_123',
207
+ redirectUri: 'example.com/sso/workos/callback',
208
+ });
209
+ expect(url).toMatchInlineSnapshot(`"https://api.workos.com/sso/authorize?client_id=proj_123&provider=Google&redirect_uri=example.com%2Fsso%2Fworkos%2Fcallback&response_type=code"`);
210
+ });
211
+ });
164
212
  });
165
213
  describe('getProfileAndToken', () => {
166
214
  describe('with all information provided', () => {
@@ -240,6 +288,89 @@ describe('SSO', () => {
240
288
  expect(profile).toMatchSnapshot();
241
289
  }));
242
290
  });
291
+ describe('with oauth tokens in the response', () => {
292
+ it('returns the oauth tokens from the profile and token response', () => __awaiter(void 0, void 0, void 0, function* () {
293
+ (0, test_utils_1.fetchOnce)({
294
+ access_token: '01DMEK0J53CVMC32CK5SE0KZ8Q',
295
+ profile: {
296
+ id: 'prof_123',
297
+ idp_id: '123',
298
+ organization_id: 'org_123',
299
+ connection_id: 'conn_123',
300
+ connection_type: 'OktaSAML',
301
+ email: 'foo@test.com',
302
+ first_name: 'foo',
303
+ last_name: 'bar',
304
+ role: {
305
+ slug: 'admin',
306
+ },
307
+ groups: ['Admins', 'Developers'],
308
+ raw_attributes: {
309
+ email: 'foo@test.com',
310
+ first_name: 'foo',
311
+ last_name: 'bar',
312
+ groups: ['Admins', 'Developers'],
313
+ },
314
+ custom_attributes: {},
315
+ },
316
+ oauth_tokens: {
317
+ access_token: 'oauth_access_token',
318
+ refresh_token: 'oauth_refresh_token',
319
+ expires_at: 1640995200,
320
+ scopes: ['profile', 'email'],
321
+ },
322
+ });
323
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
324
+ const { accessToken, profile, oauthTokens } = yield workos.sso.getProfileAndToken({
325
+ code: 'authorization_code',
326
+ clientId: 'proj_123',
327
+ });
328
+ expect(jest_fetch_mock_1.default.mock.calls.length).toEqual(1);
329
+ expect(accessToken).toBe('01DMEK0J53CVMC32CK5SE0KZ8Q');
330
+ expect(profile).toBeDefined();
331
+ expect(oauthTokens).toEqual({
332
+ accessToken: 'oauth_access_token',
333
+ refreshToken: 'oauth_refresh_token',
334
+ expiresAt: 1640995200,
335
+ scopes: ['profile', 'email'],
336
+ });
337
+ }));
338
+ });
339
+ describe('without oauth tokens in the response', () => {
340
+ it('returns undefined for oauth tokens when not present in response', () => __awaiter(void 0, void 0, void 0, function* () {
341
+ (0, test_utils_1.fetchOnce)({
342
+ access_token: '01DMEK0J53CVMC32CK5SE0KZ8Q',
343
+ profile: {
344
+ id: 'prof_123',
345
+ idp_id: '123',
346
+ organization_id: 'org_123',
347
+ connection_id: 'conn_123',
348
+ connection_type: 'OktaSAML',
349
+ email: 'foo@test.com',
350
+ first_name: 'foo',
351
+ last_name: 'bar',
352
+ role: {
353
+ slug: 'admin',
354
+ },
355
+ raw_attributes: {
356
+ email: 'foo@test.com',
357
+ first_name: 'foo',
358
+ last_name: 'bar',
359
+ },
360
+ custom_attributes: {},
361
+ },
362
+ });
363
+ const workos = new workos_1.WorkOS('sk_test_Sz3IQjepeSWaI4cMS4ms4sMuU');
364
+ const { accessToken, profile, oauthTokens } = yield workos.sso.getProfileAndToken({
365
+ code: 'authorization_code',
366
+ clientId: 'proj_123',
367
+ });
368
+ expect(jest_fetch_mock_1.default.mock.calls.length).toEqual(1);
369
+ expect(accessToken).toBe('01DMEK0J53CVMC32CK5SE0KZ8Q');
370
+ expect(profile).toBeDefined();
371
+ expect(oauthTokens).toBeUndefined();
372
+ }));
373
+ });
243
374
  });
244
375
  describe('getProfile', () => {
245
376
  it('calls the `/sso/profile` endpoint with the provided access token', () => __awaiter(void 0, void 0, void 0, function* () {
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.68.0';
35
+ const VERSION = '7.69.1';
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.68.0",
2
+ "version": "7.69.1",
3
3
  "name": "@workos-inc/node",
4
4
  "author": "WorkOS",
5
5
  "description": "A Node wrapper for the WorkOS API",