@workos-inc/node 8.0.0-rc.6 → 8.0.0-rc.8

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 (261) hide show
  1. package/README.md +54 -0
  2. package/lib/api-keys/api-keys.cjs +3 -0
  3. package/lib/api-keys/api-keys.cjs.map +1 -1
  4. package/lib/api-keys/api-keys.d.cts +2 -1
  5. package/lib/api-keys/api-keys.d.ts +2 -1
  6. package/lib/api-keys/api-keys.js +3 -0
  7. package/lib/api-keys/api-keys.js.map +1 -1
  8. package/lib/api-keys/interfaces/create-organization-api-key-options.interface.cjs +0 -0
  9. package/lib/api-keys/interfaces/create-organization-api-key-options.interface.d.cts +16 -0
  10. package/lib/api-keys/interfaces/create-organization-api-key-options.interface.d.ts +16 -0
  11. package/lib/api-keys/interfaces/create-organization-api-key-options.interface.js +1 -0
  12. package/lib/api-keys/interfaces/created-api-key.interface.cjs +0 -0
  13. package/lib/api-keys/interfaces/created-api-key.interface.d.cts +34 -0
  14. package/lib/api-keys/interfaces/created-api-key.interface.d.ts +34 -0
  15. package/lib/api-keys/interfaces/created-api-key.interface.js +1 -0
  16. package/lib/api-keys/interfaces/index.cjs +0 -0
  17. package/lib/api-keys/interfaces/index.d.cts +6 -0
  18. package/lib/api-keys/interfaces/index.d.ts +6 -0
  19. package/lib/api-keys/interfaces/index.js +1 -0
  20. package/lib/api-keys/interfaces/list-organization-api-keys-options.interface.cjs +0 -0
  21. package/lib/api-keys/interfaces/list-organization-api-keys-options.interface.d.cts +9 -0
  22. package/lib/api-keys/interfaces/list-organization-api-keys-options.interface.d.ts +9 -0
  23. package/lib/api-keys/interfaces/list-organization-api-keys-options.interface.js +1 -0
  24. package/lib/api-keys/serializers/create-organization-api-key-options.serializer.cjs +12 -0
  25. package/lib/api-keys/serializers/create-organization-api-key-options.serializer.cjs.map +1 -0
  26. package/lib/api-keys/serializers/create-organization-api-key-options.serializer.d.cts +7 -0
  27. package/lib/api-keys/serializers/create-organization-api-key-options.serializer.d.ts +7 -0
  28. package/lib/api-keys/serializers/create-organization-api-key-options.serializer.js +11 -0
  29. package/lib/api-keys/serializers/create-organization-api-key-options.serializer.js.map +1 -0
  30. package/lib/api-keys/serializers/created-api-key.serializer.cjs +20 -0
  31. package/lib/api-keys/serializers/created-api-key.serializer.cjs.map +1 -0
  32. package/lib/api-keys/serializers/created-api-key.serializer.d.cts +7 -0
  33. package/lib/api-keys/serializers/created-api-key.serializer.d.ts +7 -0
  34. package/lib/api-keys/serializers/created-api-key.serializer.js +19 -0
  35. package/lib/api-keys/serializers/created-api-key.serializer.js.map +1 -0
  36. package/lib/api-keys/serializers/index.cjs +9 -0
  37. package/lib/api-keys/serializers/index.d.cts +5 -0
  38. package/lib/api-keys/serializers/index.d.ts +5 -0
  39. package/lib/api-keys/serializers/index.js +6 -0
  40. package/lib/common/crypto/seal.cjs +7 -7
  41. package/lib/common/crypto/seal.cjs.map +1 -1
  42. package/lib/common/crypto/seal.js +1 -1
  43. package/lib/common/exceptions/api-key-required.exception.cjs +15 -0
  44. package/lib/common/exceptions/api-key-required.exception.cjs.map +1 -0
  45. package/lib/common/exceptions/api-key-required.exception.d.cts +10 -0
  46. package/lib/common/exceptions/api-key-required.exception.d.ts +10 -0
  47. package/lib/common/exceptions/api-key-required.exception.js +14 -0
  48. package/lib/common/exceptions/api-key-required.exception.js.map +1 -0
  49. package/lib/common/exceptions/index.cjs +2 -0
  50. package/lib/common/exceptions/index.d.cts +2 -1
  51. package/lib/common/exceptions/index.d.ts +2 -1
  52. package/lib/common/exceptions/index.js +2 -1
  53. package/lib/common/interfaces/event.interface.d.cts +28 -3
  54. package/lib/common/interfaces/event.interface.d.ts +28 -3
  55. package/lib/common/interfaces/get-options.interface.d.cts +2 -0
  56. package/lib/common/interfaces/get-options.interface.d.ts +2 -0
  57. package/lib/common/interfaces/index.d.cts +2 -2
  58. package/lib/common/interfaces/index.d.ts +2 -2
  59. package/lib/common/interfaces/post-options.interface.d.cts +2 -0
  60. package/lib/common/interfaces/post-options.interface.d.ts +2 -0
  61. package/lib/common/interfaces/put-options.interface.d.cts +2 -0
  62. package/lib/common/interfaces/put-options.interface.d.ts +2 -0
  63. package/lib/common/interfaces/workos-options.interface.d.cts +1 -0
  64. package/lib/common/interfaces/workos-options.interface.d.ts +1 -0
  65. package/lib/common/net/http-client.cjs.map +1 -1
  66. package/lib/common/net/http-client.js.map +1 -1
  67. package/lib/common/serializers/event.serializer.cjs +13 -5
  68. package/lib/common/serializers/event.serializer.cjs.map +1 -1
  69. package/lib/common/serializers/event.serializer.js +13 -5
  70. package/lib/common/serializers/event.serializer.js.map +1 -1
  71. package/lib/directory-sync/directory-sync.cjs +1 -1
  72. package/lib/directory-sync/directory-sync.js +1 -1
  73. package/lib/factory.cjs +10 -0
  74. package/lib/factory.cjs.map +1 -0
  75. package/lib/factory.d.cts +83 -0
  76. package/lib/factory.d.ts +83 -0
  77. package/lib/factory.js +10 -0
  78. package/lib/factory.js.map +1 -0
  79. package/lib/feature-flags/feature-flags.cjs +37 -0
  80. package/lib/feature-flags/feature-flags.cjs.map +1 -0
  81. package/lib/feature-flags/feature-flags.d.cts +21 -0
  82. package/lib/feature-flags/feature-flags.d.ts +21 -0
  83. package/lib/feature-flags/feature-flags.js +37 -0
  84. package/lib/feature-flags/feature-flags.js.map +1 -0
  85. package/lib/feature-flags/interfaces/add-flag-target-options.interface.cjs +0 -0
  86. package/lib/feature-flags/interfaces/add-flag-target-options.interface.d.cts +8 -0
  87. package/lib/feature-flags/interfaces/add-flag-target-options.interface.d.ts +8 -0
  88. package/lib/feature-flags/interfaces/add-flag-target-options.interface.js +1 -0
  89. package/lib/feature-flags/interfaces/feature-flag.interface.d.cts +8 -2
  90. package/lib/feature-flags/interfaces/feature-flag.interface.d.ts +8 -2
  91. package/lib/feature-flags/interfaces/index.d.cts +4 -1
  92. package/lib/feature-flags/interfaces/index.d.ts +4 -1
  93. package/lib/feature-flags/interfaces/list-feature-flags-options.interface.cjs +0 -0
  94. package/lib/feature-flags/interfaces/list-feature-flags-options.interface.d.cts +7 -0
  95. package/lib/feature-flags/interfaces/list-feature-flags-options.interface.d.ts +7 -0
  96. package/lib/feature-flags/interfaces/list-feature-flags-options.interface.js +1 -0
  97. package/lib/feature-flags/interfaces/remove-flag-target-options.interface.cjs +0 -0
  98. package/lib/feature-flags/interfaces/remove-flag-target-options.interface.d.cts +8 -0
  99. package/lib/feature-flags/interfaces/remove-flag-target-options.interface.d.ts +8 -0
  100. package/lib/feature-flags/interfaces/remove-flag-target-options.interface.js +1 -0
  101. package/lib/feature-flags/serializers/feature-flag.serializer.cjs +3 -0
  102. package/lib/feature-flags/serializers/feature-flag.serializer.cjs.map +1 -1
  103. package/lib/feature-flags/serializers/feature-flag.serializer.js +3 -0
  104. package/lib/feature-flags/serializers/feature-flag.serializer.js.map +1 -1
  105. package/lib/feature-flags/serializers/index.cjs +3 -0
  106. package/lib/feature-flags/serializers/index.d.cts +2 -0
  107. package/lib/feature-flags/serializers/index.d.ts +2 -0
  108. package/lib/feature-flags/serializers/index.js +3 -0
  109. package/lib/fga/serializers/query-result.serializer.cjs.map +1 -1
  110. package/lib/fga/serializers/query-result.serializer.js.map +1 -1
  111. package/lib/index.cjs +18 -9
  112. package/lib/index.cjs.map +1 -1
  113. package/lib/index.d.cts +18 -5
  114. package/lib/index.d.ts +18 -5
  115. package/lib/index.js +16 -10
  116. package/lib/index.js.map +1 -1
  117. package/lib/index.worker.cjs +15 -9
  118. package/lib/index.worker.cjs.map +1 -1
  119. package/lib/index.worker.d.cts +10 -5
  120. package/lib/index.worker.d.ts +10 -5
  121. package/lib/index.worker.js +13 -10
  122. package/lib/index.worker.js.map +1 -1
  123. package/lib/node_modules/iron-webcrypto/index.cjs +218 -0
  124. package/lib/node_modules/iron-webcrypto/index.cjs.map +1 -0
  125. package/lib/node_modules/iron-webcrypto/index.js +216 -0
  126. package/lib/node_modules/iron-webcrypto/index.js.map +1 -0
  127. package/lib/node_modules/uint8array-extras/index.cjs +55 -0
  128. package/lib/node_modules/uint8array-extras/index.cjs.map +1 -0
  129. package/lib/node_modules/uint8array-extras/index.js +52 -0
  130. package/lib/node_modules/uint8array-extras/index.js.map +1 -0
  131. package/lib/organizations/organizations.cjs +14 -2
  132. package/lib/organizations/organizations.cjs.map +1 -1
  133. package/lib/organizations/organizations.d.cts +6 -0
  134. package/lib/organizations/organizations.d.ts +6 -0
  135. package/lib/organizations/organizations.js +14 -2
  136. package/lib/organizations/organizations.js.map +1 -1
  137. package/lib/organizations/serializers/index.cjs +1 -1
  138. package/lib/organizations/serializers/index.js +1 -1
  139. package/lib/pkce/pkce.cjs +54 -0
  140. package/lib/pkce/pkce.cjs.map +1 -0
  141. package/lib/pkce/pkce.d.cts +38 -0
  142. package/lib/pkce/pkce.d.ts +38 -0
  143. package/lib/pkce/pkce.js +53 -0
  144. package/lib/pkce/pkce.js.map +1 -0
  145. package/lib/sso/interfaces/authorization-url-options.interface.d.cts +34 -8
  146. package/lib/sso/interfaces/authorization-url-options.interface.d.ts +34 -8
  147. package/lib/sso/interfaces/get-profile-and-token-options.interface.d.cts +6 -0
  148. package/lib/sso/interfaces/get-profile-and-token-options.interface.d.ts +6 -0
  149. package/lib/sso/interfaces/index.d.cts +2 -2
  150. package/lib/sso/interfaces/index.d.ts +2 -2
  151. package/lib/sso/sso.cjs +90 -8
  152. package/lib/sso/sso.cjs.map +1 -1
  153. package/lib/sso/sso.d.cts +41 -2
  154. package/lib/sso/sso.d.ts +41 -2
  155. package/lib/sso/sso.js +90 -8
  156. package/lib/sso/sso.js.map +1 -1
  157. package/lib/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.d.cts +2 -2
  158. package/lib/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.d.ts +2 -2
  159. package/lib/user-management/interfaces/authenticate-with-options-base.interface.d.cts +19 -3
  160. package/lib/user-management/interfaces/authenticate-with-options-base.interface.d.ts +19 -3
  161. package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.cjs +0 -0
  162. package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.d.cts +16 -0
  163. package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.d.ts +16 -0
  164. package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.js +1 -0
  165. package/lib/user-management/interfaces/authorization-url-options.interface.d.cts +30 -5
  166. package/lib/user-management/interfaces/authorization-url-options.interface.d.ts +30 -5
  167. package/lib/user-management/interfaces/index.d.cts +5 -3
  168. package/lib/user-management/interfaces/index.d.ts +5 -3
  169. package/lib/user-management/interfaces/logout-url-options.interface.cjs +0 -0
  170. package/lib/user-management/interfaces/logout-url-options.interface.d.cts +8 -0
  171. package/lib/user-management/interfaces/logout-url-options.interface.d.ts +8 -0
  172. package/lib/user-management/interfaces/logout-url-options.interface.js +1 -0
  173. package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.cjs.map +1 -1
  174. package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.d.cts +2 -1
  175. package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.d.ts +2 -1
  176. package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.js.map +1 -1
  177. package/lib/user-management/serializers/authenticate-with-code-options.serializer.cjs.map +1 -1
  178. package/lib/user-management/serializers/authenticate-with-code-options.serializer.d.cts +2 -1
  179. package/lib/user-management/serializers/authenticate-with-code-options.serializer.d.ts +2 -1
  180. package/lib/user-management/serializers/authenticate-with-code-options.serializer.js.map +1 -1
  181. package/lib/user-management/serializers/authenticate-with-email-verification.serializer.cjs.map +1 -1
  182. package/lib/user-management/serializers/authenticate-with-email-verification.serializer.d.cts +2 -1
  183. package/lib/user-management/serializers/authenticate-with-email-verification.serializer.d.ts +2 -1
  184. package/lib/user-management/serializers/authenticate-with-email-verification.serializer.js.map +1 -1
  185. package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.cjs.map +1 -1
  186. package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.d.cts +2 -1
  187. package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.d.ts +2 -1
  188. package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.js.map +1 -1
  189. package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.cjs.map +1 -1
  190. package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.d.cts +2 -1
  191. package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.d.ts +2 -1
  192. package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.js.map +1 -1
  193. package/lib/user-management/serializers/authenticate-with-password-options.serializer.cjs.map +1 -1
  194. package/lib/user-management/serializers/authenticate-with-password-options.serializer.d.cts +2 -1
  195. package/lib/user-management/serializers/authenticate-with-password-options.serializer.d.ts +2 -1
  196. package/lib/user-management/serializers/authenticate-with-password-options.serializer.js.map +1 -1
  197. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.cjs +14 -0
  198. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.cjs.map +1 -0
  199. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.d.cts +8 -0
  200. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.d.ts +8 -0
  201. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.js +13 -0
  202. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.js.map +1 -0
  203. package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.cjs.map +1 -1
  204. package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.d.cts +2 -1
  205. package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.d.ts +2 -1
  206. package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.js.map +1 -1
  207. package/lib/user-management/serializers/authenticate-with-totp-options.serializer.cjs.map +1 -1
  208. package/lib/user-management/serializers/authenticate-with-totp-options.serializer.d.cts +2 -1
  209. package/lib/user-management/serializers/authenticate-with-totp-options.serializer.d.ts +2 -1
  210. package/lib/user-management/serializers/authenticate-with-totp-options.serializer.js.map +1 -1
  211. package/lib/user-management/serializers/index.cjs +2 -0
  212. package/lib/user-management/serializers/index.d.cts +2 -1
  213. package/lib/user-management/serializers/index.d.ts +2 -1
  214. package/lib/user-management/serializers/index.js +2 -1
  215. package/lib/user-management/session.cjs +3 -10
  216. package/lib/user-management/session.cjs.map +1 -1
  217. package/lib/user-management/session.js +3 -10
  218. package/lib/user-management/session.js.map +1 -1
  219. package/lib/user-management/user-management.cjs +186 -31
  220. package/lib/user-management/user-management.cjs.map +1 -1
  221. package/lib/user-management/user-management.d.cts +71 -2
  222. package/lib/user-management/user-management.d.ts +71 -2
  223. package/lib/user-management/user-management.js +186 -31
  224. package/lib/user-management/user-management.js.map +1 -1
  225. package/lib/vault/vault.cjs +4 -0
  226. package/lib/vault/vault.cjs.map +1 -1
  227. package/lib/vault/vault.d.cts +1 -0
  228. package/lib/vault/vault.d.ts +1 -0
  229. package/lib/vault/vault.js +4 -0
  230. package/lib/vault/vault.js.map +1 -1
  231. package/lib/webhooks/webhooks.cjs +1 -1
  232. package/lib/webhooks/webhooks.js +1 -1
  233. package/lib/workos.cjs +68 -26
  234. package/lib/workos.cjs.map +1 -1
  235. package/lib/workos.d.cts +37 -8
  236. package/lib/workos.d.ts +37 -8
  237. package/lib/workos.js +68 -26
  238. package/lib/workos.js.map +1 -1
  239. package/package.json +4 -21
  240. package/lib/_virtual/rolldown_runtime.cjs +0 -19
  241. package/lib/_virtual/rolldown_runtime.js +0 -18
  242. package/lib/client/index.cjs +0 -15
  243. package/lib/client/index.d.cts +0 -3
  244. package/lib/client/index.d.ts +0 -3
  245. package/lib/client/index.js +0 -4
  246. package/lib/client/sso.cjs +0 -40
  247. package/lib/client/sso.cjs.map +0 -1
  248. package/lib/client/sso.d.cts +0 -21
  249. package/lib/client/sso.d.ts +0 -21
  250. package/lib/client/sso.js +0 -34
  251. package/lib/client/sso.js.map +0 -1
  252. package/lib/client/user-management.cjs +0 -80
  253. package/lib/client/user-management.cjs.map +0 -1
  254. package/lib/client/user-management.d.cts +0 -58
  255. package/lib/client/user-management.d.ts +0 -58
  256. package/lib/client/user-management.js +0 -72
  257. package/lib/client/user-management.js.map +0 -1
  258. package/lib/index.client.cjs +0 -15
  259. package/lib/index.client.d.cts +0 -3
  260. package/lib/index.client.d.ts +0 -3
  261. package/lib/index.client.js +0 -4
package/lib/sso/sso.cjs CHANGED
@@ -1,10 +1,10 @@
1
- const require_client_sso = require('../client/sso.cjs');
1
+ const require_common_utils_pagination = require('../common/utils/pagination.cjs');
2
2
  const require_sso_serializers_connection_serializer = require('./serializers/connection.serializer.cjs');
3
3
  const require_sso_serializers_list_connections_options_serializer = require('./serializers/list-connections-options.serializer.cjs');
4
4
  const require_sso_serializers_profile_serializer = require('./serializers/profile.serializer.cjs');
5
5
  const require_sso_serializers_profile_and_token_serializer = require('./serializers/profile-and-token.serializer.cjs');
6
- const require_common_utils_pagination = require('../common/utils/pagination.cjs');
7
6
  const require_common_utils_fetch_and_deserialize = require('../common/utils/fetch-and-deserialize.cjs');
7
+ const require_common_utils_query_string = require('../common/utils/query-string.cjs');
8
8
 
9
9
  //#region src/sso/sso.ts
10
10
  var SSO = class {
@@ -18,23 +18,105 @@ var SSO = class {
18
18
  await this.workos.delete(`/connections/${id}`);
19
19
  }
20
20
  getAuthorizationUrl(options) {
21
- return require_client_sso.getAuthorizationUrl({
22
- ...options,
23
- baseURL: this.workos.baseURL
21
+ const { codeChallenge, codeChallengeMethod, connection, clientId, domainHint, loginHint, organization, provider, providerQueryParams, providerScopes, redirectUri, state } = options;
22
+ if (!provider && !connection && !organization) throw new TypeError(`Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`);
23
+ const query = require_common_utils_query_string.toQueryString({
24
+ code_challenge: codeChallenge,
25
+ code_challenge_method: codeChallengeMethod,
26
+ connection,
27
+ organization,
28
+ domain_hint: domainHint,
29
+ login_hint: loginHint,
30
+ provider,
31
+ provider_query_params: providerQueryParams,
32
+ provider_scopes: providerScopes,
33
+ client_id: clientId,
34
+ redirect_uri: redirectUri,
35
+ response_type: "code",
36
+ state
37
+ });
38
+ return `${this.workos.baseURL}/sso/authorize?${query}`;
39
+ }
40
+ /**
41
+ * Generates an authorization URL with PKCE parameters automatically generated.
42
+ * Use this for public clients (CLI apps, Electron, mobile) that cannot
43
+ * securely store a client secret.
44
+ *
45
+ * @returns Object containing url, state, and codeVerifier
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const { url, state, codeVerifier } = await workos.sso.getAuthorizationUrlWithPKCE({
50
+ * connection: 'conn_123',
51
+ * clientId: 'client_123',
52
+ * redirectUri: 'myapp://callback',
53
+ * });
54
+ *
55
+ * // Store state and codeVerifier securely, then redirect user to url
56
+ * // After callback, exchange the code:
57
+ * const { profile, accessToken } = await workos.sso.getProfileAndToken({
58
+ * code: authorizationCode,
59
+ * codeVerifier,
60
+ * clientId: 'client_123',
61
+ * });
62
+ * ```
63
+ */
64
+ async getAuthorizationUrlWithPKCE(options) {
65
+ const { connection, clientId, domainHint, loginHint, organization, provider, providerQueryParams, providerScopes, redirectUri } = options;
66
+ if (!provider && !connection && !organization) throw new TypeError(`Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`);
67
+ const pkce = await this.workos.pkce.generate();
68
+ const state = this.workos.pkce.generateCodeVerifier(43);
69
+ const query = require_common_utils_query_string.toQueryString({
70
+ code_challenge: pkce.codeChallenge,
71
+ code_challenge_method: "S256",
72
+ connection,
73
+ organization,
74
+ domain_hint: domainHint,
75
+ login_hint: loginHint,
76
+ provider,
77
+ provider_query_params: providerQueryParams,
78
+ provider_scopes: providerScopes,
79
+ client_id: clientId,
80
+ redirect_uri: redirectUri,
81
+ response_type: "code",
82
+ state
24
83
  });
84
+ return {
85
+ url: `${this.workos.baseURL}/sso/authorize?${query}`,
86
+ state,
87
+ codeVerifier: pkce.codeVerifier
88
+ };
25
89
  }
26
90
  async getConnection(id) {
27
91
  const { data } = await this.workos.get(`/connections/${id}`);
28
92
  return require_sso_serializers_connection_serializer.deserializeConnection(data);
29
93
  }
30
- async getProfileAndToken({ code, clientId }) {
94
+ /**
95
+ * Exchange an authorization code for a profile and access token.
96
+ *
97
+ * Auto-detects public vs confidential client mode:
98
+ * - If codeVerifier is provided: Uses PKCE flow (public client)
99
+ * - If no codeVerifier: Uses client_secret from API key (confidential client)
100
+ * - If both: Uses both client_secret AND codeVerifier (confidential client with PKCE)
101
+ *
102
+ * Using PKCE with confidential clients is recommended by OAuth 2.1 for defense
103
+ * in depth and provides additional CSRF protection on the authorization flow.
104
+ *
105
+ * @throws Error if neither codeVerifier nor API key is available
106
+ */
107
+ async getProfileAndToken({ code, clientId, codeVerifier }) {
108
+ if (codeVerifier !== void 0 && codeVerifier.trim() === "") throw new TypeError("codeVerifier cannot be an empty string. Generate a valid PKCE pair using workos.pkce.generate().");
109
+ const hasApiKey = !!this.workos.key;
110
+ const hasPKCE = !!codeVerifier;
111
+ if (!hasPKCE && !hasApiKey) throw new TypeError("getProfileAndToken requires either a codeVerifier (for public clients) or an API key configured on the WorkOS instance (for confidential clients).");
31
112
  const form = new URLSearchParams({
32
113
  client_id: clientId,
33
- client_secret: this.workos.key,
34
114
  grant_type: "authorization_code",
35
115
  code
36
116
  });
37
- const { data } = await this.workos.post("/sso/token", form);
117
+ if (hasPKCE) form.set("code_verifier", codeVerifier);
118
+ if (hasApiKey) form.set("client_secret", this.workos.key);
119
+ const { data } = await this.workos.post("/sso/token", form, { skipApiKeyCheck: !hasApiKey });
38
120
  return require_sso_serializers_profile_and_token_serializer.deserializeProfileAndToken(data);
39
121
  }
40
122
  async getProfile({ accessToken }) {
@@ -1 +1 @@
1
- {"version":3,"file":"sso.cjs","names":["workos: WorkOS","AutoPaginatable","fetchAndDeserialize","deserializeConnection","serializeListConnectionsOptions","deserializeProfileAndToken","deserializeProfile"],"sources":["../../src/sso/sso.ts"],"sourcesContent":["import * as clientSSO from '../client/sso';\nimport { UnknownRecord } from '../common/interfaces/unknown-record.interface';\nimport { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize';\nimport { AutoPaginatable } from '../common/utils/pagination';\nimport { WorkOS } from '../workos';\nimport {\n Connection,\n ConnectionResponse,\n GetProfileAndTokenOptions,\n GetProfileOptions,\n ListConnectionsOptions,\n Profile,\n ProfileAndToken,\n ProfileAndTokenResponse,\n ProfileResponse,\n SSOAuthorizationURLOptions,\n SerializedListConnectionsOptions,\n} from './interfaces';\nimport {\n deserializeConnection,\n deserializeProfile,\n deserializeProfileAndToken,\n serializeListConnectionsOptions,\n} from './serializers';\n\nexport class SSO {\n constructor(private readonly workos: WorkOS) {}\n\n async listConnections(\n options?: ListConnectionsOptions,\n ): Promise<AutoPaginatable<Connection, SerializedListConnectionsOptions>> {\n return new AutoPaginatable(\n await fetchAndDeserialize<ConnectionResponse, Connection>(\n this.workos,\n '/connections',\n deserializeConnection,\n options ? serializeListConnectionsOptions(options) : undefined,\n ),\n (params) =>\n fetchAndDeserialize<ConnectionResponse, Connection>(\n this.workos,\n '/connections',\n deserializeConnection,\n params,\n ),\n options ? serializeListConnectionsOptions(options) : undefined,\n );\n }\n async deleteConnection(id: string) {\n await this.workos.delete(`/connections/${id}`);\n }\n\n getAuthorizationUrl(options: SSOAuthorizationURLOptions): string {\n // Delegate to client implementation\n return clientSSO.getAuthorizationUrl({\n ...options,\n baseURL: this.workos.baseURL,\n });\n }\n\n async getConnection(id: string): Promise<Connection> {\n const { data } = await this.workos.get<ConnectionResponse>(\n `/connections/${id}`,\n );\n\n return deserializeConnection(data);\n }\n\n async getProfileAndToken<\n CustomAttributesType extends UnknownRecord = UnknownRecord,\n >({\n code,\n clientId,\n }: GetProfileAndTokenOptions): Promise<\n ProfileAndToken<CustomAttributesType>\n > {\n const form = new URLSearchParams({\n client_id: clientId,\n client_secret: this.workos.key as string,\n grant_type: 'authorization_code',\n code,\n });\n\n const { data } = await this.workos.post<\n ProfileAndTokenResponse<CustomAttributesType>\n >('/sso/token', form);\n\n return deserializeProfileAndToken(data);\n }\n\n async getProfile<CustomAttributesType extends UnknownRecord = UnknownRecord>({\n accessToken,\n }: GetProfileOptions): Promise<Profile<CustomAttributesType>> {\n const { data } = await this.workos.get<\n ProfileResponse<CustomAttributesType>\n >('/sso/profile', {\n accessToken,\n });\n\n return deserializeProfile(data);\n }\n}\n"],"mappings":";;;;;;;;;AAyBA,IAAa,MAAb,MAAiB;CACf,YAAY,AAAiBA,QAAgB;EAAhB;;CAE7B,MAAM,gBACJ,SACwE;AACxE,SAAO,IAAIC,gDACT,MAAMC,+DACJ,KAAK,QACL,gBACAC,qEACA,UAAUC,4FAAgC,QAAQ,GAAG,OACtD,GACA,WACCF,+DACE,KAAK,QACL,gBACAC,qEACA,OACD,EACH,UAAUC,4FAAgC,QAAQ,GAAG,OACtD;;CAEH,MAAM,iBAAiB,IAAY;AACjC,QAAM,KAAK,OAAO,OAAO,gBAAgB,KAAK;;CAGhD,oBAAoB,SAA6C;AAE/D,gDAAqC;GACnC,GAAG;GACH,SAAS,KAAK,OAAO;GACtB,CAAC;;CAGJ,MAAM,cAAc,IAAiC;EACnD,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,IACjC,gBAAgB,KACjB;AAED,SAAOD,oEAAsB,KAAK;;CAGpC,MAAM,mBAEJ,EACA,MACA,YAGA;EACA,MAAM,OAAO,IAAI,gBAAgB;GAC/B,WAAW;GACX,eAAe,KAAK,OAAO;GAC3B,YAAY;GACZ;GACD,CAAC;EAEF,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,KAEjC,cAAc,KAAK;AAErB,SAAOE,gFAA2B,KAAK;;CAGzC,MAAM,WAAuE,EAC3E,eAC4D;EAC5D,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,IAEjC,gBAAgB,EAChB,aACD,CAAC;AAEF,SAAOC,8DAAmB,KAAK"}
1
+ {"version":3,"file":"sso.cjs","names":["workos: WorkOS","AutoPaginatable","fetchAndDeserialize","deserializeConnection","serializeListConnectionsOptions","toQueryString","deserializeProfileAndToken","deserializeProfile"],"sources":["../../src/sso/sso.ts"],"sourcesContent":["import { UnknownRecord } from '../common/interfaces/unknown-record.interface';\nimport { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize';\nimport { AutoPaginatable } from '../common/utils/pagination';\nimport { toQueryString } from '../common/utils/query-string';\nimport { WorkOS } from '../workos';\nimport {\n Connection,\n ConnectionResponse,\n GetProfileAndTokenOptions,\n GetProfileOptions,\n ListConnectionsOptions,\n Profile,\n ProfileAndToken,\n ProfileAndTokenResponse,\n ProfileResponse,\n SSOAuthorizationURLOptions,\n SSOPKCEAuthorizationURLResult,\n SerializedListConnectionsOptions,\n} from './interfaces';\nimport {\n deserializeConnection,\n deserializeProfile,\n deserializeProfileAndToken,\n serializeListConnectionsOptions,\n} from './serializers';\n\nexport class SSO {\n constructor(private readonly workos: WorkOS) {}\n\n async listConnections(\n options?: ListConnectionsOptions,\n ): Promise<AutoPaginatable<Connection, SerializedListConnectionsOptions>> {\n return new AutoPaginatable(\n await fetchAndDeserialize<ConnectionResponse, Connection>(\n this.workos,\n '/connections',\n deserializeConnection,\n options ? serializeListConnectionsOptions(options) : undefined,\n ),\n (params) =>\n fetchAndDeserialize<ConnectionResponse, Connection>(\n this.workos,\n '/connections',\n deserializeConnection,\n params,\n ),\n options ? serializeListConnectionsOptions(options) : undefined,\n );\n }\n async deleteConnection(id: string) {\n await this.workos.delete(`/connections/${id}`);\n }\n\n getAuthorizationUrl(options: SSOAuthorizationURLOptions): string {\n const {\n codeChallenge,\n codeChallengeMethod,\n connection,\n clientId,\n domainHint,\n loginHint,\n organization,\n provider,\n providerQueryParams,\n providerScopes,\n redirectUri,\n state,\n } = options;\n\n if (!provider && !connection && !organization) {\n throw new TypeError(\n `Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`,\n );\n }\n\n const query = toQueryString({\n code_challenge: codeChallenge,\n code_challenge_method: codeChallengeMethod,\n connection,\n organization,\n domain_hint: domainHint,\n login_hint: loginHint,\n provider,\n provider_query_params: providerQueryParams,\n provider_scopes: providerScopes,\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n state,\n });\n\n return `${this.workos.baseURL}/sso/authorize?${query}`;\n }\n\n /**\n * Generates an authorization URL with PKCE parameters automatically generated.\n * Use this for public clients (CLI apps, Electron, mobile) that cannot\n * securely store a client secret.\n *\n * @returns Object containing url, state, and codeVerifier\n *\n * @example\n * ```typescript\n * const { url, state, codeVerifier } = await workos.sso.getAuthorizationUrlWithPKCE({\n * connection: 'conn_123',\n * clientId: 'client_123',\n * redirectUri: 'myapp://callback',\n * });\n *\n * // Store state and codeVerifier securely, then redirect user to url\n * // After callback, exchange the code:\n * const { profile, accessToken } = await workos.sso.getProfileAndToken({\n * code: authorizationCode,\n * codeVerifier,\n * clientId: 'client_123',\n * });\n * ```\n */\n async getAuthorizationUrlWithPKCE(\n options: Omit<\n SSOAuthorizationURLOptions,\n 'codeChallenge' | 'codeChallengeMethod' | 'state'\n >,\n ): Promise<SSOPKCEAuthorizationURLResult> {\n const {\n connection,\n clientId,\n domainHint,\n loginHint,\n organization,\n provider,\n providerQueryParams,\n providerScopes,\n redirectUri,\n } = options;\n\n if (!provider && !connection && !organization) {\n throw new TypeError(\n `Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`,\n );\n }\n\n // Generate PKCE parameters\n const pkce = await this.workos.pkce.generate();\n\n // Generate secure random state\n const state = this.workos.pkce.generateCodeVerifier(43);\n\n const query = toQueryString({\n code_challenge: pkce.codeChallenge,\n code_challenge_method: 'S256',\n connection,\n organization,\n domain_hint: domainHint,\n login_hint: loginHint,\n provider,\n provider_query_params: providerQueryParams,\n provider_scopes: providerScopes,\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n state,\n });\n\n const url = `${this.workos.baseURL}/sso/authorize?${query}`;\n\n return { url, state, codeVerifier: pkce.codeVerifier };\n }\n\n async getConnection(id: string): Promise<Connection> {\n const { data } = await this.workos.get<ConnectionResponse>(\n `/connections/${id}`,\n );\n\n return deserializeConnection(data);\n }\n\n /**\n * Exchange an authorization code for a profile and access token.\n *\n * Auto-detects public vs confidential client mode:\n * - If codeVerifier is provided: Uses PKCE flow (public client)\n * - If no codeVerifier: Uses client_secret from API key (confidential client)\n * - If both: Uses both client_secret AND codeVerifier (confidential client with PKCE)\n *\n * Using PKCE with confidential clients is recommended by OAuth 2.1 for defense\n * in depth and provides additional CSRF protection on the authorization flow.\n *\n * @throws Error if neither codeVerifier nor API key is available\n */\n async getProfileAndToken<\n CustomAttributesType extends UnknownRecord = UnknownRecord,\n >({\n code,\n clientId,\n codeVerifier,\n }: GetProfileAndTokenOptions): Promise<\n ProfileAndToken<CustomAttributesType>\n > {\n // Validate codeVerifier is not an empty string (common mistake)\n if (codeVerifier !== undefined && codeVerifier.trim() === '') {\n throw new TypeError(\n 'codeVerifier cannot be an empty string. ' +\n 'Generate a valid PKCE pair using workos.pkce.generate().',\n );\n }\n\n const hasApiKey = !!this.workos.key;\n const hasPKCE = !!codeVerifier;\n\n if (!hasPKCE && !hasApiKey) {\n throw new TypeError(\n 'getProfileAndToken requires either a codeVerifier (for public clients) ' +\n 'or an API key configured on the WorkOS instance (for confidential clients).',\n );\n }\n\n const form = new URLSearchParams({\n client_id: clientId,\n grant_type: 'authorization_code',\n code,\n });\n\n // Support PKCE with confidential clients (OAuth 2.1 best practice)\n // Both can be sent together for defense in depth\n if (hasPKCE) {\n form.set('code_verifier', codeVerifier);\n }\n if (hasApiKey) {\n form.set('client_secret', this.workos.key as string);\n }\n\n const { data } = await this.workos.post<\n ProfileAndTokenResponse<CustomAttributesType>\n >('/sso/token', form, { skipApiKeyCheck: !hasApiKey });\n\n return deserializeProfileAndToken(data);\n }\n\n async getProfile<CustomAttributesType extends UnknownRecord = UnknownRecord>({\n accessToken,\n }: GetProfileOptions): Promise<Profile<CustomAttributesType>> {\n const { data } = await this.workos.get<\n ProfileResponse<CustomAttributesType>\n >('/sso/profile', {\n accessToken,\n });\n\n return deserializeProfile(data);\n }\n}\n"],"mappings":";;;;;;;;;AA0BA,IAAa,MAAb,MAAiB;CACf,YAAY,AAAiBA,QAAgB;EAAhB;;CAE7B,MAAM,gBACJ,SACwE;AACxE,SAAO,IAAIC,gDACT,MAAMC,+DACJ,KAAK,QACL,gBACAC,qEACA,UAAUC,4FAAgC,QAAQ,GAAG,OACtD,GACA,WACCF,+DACE,KAAK,QACL,gBACAC,qEACA,OACD,EACH,UAAUC,4FAAgC,QAAQ,GAAG,OACtD;;CAEH,MAAM,iBAAiB,IAAY;AACjC,QAAM,KAAK,OAAO,OAAO,gBAAgB,KAAK;;CAGhD,oBAAoB,SAA6C;EAC/D,MAAM,EACJ,eACA,qBACA,YACA,UACA,YACA,WACA,cACA,UACA,qBACA,gBACA,aACA,UACE;AAEJ,MAAI,CAAC,YAAY,CAAC,cAAc,CAAC,aAC/B,OAAM,IAAI,UACR,8FACD;EAGH,MAAM,QAAQC,gDAAc;GAC1B,gBAAgB;GAChB,uBAAuB;GACvB;GACA;GACA,aAAa;GACb,YAAY;GACZ;GACA,uBAAuB;GACvB,iBAAiB;GACjB,WAAW;GACX,cAAc;GACd,eAAe;GACf;GACD,CAAC;AAEF,SAAO,GAAG,KAAK,OAAO,QAAQ,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BjD,MAAM,4BACJ,SAIwC;EACxC,MAAM,EACJ,YACA,UACA,YACA,WACA,cACA,UACA,qBACA,gBACA,gBACE;AAEJ,MAAI,CAAC,YAAY,CAAC,cAAc,CAAC,aAC/B,OAAM,IAAI,UACR,8FACD;EAIH,MAAM,OAAO,MAAM,KAAK,OAAO,KAAK,UAAU;EAG9C,MAAM,QAAQ,KAAK,OAAO,KAAK,qBAAqB,GAAG;EAEvD,MAAM,QAAQA,gDAAc;GAC1B,gBAAgB,KAAK;GACrB,uBAAuB;GACvB;GACA;GACA,aAAa;GACb,YAAY;GACZ;GACA,uBAAuB;GACvB,iBAAiB;GACjB,WAAW;GACX,cAAc;GACd,eAAe;GACf;GACD,CAAC;AAIF,SAAO;GAAE,KAFG,GAAG,KAAK,OAAO,QAAQ,iBAAiB;GAEtC;GAAO,cAAc,KAAK;GAAc;;CAGxD,MAAM,cAAc,IAAiC;EACnD,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,IACjC,gBAAgB,KACjB;AAED,SAAOF,oEAAsB,KAAK;;;;;;;;;;;;;;;CAgBpC,MAAM,mBAEJ,EACA,MACA,UACA,gBAGA;AAEA,MAAI,iBAAiB,UAAa,aAAa,MAAM,KAAK,GACxD,OAAM,IAAI,UACR,mGAED;EAGH,MAAM,YAAY,CAAC,CAAC,KAAK,OAAO;EAChC,MAAM,UAAU,CAAC,CAAC;AAElB,MAAI,CAAC,WAAW,CAAC,UACf,OAAM,IAAI,UACR,qJAED;EAGH,MAAM,OAAO,IAAI,gBAAgB;GAC/B,WAAW;GACX,YAAY;GACZ;GACD,CAAC;AAIF,MAAI,QACF,MAAK,IAAI,iBAAiB,aAAa;AAEzC,MAAI,UACF,MAAK,IAAI,iBAAiB,KAAK,OAAO,IAAc;EAGtD,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,KAEjC,cAAc,MAAM,EAAE,iBAAiB,CAAC,WAAW,CAAC;AAEtD,SAAOG,gFAA2B,KAAK;;CAGzC,MAAM,WAAuE,EAC3E,eAC4D;EAC5D,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,IAEjC,gBAAgB,EAChB,aACD,CAAC;AAEF,SAAOC,8DAAmB,KAAK"}
package/lib/sso/sso.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { SSOAuthorizationURLOptions } from "./interfaces/authorization-url-options.interface.cjs";
1
+ import { SSOAuthorizationURLOptions, SSOPKCEAuthorizationURLResult } from "./interfaces/authorization-url-options.interface.cjs";
2
2
  import { Connection } from "./interfaces/connection.interface.cjs";
3
3
  import { GetProfileOptions } from "./interfaces/get-profile-options.interface.cjs";
4
4
  import { GetProfileAndTokenOptions } from "./interfaces/get-profile-and-token-options.interface.cjs";
@@ -16,10 +16,49 @@ declare class SSO {
16
16
  listConnections(options?: ListConnectionsOptions): Promise<AutoPaginatable<Connection, SerializedListConnectionsOptions>>;
17
17
  deleteConnection(id: string): Promise<void>;
18
18
  getAuthorizationUrl(options: SSOAuthorizationURLOptions): string;
19
+ /**
20
+ * Generates an authorization URL with PKCE parameters automatically generated.
21
+ * Use this for public clients (CLI apps, Electron, mobile) that cannot
22
+ * securely store a client secret.
23
+ *
24
+ * @returns Object containing url, state, and codeVerifier
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const { url, state, codeVerifier } = await workos.sso.getAuthorizationUrlWithPKCE({
29
+ * connection: 'conn_123',
30
+ * clientId: 'client_123',
31
+ * redirectUri: 'myapp://callback',
32
+ * });
33
+ *
34
+ * // Store state and codeVerifier securely, then redirect user to url
35
+ * // After callback, exchange the code:
36
+ * const { profile, accessToken } = await workos.sso.getProfileAndToken({
37
+ * code: authorizationCode,
38
+ * codeVerifier,
39
+ * clientId: 'client_123',
40
+ * });
41
+ * ```
42
+ */
43
+ getAuthorizationUrlWithPKCE(options: Omit<SSOAuthorizationURLOptions, 'codeChallenge' | 'codeChallengeMethod' | 'state'>): Promise<SSOPKCEAuthorizationURLResult>;
19
44
  getConnection(id: string): Promise<Connection>;
45
+ /**
46
+ * Exchange an authorization code for a profile and access token.
47
+ *
48
+ * Auto-detects public vs confidential client mode:
49
+ * - If codeVerifier is provided: Uses PKCE flow (public client)
50
+ * - If no codeVerifier: Uses client_secret from API key (confidential client)
51
+ * - If both: Uses both client_secret AND codeVerifier (confidential client with PKCE)
52
+ *
53
+ * Using PKCE with confidential clients is recommended by OAuth 2.1 for defense
54
+ * in depth and provides additional CSRF protection on the authorization flow.
55
+ *
56
+ * @throws Error if neither codeVerifier nor API key is available
57
+ */
20
58
  getProfileAndToken<CustomAttributesType extends UnknownRecord = UnknownRecord>({
21
59
  code,
22
- clientId
60
+ clientId,
61
+ codeVerifier
23
62
  }: GetProfileAndTokenOptions): Promise<ProfileAndToken<CustomAttributesType>>;
24
63
  getProfile<CustomAttributesType extends UnknownRecord = UnknownRecord>({
25
64
  accessToken
package/lib/sso/sso.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SSOAuthorizationURLOptions } from "./interfaces/authorization-url-options.interface.js";
1
+ import { SSOAuthorizationURLOptions, SSOPKCEAuthorizationURLResult } from "./interfaces/authorization-url-options.interface.js";
2
2
  import { Connection } from "./interfaces/connection.interface.js";
3
3
  import { GetProfileOptions } from "./interfaces/get-profile-options.interface.js";
4
4
  import { GetProfileAndTokenOptions } from "./interfaces/get-profile-and-token-options.interface.js";
@@ -16,10 +16,49 @@ declare class SSO {
16
16
  listConnections(options?: ListConnectionsOptions): Promise<AutoPaginatable<Connection, SerializedListConnectionsOptions>>;
17
17
  deleteConnection(id: string): Promise<void>;
18
18
  getAuthorizationUrl(options: SSOAuthorizationURLOptions): string;
19
+ /**
20
+ * Generates an authorization URL with PKCE parameters automatically generated.
21
+ * Use this for public clients (CLI apps, Electron, mobile) that cannot
22
+ * securely store a client secret.
23
+ *
24
+ * @returns Object containing url, state, and codeVerifier
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * const { url, state, codeVerifier } = await workos.sso.getAuthorizationUrlWithPKCE({
29
+ * connection: 'conn_123',
30
+ * clientId: 'client_123',
31
+ * redirectUri: 'myapp://callback',
32
+ * });
33
+ *
34
+ * // Store state and codeVerifier securely, then redirect user to url
35
+ * // After callback, exchange the code:
36
+ * const { profile, accessToken } = await workos.sso.getProfileAndToken({
37
+ * code: authorizationCode,
38
+ * codeVerifier,
39
+ * clientId: 'client_123',
40
+ * });
41
+ * ```
42
+ */
43
+ getAuthorizationUrlWithPKCE(options: Omit<SSOAuthorizationURLOptions, 'codeChallenge' | 'codeChallengeMethod' | 'state'>): Promise<SSOPKCEAuthorizationURLResult>;
19
44
  getConnection(id: string): Promise<Connection>;
45
+ /**
46
+ * Exchange an authorization code for a profile and access token.
47
+ *
48
+ * Auto-detects public vs confidential client mode:
49
+ * - If codeVerifier is provided: Uses PKCE flow (public client)
50
+ * - If no codeVerifier: Uses client_secret from API key (confidential client)
51
+ * - If both: Uses both client_secret AND codeVerifier (confidential client with PKCE)
52
+ *
53
+ * Using PKCE with confidential clients is recommended by OAuth 2.1 for defense
54
+ * in depth and provides additional CSRF protection on the authorization flow.
55
+ *
56
+ * @throws Error if neither codeVerifier nor API key is available
57
+ */
20
58
  getProfileAndToken<CustomAttributesType extends UnknownRecord = UnknownRecord>({
21
59
  code,
22
- clientId
60
+ clientId,
61
+ codeVerifier
23
62
  }: GetProfileAndTokenOptions): Promise<ProfileAndToken<CustomAttributesType>>;
24
63
  getProfile<CustomAttributesType extends UnknownRecord = UnknownRecord>({
25
64
  accessToken
package/lib/sso/sso.js CHANGED
@@ -1,10 +1,10 @@
1
- import { getAuthorizationUrl } from "../client/sso.js";
1
+ import { AutoPaginatable } from "../common/utils/pagination.js";
2
2
  import { deserializeConnection } from "./serializers/connection.serializer.js";
3
3
  import { serializeListConnectionsOptions } from "./serializers/list-connections-options.serializer.js";
4
4
  import { deserializeProfile } from "./serializers/profile.serializer.js";
5
5
  import { deserializeProfileAndToken } from "./serializers/profile-and-token.serializer.js";
6
- import { AutoPaginatable } from "../common/utils/pagination.js";
7
6
  import { fetchAndDeserialize } from "../common/utils/fetch-and-deserialize.js";
7
+ import { toQueryString } from "../common/utils/query-string.js";
8
8
 
9
9
  //#region src/sso/sso.ts
10
10
  var SSO = class {
@@ -18,23 +18,105 @@ var SSO = class {
18
18
  await this.workos.delete(`/connections/${id}`);
19
19
  }
20
20
  getAuthorizationUrl(options) {
21
- return getAuthorizationUrl({
22
- ...options,
23
- baseURL: this.workos.baseURL
21
+ const { codeChallenge, codeChallengeMethod, connection, clientId, domainHint, loginHint, organization, provider, providerQueryParams, providerScopes, redirectUri, state } = options;
22
+ if (!provider && !connection && !organization) throw new TypeError(`Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`);
23
+ const query = toQueryString({
24
+ code_challenge: codeChallenge,
25
+ code_challenge_method: codeChallengeMethod,
26
+ connection,
27
+ organization,
28
+ domain_hint: domainHint,
29
+ login_hint: loginHint,
30
+ provider,
31
+ provider_query_params: providerQueryParams,
32
+ provider_scopes: providerScopes,
33
+ client_id: clientId,
34
+ redirect_uri: redirectUri,
35
+ response_type: "code",
36
+ state
37
+ });
38
+ return `${this.workos.baseURL}/sso/authorize?${query}`;
39
+ }
40
+ /**
41
+ * Generates an authorization URL with PKCE parameters automatically generated.
42
+ * Use this for public clients (CLI apps, Electron, mobile) that cannot
43
+ * securely store a client secret.
44
+ *
45
+ * @returns Object containing url, state, and codeVerifier
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * const { url, state, codeVerifier } = await workos.sso.getAuthorizationUrlWithPKCE({
50
+ * connection: 'conn_123',
51
+ * clientId: 'client_123',
52
+ * redirectUri: 'myapp://callback',
53
+ * });
54
+ *
55
+ * // Store state and codeVerifier securely, then redirect user to url
56
+ * // After callback, exchange the code:
57
+ * const { profile, accessToken } = await workos.sso.getProfileAndToken({
58
+ * code: authorizationCode,
59
+ * codeVerifier,
60
+ * clientId: 'client_123',
61
+ * });
62
+ * ```
63
+ */
64
+ async getAuthorizationUrlWithPKCE(options) {
65
+ const { connection, clientId, domainHint, loginHint, organization, provider, providerQueryParams, providerScopes, redirectUri } = options;
66
+ if (!provider && !connection && !organization) throw new TypeError(`Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`);
67
+ const pkce = await this.workos.pkce.generate();
68
+ const state = this.workos.pkce.generateCodeVerifier(43);
69
+ const query = toQueryString({
70
+ code_challenge: pkce.codeChallenge,
71
+ code_challenge_method: "S256",
72
+ connection,
73
+ organization,
74
+ domain_hint: domainHint,
75
+ login_hint: loginHint,
76
+ provider,
77
+ provider_query_params: providerQueryParams,
78
+ provider_scopes: providerScopes,
79
+ client_id: clientId,
80
+ redirect_uri: redirectUri,
81
+ response_type: "code",
82
+ state
24
83
  });
84
+ return {
85
+ url: `${this.workos.baseURL}/sso/authorize?${query}`,
86
+ state,
87
+ codeVerifier: pkce.codeVerifier
88
+ };
25
89
  }
26
90
  async getConnection(id) {
27
91
  const { data } = await this.workos.get(`/connections/${id}`);
28
92
  return deserializeConnection(data);
29
93
  }
30
- async getProfileAndToken({ code, clientId }) {
94
+ /**
95
+ * Exchange an authorization code for a profile and access token.
96
+ *
97
+ * Auto-detects public vs confidential client mode:
98
+ * - If codeVerifier is provided: Uses PKCE flow (public client)
99
+ * - If no codeVerifier: Uses client_secret from API key (confidential client)
100
+ * - If both: Uses both client_secret AND codeVerifier (confidential client with PKCE)
101
+ *
102
+ * Using PKCE with confidential clients is recommended by OAuth 2.1 for defense
103
+ * in depth and provides additional CSRF protection on the authorization flow.
104
+ *
105
+ * @throws Error if neither codeVerifier nor API key is available
106
+ */
107
+ async getProfileAndToken({ code, clientId, codeVerifier }) {
108
+ if (codeVerifier !== void 0 && codeVerifier.trim() === "") throw new TypeError("codeVerifier cannot be an empty string. Generate a valid PKCE pair using workos.pkce.generate().");
109
+ const hasApiKey = !!this.workos.key;
110
+ const hasPKCE = !!codeVerifier;
111
+ if (!hasPKCE && !hasApiKey) throw new TypeError("getProfileAndToken requires either a codeVerifier (for public clients) or an API key configured on the WorkOS instance (for confidential clients).");
31
112
  const form = new URLSearchParams({
32
113
  client_id: clientId,
33
- client_secret: this.workos.key,
34
114
  grant_type: "authorization_code",
35
115
  code
36
116
  });
37
- const { data } = await this.workos.post("/sso/token", form);
117
+ if (hasPKCE) form.set("code_verifier", codeVerifier);
118
+ if (hasApiKey) form.set("client_secret", this.workos.key);
119
+ const { data } = await this.workos.post("/sso/token", form, { skipApiKeyCheck: !hasApiKey });
38
120
  return deserializeProfileAndToken(data);
39
121
  }
40
122
  async getProfile({ accessToken }) {
@@ -1 +1 @@
1
- {"version":3,"file":"sso.js","names":["workos: WorkOS","clientSSO.getAuthorizationUrl"],"sources":["../../src/sso/sso.ts"],"sourcesContent":["import * as clientSSO from '../client/sso';\nimport { UnknownRecord } from '../common/interfaces/unknown-record.interface';\nimport { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize';\nimport { AutoPaginatable } from '../common/utils/pagination';\nimport { WorkOS } from '../workos';\nimport {\n Connection,\n ConnectionResponse,\n GetProfileAndTokenOptions,\n GetProfileOptions,\n ListConnectionsOptions,\n Profile,\n ProfileAndToken,\n ProfileAndTokenResponse,\n ProfileResponse,\n SSOAuthorizationURLOptions,\n SerializedListConnectionsOptions,\n} from './interfaces';\nimport {\n deserializeConnection,\n deserializeProfile,\n deserializeProfileAndToken,\n serializeListConnectionsOptions,\n} from './serializers';\n\nexport class SSO {\n constructor(private readonly workos: WorkOS) {}\n\n async listConnections(\n options?: ListConnectionsOptions,\n ): Promise<AutoPaginatable<Connection, SerializedListConnectionsOptions>> {\n return new AutoPaginatable(\n await fetchAndDeserialize<ConnectionResponse, Connection>(\n this.workos,\n '/connections',\n deserializeConnection,\n options ? serializeListConnectionsOptions(options) : undefined,\n ),\n (params) =>\n fetchAndDeserialize<ConnectionResponse, Connection>(\n this.workos,\n '/connections',\n deserializeConnection,\n params,\n ),\n options ? serializeListConnectionsOptions(options) : undefined,\n );\n }\n async deleteConnection(id: string) {\n await this.workos.delete(`/connections/${id}`);\n }\n\n getAuthorizationUrl(options: SSOAuthorizationURLOptions): string {\n // Delegate to client implementation\n return clientSSO.getAuthorizationUrl({\n ...options,\n baseURL: this.workos.baseURL,\n });\n }\n\n async getConnection(id: string): Promise<Connection> {\n const { data } = await this.workos.get<ConnectionResponse>(\n `/connections/${id}`,\n );\n\n return deserializeConnection(data);\n }\n\n async getProfileAndToken<\n CustomAttributesType extends UnknownRecord = UnknownRecord,\n >({\n code,\n clientId,\n }: GetProfileAndTokenOptions): Promise<\n ProfileAndToken<CustomAttributesType>\n > {\n const form = new URLSearchParams({\n client_id: clientId,\n client_secret: this.workos.key as string,\n grant_type: 'authorization_code',\n code,\n });\n\n const { data } = await this.workos.post<\n ProfileAndTokenResponse<CustomAttributesType>\n >('/sso/token', form);\n\n return deserializeProfileAndToken(data);\n }\n\n async getProfile<CustomAttributesType extends UnknownRecord = UnknownRecord>({\n accessToken,\n }: GetProfileOptions): Promise<Profile<CustomAttributesType>> {\n const { data } = await this.workos.get<\n ProfileResponse<CustomAttributesType>\n >('/sso/profile', {\n accessToken,\n });\n\n return deserializeProfile(data);\n }\n}\n"],"mappings":";;;;;;;;;AAyBA,IAAa,MAAb,MAAiB;CACf,YAAY,AAAiBA,QAAgB;EAAhB;;CAE7B,MAAM,gBACJ,SACwE;AACxE,SAAO,IAAI,gBACT,MAAM,oBACJ,KAAK,QACL,gBACA,uBACA,UAAU,gCAAgC,QAAQ,GAAG,OACtD,GACA,WACC,oBACE,KAAK,QACL,gBACA,uBACA,OACD,EACH,UAAU,gCAAgC,QAAQ,GAAG,OACtD;;CAEH,MAAM,iBAAiB,IAAY;AACjC,QAAM,KAAK,OAAO,OAAO,gBAAgB,KAAK;;CAGhD,oBAAoB,SAA6C;AAE/D,SAAOC,oBAA8B;GACnC,GAAG;GACH,SAAS,KAAK,OAAO;GACtB,CAAC;;CAGJ,MAAM,cAAc,IAAiC;EACnD,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,IACjC,gBAAgB,KACjB;AAED,SAAO,sBAAsB,KAAK;;CAGpC,MAAM,mBAEJ,EACA,MACA,YAGA;EACA,MAAM,OAAO,IAAI,gBAAgB;GAC/B,WAAW;GACX,eAAe,KAAK,OAAO;GAC3B,YAAY;GACZ;GACD,CAAC;EAEF,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,KAEjC,cAAc,KAAK;AAErB,SAAO,2BAA2B,KAAK;;CAGzC,MAAM,WAAuE,EAC3E,eAC4D;EAC5D,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,IAEjC,gBAAgB,EAChB,aACD,CAAC;AAEF,SAAO,mBAAmB,KAAK"}
1
+ {"version":3,"file":"sso.js","names":["workos: WorkOS"],"sources":["../../src/sso/sso.ts"],"sourcesContent":["import { UnknownRecord } from '../common/interfaces/unknown-record.interface';\nimport { fetchAndDeserialize } from '../common/utils/fetch-and-deserialize';\nimport { AutoPaginatable } from '../common/utils/pagination';\nimport { toQueryString } from '../common/utils/query-string';\nimport { WorkOS } from '../workos';\nimport {\n Connection,\n ConnectionResponse,\n GetProfileAndTokenOptions,\n GetProfileOptions,\n ListConnectionsOptions,\n Profile,\n ProfileAndToken,\n ProfileAndTokenResponse,\n ProfileResponse,\n SSOAuthorizationURLOptions,\n SSOPKCEAuthorizationURLResult,\n SerializedListConnectionsOptions,\n} from './interfaces';\nimport {\n deserializeConnection,\n deserializeProfile,\n deserializeProfileAndToken,\n serializeListConnectionsOptions,\n} from './serializers';\n\nexport class SSO {\n constructor(private readonly workos: WorkOS) {}\n\n async listConnections(\n options?: ListConnectionsOptions,\n ): Promise<AutoPaginatable<Connection, SerializedListConnectionsOptions>> {\n return new AutoPaginatable(\n await fetchAndDeserialize<ConnectionResponse, Connection>(\n this.workos,\n '/connections',\n deserializeConnection,\n options ? serializeListConnectionsOptions(options) : undefined,\n ),\n (params) =>\n fetchAndDeserialize<ConnectionResponse, Connection>(\n this.workos,\n '/connections',\n deserializeConnection,\n params,\n ),\n options ? serializeListConnectionsOptions(options) : undefined,\n );\n }\n async deleteConnection(id: string) {\n await this.workos.delete(`/connections/${id}`);\n }\n\n getAuthorizationUrl(options: SSOAuthorizationURLOptions): string {\n const {\n codeChallenge,\n codeChallengeMethod,\n connection,\n clientId,\n domainHint,\n loginHint,\n organization,\n provider,\n providerQueryParams,\n providerScopes,\n redirectUri,\n state,\n } = options;\n\n if (!provider && !connection && !organization) {\n throw new TypeError(\n `Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`,\n );\n }\n\n const query = toQueryString({\n code_challenge: codeChallenge,\n code_challenge_method: codeChallengeMethod,\n connection,\n organization,\n domain_hint: domainHint,\n login_hint: loginHint,\n provider,\n provider_query_params: providerQueryParams,\n provider_scopes: providerScopes,\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n state,\n });\n\n return `${this.workos.baseURL}/sso/authorize?${query}`;\n }\n\n /**\n * Generates an authorization URL with PKCE parameters automatically generated.\n * Use this for public clients (CLI apps, Electron, mobile) that cannot\n * securely store a client secret.\n *\n * @returns Object containing url, state, and codeVerifier\n *\n * @example\n * ```typescript\n * const { url, state, codeVerifier } = await workos.sso.getAuthorizationUrlWithPKCE({\n * connection: 'conn_123',\n * clientId: 'client_123',\n * redirectUri: 'myapp://callback',\n * });\n *\n * // Store state and codeVerifier securely, then redirect user to url\n * // After callback, exchange the code:\n * const { profile, accessToken } = await workos.sso.getProfileAndToken({\n * code: authorizationCode,\n * codeVerifier,\n * clientId: 'client_123',\n * });\n * ```\n */\n async getAuthorizationUrlWithPKCE(\n options: Omit<\n SSOAuthorizationURLOptions,\n 'codeChallenge' | 'codeChallengeMethod' | 'state'\n >,\n ): Promise<SSOPKCEAuthorizationURLResult> {\n const {\n connection,\n clientId,\n domainHint,\n loginHint,\n organization,\n provider,\n providerQueryParams,\n providerScopes,\n redirectUri,\n } = options;\n\n if (!provider && !connection && !organization) {\n throw new TypeError(\n `Incomplete arguments. Need to specify either a 'connection', 'organization', or 'provider'.`,\n );\n }\n\n // Generate PKCE parameters\n const pkce = await this.workos.pkce.generate();\n\n // Generate secure random state\n const state = this.workos.pkce.generateCodeVerifier(43);\n\n const query = toQueryString({\n code_challenge: pkce.codeChallenge,\n code_challenge_method: 'S256',\n connection,\n organization,\n domain_hint: domainHint,\n login_hint: loginHint,\n provider,\n provider_query_params: providerQueryParams,\n provider_scopes: providerScopes,\n client_id: clientId,\n redirect_uri: redirectUri,\n response_type: 'code',\n state,\n });\n\n const url = `${this.workos.baseURL}/sso/authorize?${query}`;\n\n return { url, state, codeVerifier: pkce.codeVerifier };\n }\n\n async getConnection(id: string): Promise<Connection> {\n const { data } = await this.workos.get<ConnectionResponse>(\n `/connections/${id}`,\n );\n\n return deserializeConnection(data);\n }\n\n /**\n * Exchange an authorization code for a profile and access token.\n *\n * Auto-detects public vs confidential client mode:\n * - If codeVerifier is provided: Uses PKCE flow (public client)\n * - If no codeVerifier: Uses client_secret from API key (confidential client)\n * - If both: Uses both client_secret AND codeVerifier (confidential client with PKCE)\n *\n * Using PKCE with confidential clients is recommended by OAuth 2.1 for defense\n * in depth and provides additional CSRF protection on the authorization flow.\n *\n * @throws Error if neither codeVerifier nor API key is available\n */\n async getProfileAndToken<\n CustomAttributesType extends UnknownRecord = UnknownRecord,\n >({\n code,\n clientId,\n codeVerifier,\n }: GetProfileAndTokenOptions): Promise<\n ProfileAndToken<CustomAttributesType>\n > {\n // Validate codeVerifier is not an empty string (common mistake)\n if (codeVerifier !== undefined && codeVerifier.trim() === '') {\n throw new TypeError(\n 'codeVerifier cannot be an empty string. ' +\n 'Generate a valid PKCE pair using workos.pkce.generate().',\n );\n }\n\n const hasApiKey = !!this.workos.key;\n const hasPKCE = !!codeVerifier;\n\n if (!hasPKCE && !hasApiKey) {\n throw new TypeError(\n 'getProfileAndToken requires either a codeVerifier (for public clients) ' +\n 'or an API key configured on the WorkOS instance (for confidential clients).',\n );\n }\n\n const form = new URLSearchParams({\n client_id: clientId,\n grant_type: 'authorization_code',\n code,\n });\n\n // Support PKCE with confidential clients (OAuth 2.1 best practice)\n // Both can be sent together for defense in depth\n if (hasPKCE) {\n form.set('code_verifier', codeVerifier);\n }\n if (hasApiKey) {\n form.set('client_secret', this.workos.key as string);\n }\n\n const { data } = await this.workos.post<\n ProfileAndTokenResponse<CustomAttributesType>\n >('/sso/token', form, { skipApiKeyCheck: !hasApiKey });\n\n return deserializeProfileAndToken(data);\n }\n\n async getProfile<CustomAttributesType extends UnknownRecord = UnknownRecord>({\n accessToken,\n }: GetProfileOptions): Promise<Profile<CustomAttributesType>> {\n const { data } = await this.workos.get<\n ProfileResponse<CustomAttributesType>\n >('/sso/profile', {\n accessToken,\n });\n\n return deserializeProfile(data);\n }\n}\n"],"mappings":";;;;;;;;;AA0BA,IAAa,MAAb,MAAiB;CACf,YAAY,AAAiBA,QAAgB;EAAhB;;CAE7B,MAAM,gBACJ,SACwE;AACxE,SAAO,IAAI,gBACT,MAAM,oBACJ,KAAK,QACL,gBACA,uBACA,UAAU,gCAAgC,QAAQ,GAAG,OACtD,GACA,WACC,oBACE,KAAK,QACL,gBACA,uBACA,OACD,EACH,UAAU,gCAAgC,QAAQ,GAAG,OACtD;;CAEH,MAAM,iBAAiB,IAAY;AACjC,QAAM,KAAK,OAAO,OAAO,gBAAgB,KAAK;;CAGhD,oBAAoB,SAA6C;EAC/D,MAAM,EACJ,eACA,qBACA,YACA,UACA,YACA,WACA,cACA,UACA,qBACA,gBACA,aACA,UACE;AAEJ,MAAI,CAAC,YAAY,CAAC,cAAc,CAAC,aAC/B,OAAM,IAAI,UACR,8FACD;EAGH,MAAM,QAAQ,cAAc;GAC1B,gBAAgB;GAChB,uBAAuB;GACvB;GACA;GACA,aAAa;GACb,YAAY;GACZ;GACA,uBAAuB;GACvB,iBAAiB;GACjB,WAAW;GACX,cAAc;GACd,eAAe;GACf;GACD,CAAC;AAEF,SAAO,GAAG,KAAK,OAAO,QAAQ,iBAAiB;;;;;;;;;;;;;;;;;;;;;;;;;;CA2BjD,MAAM,4BACJ,SAIwC;EACxC,MAAM,EACJ,YACA,UACA,YACA,WACA,cACA,UACA,qBACA,gBACA,gBACE;AAEJ,MAAI,CAAC,YAAY,CAAC,cAAc,CAAC,aAC/B,OAAM,IAAI,UACR,8FACD;EAIH,MAAM,OAAO,MAAM,KAAK,OAAO,KAAK,UAAU;EAG9C,MAAM,QAAQ,KAAK,OAAO,KAAK,qBAAqB,GAAG;EAEvD,MAAM,QAAQ,cAAc;GAC1B,gBAAgB,KAAK;GACrB,uBAAuB;GACvB;GACA;GACA,aAAa;GACb,YAAY;GACZ;GACA,uBAAuB;GACvB,iBAAiB;GACjB,WAAW;GACX,cAAc;GACd,eAAe;GACf;GACD,CAAC;AAIF,SAAO;GAAE,KAFG,GAAG,KAAK,OAAO,QAAQ,iBAAiB;GAEtC;GAAO,cAAc,KAAK;GAAc;;CAGxD,MAAM,cAAc,IAAiC;EACnD,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,IACjC,gBAAgB,KACjB;AAED,SAAO,sBAAsB,KAAK;;;;;;;;;;;;;;;CAgBpC,MAAM,mBAEJ,EACA,MACA,UACA,gBAGA;AAEA,MAAI,iBAAiB,UAAa,aAAa,MAAM,KAAK,GACxD,OAAM,IAAI,UACR,mGAED;EAGH,MAAM,YAAY,CAAC,CAAC,KAAK,OAAO;EAChC,MAAM,UAAU,CAAC,CAAC;AAElB,MAAI,CAAC,WAAW,CAAC,UACf,OAAM,IAAI,UACR,qJAED;EAGH,MAAM,OAAO,IAAI,gBAAgB;GAC/B,WAAW;GACX,YAAY;GACZ;GACD,CAAC;AAIF,MAAI,QACF,MAAK,IAAI,iBAAiB,aAAa;AAEzC,MAAI,UACF,MAAK,IAAI,iBAAiB,KAAK,OAAO,IAAc;EAGtD,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,KAEjC,cAAc,MAAM,EAAE,iBAAiB,CAAC,WAAW,CAAC;AAEtD,SAAO,2BAA2B,KAAK;;CAGzC,MAAM,WAAuE,EAC3E,eAC4D;EAC5D,MAAM,EAAE,SAAS,MAAM,KAAK,OAAO,IAEjC,gBAAgB,EAChB,aACD,CAAC;AAEF,SAAO,mBAAmB,KAAK"}
@@ -1,4 +1,4 @@
1
- import { AuthenticateWithOptionsBase, SerializedAuthenticateWithPKCEBase } from "./authenticate-with-options-base.interface.cjs";
1
+ import { AuthenticateWithOptionsBase, SerializedAuthenticatePublicClientBase } from "./authenticate-with-options-base.interface.cjs";
2
2
 
3
3
  //#region src/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.d.ts
4
4
  interface AuthenticateWithCodeAndVerifierOptions extends AuthenticateWithOptionsBase {
@@ -6,7 +6,7 @@ interface AuthenticateWithCodeAndVerifierOptions extends AuthenticateWithOptions
6
6
  code: string;
7
7
  invitationToken?: string;
8
8
  }
9
- interface SerializedAuthenticateWithCodeAndVerifierOptions extends SerializedAuthenticateWithPKCEBase {
9
+ interface SerializedAuthenticateWithCodeAndVerifierOptions extends SerializedAuthenticatePublicClientBase {
10
10
  grant_type: 'authorization_code';
11
11
  code_verifier: string;
12
12
  code: string;
@@ -1,4 +1,4 @@
1
- import { AuthenticateWithOptionsBase, SerializedAuthenticateWithPKCEBase } from "./authenticate-with-options-base.interface.js";
1
+ import { AuthenticateWithOptionsBase, SerializedAuthenticatePublicClientBase } from "./authenticate-with-options-base.interface.js";
2
2
 
3
3
  //#region src/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.d.ts
4
4
  interface AuthenticateWithCodeAndVerifierOptions extends AuthenticateWithOptionsBase {
@@ -6,7 +6,7 @@ interface AuthenticateWithCodeAndVerifierOptions extends AuthenticateWithOptions
6
6
  code: string;
7
7
  invitationToken?: string;
8
8
  }
9
- interface SerializedAuthenticateWithCodeAndVerifierOptions extends SerializedAuthenticateWithPKCEBase {
9
+ interface SerializedAuthenticateWithCodeAndVerifierOptions extends SerializedAuthenticatePublicClientBase {
10
10
  grant_type: 'authorization_code';
11
11
  code_verifier: string;
12
12
  code: string;
@@ -4,7 +4,7 @@ interface AuthenticateWithSessionOptions {
4
4
  sealSession: boolean;
5
5
  }
6
6
  interface AuthenticateWithOptionsBase {
7
- clientId: string;
7
+ clientId?: string;
8
8
  ipAddress?: string;
9
9
  userAgent?: string;
10
10
  session?: AuthenticateWithSessionOptions;
@@ -15,11 +15,27 @@ interface SerializedAuthenticateWithOptionsBase {
15
15
  ip_address?: string;
16
16
  user_agent?: string;
17
17
  }
18
- interface SerializedAuthenticateWithPKCEBase {
18
+ /** Base for serialized auth options that don't require client_secret (public clients) */
19
+ interface SerializedAuthenticatePublicClientBase {
19
20
  client_id: string;
20
21
  ip_address?: string;
21
22
  user_agent?: string;
22
23
  }
24
+ /**
25
+ * Utility type for serializer input signatures.
26
+ *
27
+ * Since `clientId` is optional in user-facing interfaces (allowing fallback to
28
+ * the constructor-provided value), but serializers require a resolved string,
29
+ * this type overrides the optional `clientId` with a required one.
30
+ *
31
+ * Usage in serializers:
32
+ * ```
33
+ * const serialize = (options: WithResolvedClientId<SomeOptions>) => ...
34
+ * ```
35
+ */
36
+ type WithResolvedClientId<T> = Omit<T, 'clientId'> & {
37
+ clientId: string;
38
+ };
23
39
  //#endregion
24
- export { AuthenticateWithOptionsBase, AuthenticateWithSessionOptions, SerializedAuthenticateWithOptionsBase, SerializedAuthenticateWithPKCEBase };
40
+ export { AuthenticateWithOptionsBase, AuthenticateWithSessionOptions, SerializedAuthenticatePublicClientBase, SerializedAuthenticateWithOptionsBase, WithResolvedClientId };
25
41
  //# sourceMappingURL=authenticate-with-options-base.interface.d.cts.map
@@ -4,7 +4,7 @@ interface AuthenticateWithSessionOptions {
4
4
  sealSession: boolean;
5
5
  }
6
6
  interface AuthenticateWithOptionsBase {
7
- clientId: string;
7
+ clientId?: string;
8
8
  ipAddress?: string;
9
9
  userAgent?: string;
10
10
  session?: AuthenticateWithSessionOptions;
@@ -15,11 +15,27 @@ interface SerializedAuthenticateWithOptionsBase {
15
15
  ip_address?: string;
16
16
  user_agent?: string;
17
17
  }
18
- interface SerializedAuthenticateWithPKCEBase {
18
+ /** Base for serialized auth options that don't require client_secret (public clients) */
19
+ interface SerializedAuthenticatePublicClientBase {
19
20
  client_id: string;
20
21
  ip_address?: string;
21
22
  user_agent?: string;
22
23
  }
24
+ /**
25
+ * Utility type for serializer input signatures.
26
+ *
27
+ * Since `clientId` is optional in user-facing interfaces (allowing fallback to
28
+ * the constructor-provided value), but serializers require a resolved string,
29
+ * this type overrides the optional `clientId` with a required one.
30
+ *
31
+ * Usage in serializers:
32
+ * ```
33
+ * const serialize = (options: WithResolvedClientId<SomeOptions>) => ...
34
+ * ```
35
+ */
36
+ type WithResolvedClientId<T> = Omit<T, 'clientId'> & {
37
+ clientId: string;
38
+ };
23
39
  //#endregion
24
- export { AuthenticateWithOptionsBase, AuthenticateWithSessionOptions, SerializedAuthenticateWithOptionsBase, SerializedAuthenticateWithPKCEBase };
40
+ export { AuthenticateWithOptionsBase, AuthenticateWithSessionOptions, SerializedAuthenticatePublicClientBase, SerializedAuthenticateWithOptionsBase, WithResolvedClientId };
25
41
  //# sourceMappingURL=authenticate-with-options-base.interface.d.ts.map
@@ -0,0 +1,16 @@
1
+ import { AuthenticateWithOptionsBase, SerializedAuthenticatePublicClientBase } from "./authenticate-with-options-base.interface.cjs";
2
+
3
+ //#region src/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.d.ts
4
+ /** Options for refreshing tokens as a public client (no client_secret required) */
5
+ interface AuthenticateWithRefreshTokenPublicClientOptions extends AuthenticateWithOptionsBase {
6
+ refreshToken: string;
7
+ organizationId?: string;
8
+ }
9
+ interface SerializedAuthenticateWithRefreshTokenPublicClientOptions extends SerializedAuthenticatePublicClientBase {
10
+ grant_type: 'refresh_token';
11
+ refresh_token: string;
12
+ organization_id: string | undefined;
13
+ }
14
+ //#endregion
15
+ export { AuthenticateWithRefreshTokenPublicClientOptions, SerializedAuthenticateWithRefreshTokenPublicClientOptions };
16
+ //# sourceMappingURL=authenticate-with-refresh-token-public-client-options.interface.d.cts.map
@@ -0,0 +1,16 @@
1
+ import { AuthenticateWithOptionsBase, SerializedAuthenticatePublicClientBase } from "./authenticate-with-options-base.interface.js";
2
+
3
+ //#region src/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.d.ts
4
+ /** Options for refreshing tokens as a public client (no client_secret required) */
5
+ interface AuthenticateWithRefreshTokenPublicClientOptions extends AuthenticateWithOptionsBase {
6
+ refreshToken: string;
7
+ organizationId?: string;
8
+ }
9
+ interface SerializedAuthenticateWithRefreshTokenPublicClientOptions extends SerializedAuthenticatePublicClientBase {
10
+ grant_type: 'refresh_token';
11
+ refresh_token: string;
12
+ organization_id: string | undefined;
13
+ }
14
+ //#endregion
15
+ export { AuthenticateWithRefreshTokenPublicClientOptions, SerializedAuthenticateWithRefreshTokenPublicClientOptions };
16
+ //# sourceMappingURL=authenticate-with-refresh-token-public-client-options.interface.d.ts.map
@@ -1,8 +1,17 @@
1
1
  //#region src/user-management/interfaces/authorization-url-options.interface.d.ts
2
- interface UserManagementAuthorizationURLOptions {
3
- clientId: string;
4
- codeChallenge?: string;
5
- codeChallengeMethod?: 'S256';
2
+ /**
3
+ * PKCE fields must be provided together or not at all.
4
+ * Use workos.pkce.generate() to create a valid pair.
5
+ */
6
+ type PKCEFields = {
7
+ codeChallenge?: never;
8
+ codeChallengeMethod?: never;
9
+ } | {
10
+ codeChallenge: string;
11
+ codeChallengeMethod: 'S256';
12
+ };
13
+ interface UserManagementAuthorizationURLBaseOptions {
14
+ clientId?: string;
6
15
  connectionId?: string;
7
16
  organizationId?: string;
8
17
  domainHint?: string;
@@ -15,6 +24,22 @@ interface UserManagementAuthorizationURLOptions {
15
24
  state?: string;
16
25
  screenHint?: 'sign-up' | 'sign-in';
17
26
  }
27
+ type UserManagementAuthorizationURLOptions = UserManagementAuthorizationURLBaseOptions & PKCEFields;
28
+ /**
29
+ * Result of getAuthorizationUrlWithPKCE() containing the URL,
30
+ * state, and PKCE code verifier.
31
+ *
32
+ * The codeVerifier must be stored securely and passed to
33
+ * authenticateWithCode() during token exchange.
34
+ */
35
+ interface PKCEAuthorizationURLResult {
36
+ /** The complete authorization URL to redirect the user to */
37
+ url: string;
38
+ /** The state parameter (auto-generated) */
39
+ state: string;
40
+ /** The PKCE code verifier. Store securely and pass to authenticateWithCode(). */
41
+ codeVerifier: string;
42
+ }
18
43
  //#endregion
19
- export { UserManagementAuthorizationURLOptions };
44
+ export { PKCEAuthorizationURLResult, UserManagementAuthorizationURLOptions };
20
45
  //# sourceMappingURL=authorization-url-options.interface.d.cts.map