@workos-inc/node 8.0.0-rc.7 → 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 (250) 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/exceptions/api-key-required.exception.cjs +15 -0
  41. package/lib/common/exceptions/api-key-required.exception.cjs.map +1 -0
  42. package/lib/common/exceptions/api-key-required.exception.d.cts +10 -0
  43. package/lib/common/exceptions/api-key-required.exception.d.ts +10 -0
  44. package/lib/common/exceptions/api-key-required.exception.js +14 -0
  45. package/lib/common/exceptions/api-key-required.exception.js.map +1 -0
  46. package/lib/common/exceptions/index.cjs +2 -0
  47. package/lib/common/exceptions/index.d.cts +2 -1
  48. package/lib/common/exceptions/index.d.ts +2 -1
  49. package/lib/common/exceptions/index.js +2 -1
  50. package/lib/common/interfaces/event.interface.d.cts +28 -3
  51. package/lib/common/interfaces/event.interface.d.ts +28 -3
  52. package/lib/common/interfaces/get-options.interface.d.cts +2 -0
  53. package/lib/common/interfaces/get-options.interface.d.ts +2 -0
  54. package/lib/common/interfaces/index.d.cts +2 -2
  55. package/lib/common/interfaces/index.d.ts +2 -2
  56. package/lib/common/interfaces/post-options.interface.d.cts +2 -0
  57. package/lib/common/interfaces/post-options.interface.d.ts +2 -0
  58. package/lib/common/interfaces/put-options.interface.d.cts +2 -0
  59. package/lib/common/interfaces/put-options.interface.d.ts +2 -0
  60. package/lib/common/interfaces/workos-options.interface.d.cts +1 -0
  61. package/lib/common/interfaces/workos-options.interface.d.ts +1 -0
  62. package/lib/common/net/http-client.cjs.map +1 -1
  63. package/lib/common/net/http-client.js.map +1 -1
  64. package/lib/common/serializers/event.serializer.cjs +13 -5
  65. package/lib/common/serializers/event.serializer.cjs.map +1 -1
  66. package/lib/common/serializers/event.serializer.js +13 -5
  67. package/lib/common/serializers/event.serializer.js.map +1 -1
  68. package/lib/directory-sync/directory-sync.cjs +1 -1
  69. package/lib/directory-sync/directory-sync.js +1 -1
  70. package/lib/factory.cjs +10 -0
  71. package/lib/factory.cjs.map +1 -0
  72. package/lib/factory.d.cts +83 -0
  73. package/lib/factory.d.ts +83 -0
  74. package/lib/factory.js +10 -0
  75. package/lib/factory.js.map +1 -0
  76. package/lib/feature-flags/feature-flags.cjs +37 -0
  77. package/lib/feature-flags/feature-flags.cjs.map +1 -0
  78. package/lib/feature-flags/feature-flags.d.cts +21 -0
  79. package/lib/feature-flags/feature-flags.d.ts +21 -0
  80. package/lib/feature-flags/feature-flags.js +37 -0
  81. package/lib/feature-flags/feature-flags.js.map +1 -0
  82. package/lib/feature-flags/interfaces/add-flag-target-options.interface.cjs +0 -0
  83. package/lib/feature-flags/interfaces/add-flag-target-options.interface.d.cts +8 -0
  84. package/lib/feature-flags/interfaces/add-flag-target-options.interface.d.ts +8 -0
  85. package/lib/feature-flags/interfaces/add-flag-target-options.interface.js +1 -0
  86. package/lib/feature-flags/interfaces/feature-flag.interface.d.cts +8 -2
  87. package/lib/feature-flags/interfaces/feature-flag.interface.d.ts +8 -2
  88. package/lib/feature-flags/interfaces/index.d.cts +4 -1
  89. package/lib/feature-flags/interfaces/index.d.ts +4 -1
  90. package/lib/feature-flags/interfaces/list-feature-flags-options.interface.cjs +0 -0
  91. package/lib/feature-flags/interfaces/list-feature-flags-options.interface.d.cts +7 -0
  92. package/lib/feature-flags/interfaces/list-feature-flags-options.interface.d.ts +7 -0
  93. package/lib/feature-flags/interfaces/list-feature-flags-options.interface.js +1 -0
  94. package/lib/feature-flags/interfaces/remove-flag-target-options.interface.cjs +0 -0
  95. package/lib/feature-flags/interfaces/remove-flag-target-options.interface.d.cts +8 -0
  96. package/lib/feature-flags/interfaces/remove-flag-target-options.interface.d.ts +8 -0
  97. package/lib/feature-flags/interfaces/remove-flag-target-options.interface.js +1 -0
  98. package/lib/feature-flags/serializers/feature-flag.serializer.cjs +3 -0
  99. package/lib/feature-flags/serializers/feature-flag.serializer.cjs.map +1 -1
  100. package/lib/feature-flags/serializers/feature-flag.serializer.js +3 -0
  101. package/lib/feature-flags/serializers/feature-flag.serializer.js.map +1 -1
  102. package/lib/feature-flags/serializers/index.cjs +3 -0
  103. package/lib/feature-flags/serializers/index.d.cts +2 -0
  104. package/lib/feature-flags/serializers/index.d.ts +2 -0
  105. package/lib/feature-flags/serializers/index.js +3 -0
  106. package/lib/fga/serializers/query-result.serializer.cjs.map +1 -1
  107. package/lib/fga/serializers/query-result.serializer.js.map +1 -1
  108. package/lib/index.cjs +18 -9
  109. package/lib/index.cjs.map +1 -1
  110. package/lib/index.d.cts +18 -5
  111. package/lib/index.d.ts +18 -5
  112. package/lib/index.js +16 -10
  113. package/lib/index.js.map +1 -1
  114. package/lib/index.worker.cjs +15 -9
  115. package/lib/index.worker.cjs.map +1 -1
  116. package/lib/index.worker.d.cts +10 -5
  117. package/lib/index.worker.d.ts +10 -5
  118. package/lib/index.worker.js +13 -10
  119. package/lib/index.worker.js.map +1 -1
  120. package/lib/organizations/organizations.cjs +14 -2
  121. package/lib/organizations/organizations.cjs.map +1 -1
  122. package/lib/organizations/organizations.d.cts +6 -0
  123. package/lib/organizations/organizations.d.ts +6 -0
  124. package/lib/organizations/organizations.js +14 -2
  125. package/lib/organizations/organizations.js.map +1 -1
  126. package/lib/organizations/serializers/index.cjs +1 -1
  127. package/lib/organizations/serializers/index.js +1 -1
  128. package/lib/pkce/pkce.cjs +54 -0
  129. package/lib/pkce/pkce.cjs.map +1 -0
  130. package/lib/pkce/pkce.d.cts +38 -0
  131. package/lib/pkce/pkce.d.ts +38 -0
  132. package/lib/pkce/pkce.js +53 -0
  133. package/lib/pkce/pkce.js.map +1 -0
  134. package/lib/sso/interfaces/authorization-url-options.interface.d.cts +34 -8
  135. package/lib/sso/interfaces/authorization-url-options.interface.d.ts +34 -8
  136. package/lib/sso/interfaces/get-profile-and-token-options.interface.d.cts +6 -0
  137. package/lib/sso/interfaces/get-profile-and-token-options.interface.d.ts +6 -0
  138. package/lib/sso/interfaces/index.d.cts +2 -2
  139. package/lib/sso/interfaces/index.d.ts +2 -2
  140. package/lib/sso/sso.cjs +90 -8
  141. package/lib/sso/sso.cjs.map +1 -1
  142. package/lib/sso/sso.d.cts +41 -2
  143. package/lib/sso/sso.d.ts +41 -2
  144. package/lib/sso/sso.js +90 -8
  145. package/lib/sso/sso.js.map +1 -1
  146. package/lib/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.d.cts +2 -2
  147. package/lib/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.d.ts +2 -2
  148. package/lib/user-management/interfaces/authenticate-with-options-base.interface.d.cts +19 -3
  149. package/lib/user-management/interfaces/authenticate-with-options-base.interface.d.ts +19 -3
  150. package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.cjs +0 -0
  151. package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.d.cts +16 -0
  152. package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.d.ts +16 -0
  153. package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.js +1 -0
  154. package/lib/user-management/interfaces/authorization-url-options.interface.d.cts +30 -5
  155. package/lib/user-management/interfaces/authorization-url-options.interface.d.ts +30 -5
  156. package/lib/user-management/interfaces/index.d.cts +5 -3
  157. package/lib/user-management/interfaces/index.d.ts +5 -3
  158. package/lib/user-management/interfaces/logout-url-options.interface.cjs +0 -0
  159. package/lib/user-management/interfaces/logout-url-options.interface.d.cts +8 -0
  160. package/lib/user-management/interfaces/logout-url-options.interface.d.ts +8 -0
  161. package/lib/user-management/interfaces/logout-url-options.interface.js +1 -0
  162. package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.cjs.map +1 -1
  163. package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.d.cts +2 -1
  164. package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.d.ts +2 -1
  165. package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.js.map +1 -1
  166. package/lib/user-management/serializers/authenticate-with-code-options.serializer.cjs.map +1 -1
  167. package/lib/user-management/serializers/authenticate-with-code-options.serializer.d.cts +2 -1
  168. package/lib/user-management/serializers/authenticate-with-code-options.serializer.d.ts +2 -1
  169. package/lib/user-management/serializers/authenticate-with-code-options.serializer.js.map +1 -1
  170. package/lib/user-management/serializers/authenticate-with-email-verification.serializer.cjs.map +1 -1
  171. package/lib/user-management/serializers/authenticate-with-email-verification.serializer.d.cts +2 -1
  172. package/lib/user-management/serializers/authenticate-with-email-verification.serializer.d.ts +2 -1
  173. package/lib/user-management/serializers/authenticate-with-email-verification.serializer.js.map +1 -1
  174. package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.cjs.map +1 -1
  175. package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.d.cts +2 -1
  176. package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.d.ts +2 -1
  177. package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.js.map +1 -1
  178. package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.cjs.map +1 -1
  179. package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.d.cts +2 -1
  180. package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.d.ts +2 -1
  181. package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.js.map +1 -1
  182. package/lib/user-management/serializers/authenticate-with-password-options.serializer.cjs.map +1 -1
  183. package/lib/user-management/serializers/authenticate-with-password-options.serializer.d.cts +2 -1
  184. package/lib/user-management/serializers/authenticate-with-password-options.serializer.d.ts +2 -1
  185. package/lib/user-management/serializers/authenticate-with-password-options.serializer.js.map +1 -1
  186. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.cjs +14 -0
  187. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.cjs.map +1 -0
  188. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.d.cts +8 -0
  189. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.d.ts +8 -0
  190. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.js +13 -0
  191. package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.js.map +1 -0
  192. package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.cjs.map +1 -1
  193. package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.d.cts +2 -1
  194. package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.d.ts +2 -1
  195. package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.js.map +1 -1
  196. package/lib/user-management/serializers/authenticate-with-totp-options.serializer.cjs.map +1 -1
  197. package/lib/user-management/serializers/authenticate-with-totp-options.serializer.d.cts +2 -1
  198. package/lib/user-management/serializers/authenticate-with-totp-options.serializer.d.ts +2 -1
  199. package/lib/user-management/serializers/authenticate-with-totp-options.serializer.js.map +1 -1
  200. package/lib/user-management/serializers/index.cjs +2 -0
  201. package/lib/user-management/serializers/index.d.cts +2 -1
  202. package/lib/user-management/serializers/index.d.ts +2 -1
  203. package/lib/user-management/serializers/index.js +2 -1
  204. package/lib/user-management/session.cjs +3 -10
  205. package/lib/user-management/session.cjs.map +1 -1
  206. package/lib/user-management/session.js +3 -10
  207. package/lib/user-management/session.js.map +1 -1
  208. package/lib/user-management/user-management.cjs +186 -31
  209. package/lib/user-management/user-management.cjs.map +1 -1
  210. package/lib/user-management/user-management.d.cts +71 -2
  211. package/lib/user-management/user-management.d.ts +71 -2
  212. package/lib/user-management/user-management.js +186 -31
  213. package/lib/user-management/user-management.js.map +1 -1
  214. package/lib/vault/vault.cjs +4 -0
  215. package/lib/vault/vault.cjs.map +1 -1
  216. package/lib/vault/vault.d.cts +1 -0
  217. package/lib/vault/vault.d.ts +1 -0
  218. package/lib/vault/vault.js +4 -0
  219. package/lib/vault/vault.js.map +1 -1
  220. package/lib/webhooks/webhooks.cjs +1 -1
  221. package/lib/webhooks/webhooks.js +1 -1
  222. package/lib/workos.cjs +68 -26
  223. package/lib/workos.cjs.map +1 -1
  224. package/lib/workos.d.cts +37 -8
  225. package/lib/workos.d.ts +37 -8
  226. package/lib/workos.js +68 -26
  227. package/lib/workos.js.map +1 -1
  228. package/package.json +4 -21
  229. package/lib/_virtual/rolldown_runtime.cjs +0 -19
  230. package/lib/_virtual/rolldown_runtime.js +0 -18
  231. package/lib/client/index.cjs +0 -15
  232. package/lib/client/index.d.cts +0 -3
  233. package/lib/client/index.d.ts +0 -3
  234. package/lib/client/index.js +0 -4
  235. package/lib/client/sso.cjs +0 -40
  236. package/lib/client/sso.cjs.map +0 -1
  237. package/lib/client/sso.d.cts +0 -21
  238. package/lib/client/sso.d.ts +0 -21
  239. package/lib/client/sso.js +0 -34
  240. package/lib/client/sso.js.map +0 -1
  241. package/lib/client/user-management.cjs +0 -80
  242. package/lib/client/user-management.cjs.map +0 -1
  243. package/lib/client/user-management.d.cts +0 -58
  244. package/lib/client/user-management.d.ts +0 -58
  245. package/lib/client/user-management.js +0 -72
  246. package/lib/client/user-management.js.map +0 -1
  247. package/lib/index.client.cjs +0 -15
  248. package/lib/index.client.d.cts +0 -3
  249. package/lib/index.client.d.ts +0 -3
  250. package/lib/index.client.js +0 -4
@@ -1,5 +1,5 @@
1
- import { deserializeOrganization } from "./organization.serializer.js";
2
1
  import { serializeCreateOrganizationOptions } from "./create-organization-options.serializer.js";
2
+ import { deserializeOrganization } from "./organization.serializer.js";
3
3
  import { serializeUpdateOrganizationOptions } from "./update-organization-options.serializer.js";
4
4
 
5
5
  export { deserializeOrganization, serializeCreateOrganizationOptions, serializeUpdateOrganizationOptions };
@@ -0,0 +1,54 @@
1
+
2
+ //#region src/pkce/pkce.ts
3
+ /**
4
+ * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0 public clients.
5
+ *
6
+ * Implements RFC 7636 for secure authorization code exchange without a client secret.
7
+ * Used by Electron apps, React Native/mobile apps, CLI tools, and other public clients.
8
+ */
9
+ var PKCE = class {
10
+ /**
11
+ * Generate a cryptographically random code verifier.
12
+ *
13
+ * @param length - Length of verifier (43-128, default 43)
14
+ * @returns RFC 7636 compliant code verifier
15
+ */
16
+ generateCodeVerifier(length = 43) {
17
+ if (length < 43 || length > 128) throw new RangeError(`Code verifier length must be between 43 and 128, got ${length}`);
18
+ const byteLength = Math.ceil(length * 3 / 4);
19
+ const randomBytes = new Uint8Array(byteLength);
20
+ crypto.getRandomValues(randomBytes);
21
+ return this.base64UrlEncode(randomBytes).slice(0, length);
22
+ }
23
+ /**
24
+ * Generate S256 code challenge from a verifier.
25
+ *
26
+ * @param verifier - The code verifier
27
+ * @returns Base64URL-encoded SHA256 hash
28
+ */
29
+ async generateCodeChallenge(verifier) {
30
+ const data = new TextEncoder().encode(verifier);
31
+ const hash = await crypto.subtle.digest("SHA-256", data);
32
+ return this.base64UrlEncode(new Uint8Array(hash));
33
+ }
34
+ /**
35
+ * Generate a complete PKCE pair (verifier + challenge).
36
+ *
37
+ * @returns Code verifier, challenge, and method ('S256')
38
+ */
39
+ async generate() {
40
+ const codeVerifier = this.generateCodeVerifier();
41
+ return {
42
+ codeVerifier,
43
+ codeChallenge: await this.generateCodeChallenge(codeVerifier),
44
+ codeChallengeMethod: "S256"
45
+ };
46
+ }
47
+ base64UrlEncode(buffer) {
48
+ return btoa(String.fromCharCode(...buffer)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
49
+ }
50
+ };
51
+
52
+ //#endregion
53
+ exports.PKCE = PKCE;
54
+ //# sourceMappingURL=pkce.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.cjs","names":[],"sources":["../../src/pkce/pkce.ts"],"sourcesContent":["export interface PKCEPair {\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: 'S256';\n}\n\n/**\n * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0 public clients.\n *\n * Implements RFC 7636 for secure authorization code exchange without a client secret.\n * Used by Electron apps, React Native/mobile apps, CLI tools, and other public clients.\n */\nexport class PKCE {\n /**\n * Generate a cryptographically random code verifier.\n *\n * @param length - Length of verifier (43-128, default 43)\n * @returns RFC 7636 compliant code verifier\n */\n generateCodeVerifier(length: number = 43): string {\n if (length < 43 || length > 128) {\n throw new RangeError(\n `Code verifier length must be between 43 and 128, got ${length}`,\n );\n }\n\n const byteLength = Math.ceil((length * 3) / 4);\n const randomBytes = new Uint8Array(byteLength);\n crypto.getRandomValues(randomBytes);\n\n return this.base64UrlEncode(randomBytes).slice(0, length);\n }\n\n /**\n * Generate S256 code challenge from a verifier.\n *\n * @param verifier - The code verifier\n * @returns Base64URL-encoded SHA256 hash\n */\n async generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return this.base64UrlEncode(new Uint8Array(hash));\n }\n\n /**\n * Generate a complete PKCE pair (verifier + challenge).\n *\n * @returns Code verifier, challenge, and method ('S256')\n */\n async generate(): Promise<PKCEPair> {\n const codeVerifier = this.generateCodeVerifier();\n const codeChallenge = await this.generateCodeChallenge(codeVerifier);\n return { codeVerifier, codeChallenge, codeChallengeMethod: 'S256' };\n }\n\n private base64UrlEncode(buffer: Uint8Array): string {\n const base64 = btoa(String.fromCharCode(...buffer));\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n }\n}\n"],"mappings":";;;;;;;;AAYA,IAAa,OAAb,MAAkB;;;;;;;CAOhB,qBAAqB,SAAiB,IAAY;AAChD,MAAI,SAAS,MAAM,SAAS,IAC1B,OAAM,IAAI,WACR,wDAAwD,SACzD;EAGH,MAAM,aAAa,KAAK,KAAM,SAAS,IAAK,EAAE;EAC9C,MAAM,cAAc,IAAI,WAAW,WAAW;AAC9C,SAAO,gBAAgB,YAAY;AAEnC,SAAO,KAAK,gBAAgB,YAAY,CAAC,MAAM,GAAG,OAAO;;;;;;;;CAS3D,MAAM,sBAAsB,UAAmC;EAE7D,MAAM,OADU,IAAI,aAAa,CACZ,OAAO,SAAS;EACrC,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,WAAW,KAAK;AACxD,SAAO,KAAK,gBAAgB,IAAI,WAAW,KAAK,CAAC;;;;;;;CAQnD,MAAM,WAA8B;EAClC,MAAM,eAAe,KAAK,sBAAsB;AAEhD,SAAO;GAAE;GAAc,eADD,MAAM,KAAK,sBAAsB,aAAa;GAC9B,qBAAqB;GAAQ;;CAGrE,AAAQ,gBAAgB,QAA4B;AAElD,SADe,KAAK,OAAO,aAAa,GAAG,OAAO,CAAC,CACrC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,GAAG"}
@@ -0,0 +1,38 @@
1
+ //#region src/pkce/pkce.d.ts
2
+ interface PKCEPair {
3
+ codeVerifier: string;
4
+ codeChallenge: string;
5
+ codeChallengeMethod: 'S256';
6
+ }
7
+ /**
8
+ * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0 public clients.
9
+ *
10
+ * Implements RFC 7636 for secure authorization code exchange without a client secret.
11
+ * Used by Electron apps, React Native/mobile apps, CLI tools, and other public clients.
12
+ */
13
+ declare class PKCE {
14
+ /**
15
+ * Generate a cryptographically random code verifier.
16
+ *
17
+ * @param length - Length of verifier (43-128, default 43)
18
+ * @returns RFC 7636 compliant code verifier
19
+ */
20
+ generateCodeVerifier(length?: number): string;
21
+ /**
22
+ * Generate S256 code challenge from a verifier.
23
+ *
24
+ * @param verifier - The code verifier
25
+ * @returns Base64URL-encoded SHA256 hash
26
+ */
27
+ generateCodeChallenge(verifier: string): Promise<string>;
28
+ /**
29
+ * Generate a complete PKCE pair (verifier + challenge).
30
+ *
31
+ * @returns Code verifier, challenge, and method ('S256')
32
+ */
33
+ generate(): Promise<PKCEPair>;
34
+ private base64UrlEncode;
35
+ }
36
+ //#endregion
37
+ export { PKCE, PKCEPair };
38
+ //# sourceMappingURL=pkce.d.cts.map
@@ -0,0 +1,38 @@
1
+ //#region src/pkce/pkce.d.ts
2
+ interface PKCEPair {
3
+ codeVerifier: string;
4
+ codeChallenge: string;
5
+ codeChallengeMethod: 'S256';
6
+ }
7
+ /**
8
+ * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0 public clients.
9
+ *
10
+ * Implements RFC 7636 for secure authorization code exchange without a client secret.
11
+ * Used by Electron apps, React Native/mobile apps, CLI tools, and other public clients.
12
+ */
13
+ declare class PKCE {
14
+ /**
15
+ * Generate a cryptographically random code verifier.
16
+ *
17
+ * @param length - Length of verifier (43-128, default 43)
18
+ * @returns RFC 7636 compliant code verifier
19
+ */
20
+ generateCodeVerifier(length?: number): string;
21
+ /**
22
+ * Generate S256 code challenge from a verifier.
23
+ *
24
+ * @param verifier - The code verifier
25
+ * @returns Base64URL-encoded SHA256 hash
26
+ */
27
+ generateCodeChallenge(verifier: string): Promise<string>;
28
+ /**
29
+ * Generate a complete PKCE pair (verifier + challenge).
30
+ *
31
+ * @returns Code verifier, challenge, and method ('S256')
32
+ */
33
+ generate(): Promise<PKCEPair>;
34
+ private base64UrlEncode;
35
+ }
36
+ //#endregion
37
+ export { PKCE, PKCEPair };
38
+ //# sourceMappingURL=pkce.d.ts.map
@@ -0,0 +1,53 @@
1
+ //#region src/pkce/pkce.ts
2
+ /**
3
+ * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0 public clients.
4
+ *
5
+ * Implements RFC 7636 for secure authorization code exchange without a client secret.
6
+ * Used by Electron apps, React Native/mobile apps, CLI tools, and other public clients.
7
+ */
8
+ var PKCE = class {
9
+ /**
10
+ * Generate a cryptographically random code verifier.
11
+ *
12
+ * @param length - Length of verifier (43-128, default 43)
13
+ * @returns RFC 7636 compliant code verifier
14
+ */
15
+ generateCodeVerifier(length = 43) {
16
+ if (length < 43 || length > 128) throw new RangeError(`Code verifier length must be between 43 and 128, got ${length}`);
17
+ const byteLength = Math.ceil(length * 3 / 4);
18
+ const randomBytes = new Uint8Array(byteLength);
19
+ crypto.getRandomValues(randomBytes);
20
+ return this.base64UrlEncode(randomBytes).slice(0, length);
21
+ }
22
+ /**
23
+ * Generate S256 code challenge from a verifier.
24
+ *
25
+ * @param verifier - The code verifier
26
+ * @returns Base64URL-encoded SHA256 hash
27
+ */
28
+ async generateCodeChallenge(verifier) {
29
+ const data = new TextEncoder().encode(verifier);
30
+ const hash = await crypto.subtle.digest("SHA-256", data);
31
+ return this.base64UrlEncode(new Uint8Array(hash));
32
+ }
33
+ /**
34
+ * Generate a complete PKCE pair (verifier + challenge).
35
+ *
36
+ * @returns Code verifier, challenge, and method ('S256')
37
+ */
38
+ async generate() {
39
+ const codeVerifier = this.generateCodeVerifier();
40
+ return {
41
+ codeVerifier,
42
+ codeChallenge: await this.generateCodeChallenge(codeVerifier),
43
+ codeChallengeMethod: "S256"
44
+ };
45
+ }
46
+ base64UrlEncode(buffer) {
47
+ return btoa(String.fromCharCode(...buffer)).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
48
+ }
49
+ };
50
+
51
+ //#endregion
52
+ export { PKCE };
53
+ //# sourceMappingURL=pkce.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pkce.js","names":[],"sources":["../../src/pkce/pkce.ts"],"sourcesContent":["export interface PKCEPair {\n codeVerifier: string;\n codeChallenge: string;\n codeChallengeMethod: 'S256';\n}\n\n/**\n * PKCE (Proof Key for Code Exchange) utilities for OAuth 2.0 public clients.\n *\n * Implements RFC 7636 for secure authorization code exchange without a client secret.\n * Used by Electron apps, React Native/mobile apps, CLI tools, and other public clients.\n */\nexport class PKCE {\n /**\n * Generate a cryptographically random code verifier.\n *\n * @param length - Length of verifier (43-128, default 43)\n * @returns RFC 7636 compliant code verifier\n */\n generateCodeVerifier(length: number = 43): string {\n if (length < 43 || length > 128) {\n throw new RangeError(\n `Code verifier length must be between 43 and 128, got ${length}`,\n );\n }\n\n const byteLength = Math.ceil((length * 3) / 4);\n const randomBytes = new Uint8Array(byteLength);\n crypto.getRandomValues(randomBytes);\n\n return this.base64UrlEncode(randomBytes).slice(0, length);\n }\n\n /**\n * Generate S256 code challenge from a verifier.\n *\n * @param verifier - The code verifier\n * @returns Base64URL-encoded SHA256 hash\n */\n async generateCodeChallenge(verifier: string): Promise<string> {\n const encoder = new TextEncoder();\n const data = encoder.encode(verifier);\n const hash = await crypto.subtle.digest('SHA-256', data);\n return this.base64UrlEncode(new Uint8Array(hash));\n }\n\n /**\n * Generate a complete PKCE pair (verifier + challenge).\n *\n * @returns Code verifier, challenge, and method ('S256')\n */\n async generate(): Promise<PKCEPair> {\n const codeVerifier = this.generateCodeVerifier();\n const codeChallenge = await this.generateCodeChallenge(codeVerifier);\n return { codeVerifier, codeChallenge, codeChallengeMethod: 'S256' };\n }\n\n private base64UrlEncode(buffer: Uint8Array): string {\n const base64 = btoa(String.fromCharCode(...buffer));\n return base64.replace(/\\+/g, '-').replace(/\\//g, '_').replace(/=+$/, '');\n }\n}\n"],"mappings":";;;;;;;AAYA,IAAa,OAAb,MAAkB;;;;;;;CAOhB,qBAAqB,SAAiB,IAAY;AAChD,MAAI,SAAS,MAAM,SAAS,IAC1B,OAAM,IAAI,WACR,wDAAwD,SACzD;EAGH,MAAM,aAAa,KAAK,KAAM,SAAS,IAAK,EAAE;EAC9C,MAAM,cAAc,IAAI,WAAW,WAAW;AAC9C,SAAO,gBAAgB,YAAY;AAEnC,SAAO,KAAK,gBAAgB,YAAY,CAAC,MAAM,GAAG,OAAO;;;;;;;;CAS3D,MAAM,sBAAsB,UAAmC;EAE7D,MAAM,OADU,IAAI,aAAa,CACZ,OAAO,SAAS;EACrC,MAAM,OAAO,MAAM,OAAO,OAAO,OAAO,WAAW,KAAK;AACxD,SAAO,KAAK,gBAAgB,IAAI,WAAW,KAAK,CAAC;;;;;;;CAQnD,MAAM,WAA8B;EAClC,MAAM,eAAe,KAAK,sBAAsB;AAEhD,SAAO;GAAE;GAAc,eADD,MAAM,KAAK,sBAAsB,aAAa;GAC9B,qBAAqB;GAAQ;;CAGrE,AAAQ,gBAAgB,QAA4B;AAElD,SADe,KAAK,OAAO,aAAa,GAAG,OAAO,CAAC,CACrC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,IAAI,CAAC,QAAQ,OAAO,GAAG"}
@@ -1,5 +1,16 @@
1
1
  //#region src/sso/interfaces/authorization-url-options.interface.d.ts
2
- interface SSOAuthorizationURLBase {
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 SSOAuthorizationURLBaseFields {
3
14
  clientId: string;
4
15
  domainHint?: string;
5
16
  loginHint?: string;
@@ -8,22 +19,37 @@ interface SSOAuthorizationURLBase {
8
19
  redirectUri: string;
9
20
  state?: string;
10
21
  }
11
- interface SSOWithConnection extends SSOAuthorizationURLBase {
22
+ /**
23
+ * Result of getAuthorizationUrlWithPKCE() containing the URL,
24
+ * state, and PKCE code verifier.
25
+ *
26
+ * The codeVerifier must be stored securely and passed to
27
+ * getProfileAndToken() during token exchange.
28
+ */
29
+ interface SSOPKCEAuthorizationURLResult {
30
+ /** The complete authorization URL to redirect the user to */
31
+ url: string;
32
+ /** The state parameter (auto-generated) */
33
+ state: string;
34
+ /** The PKCE code verifier. Store securely and pass to getProfileAndToken(). */
35
+ codeVerifier: string;
36
+ }
37
+ type SSOWithConnection = SSOAuthorizationURLBaseFields & PKCEFields & {
12
38
  connection: string;
13
39
  organization?: never;
14
40
  provider?: never;
15
- }
16
- interface SSOWithOrganization extends SSOAuthorizationURLBase {
41
+ };
42
+ type SSOWithOrganization = SSOAuthorizationURLBaseFields & PKCEFields & {
17
43
  organization: string;
18
44
  connection?: never;
19
45
  provider?: never;
20
- }
21
- interface SSOWithProvider extends SSOAuthorizationURLBase {
46
+ };
47
+ type SSOWithProvider = SSOAuthorizationURLBaseFields & PKCEFields & {
22
48
  provider: string;
23
49
  connection?: never;
24
50
  organization?: never;
25
- }
51
+ };
26
52
  type SSOAuthorizationURLOptions = SSOWithConnection | SSOWithOrganization | SSOWithProvider;
27
53
  //#endregion
28
- export { SSOAuthorizationURLOptions };
54
+ export { SSOAuthorizationURLOptions, SSOPKCEAuthorizationURLResult };
29
55
  //# sourceMappingURL=authorization-url-options.interface.d.cts.map
@@ -1,5 +1,16 @@
1
1
  //#region src/sso/interfaces/authorization-url-options.interface.d.ts
2
- interface SSOAuthorizationURLBase {
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 SSOAuthorizationURLBaseFields {
3
14
  clientId: string;
4
15
  domainHint?: string;
5
16
  loginHint?: string;
@@ -8,22 +19,37 @@ interface SSOAuthorizationURLBase {
8
19
  redirectUri: string;
9
20
  state?: string;
10
21
  }
11
- interface SSOWithConnection extends SSOAuthorizationURLBase {
22
+ /**
23
+ * Result of getAuthorizationUrlWithPKCE() containing the URL,
24
+ * state, and PKCE code verifier.
25
+ *
26
+ * The codeVerifier must be stored securely and passed to
27
+ * getProfileAndToken() during token exchange.
28
+ */
29
+ interface SSOPKCEAuthorizationURLResult {
30
+ /** The complete authorization URL to redirect the user to */
31
+ url: string;
32
+ /** The state parameter (auto-generated) */
33
+ state: string;
34
+ /** The PKCE code verifier. Store securely and pass to getProfileAndToken(). */
35
+ codeVerifier: string;
36
+ }
37
+ type SSOWithConnection = SSOAuthorizationURLBaseFields & PKCEFields & {
12
38
  connection: string;
13
39
  organization?: never;
14
40
  provider?: never;
15
- }
16
- interface SSOWithOrganization extends SSOAuthorizationURLBase {
41
+ };
42
+ type SSOWithOrganization = SSOAuthorizationURLBaseFields & PKCEFields & {
17
43
  organization: string;
18
44
  connection?: never;
19
45
  provider?: never;
20
- }
21
- interface SSOWithProvider extends SSOAuthorizationURLBase {
46
+ };
47
+ type SSOWithProvider = SSOAuthorizationURLBaseFields & PKCEFields & {
22
48
  provider: string;
23
49
  connection?: never;
24
50
  organization?: never;
25
- }
51
+ };
26
52
  type SSOAuthorizationURLOptions = SSOWithConnection | SSOWithOrganization | SSOWithProvider;
27
53
  //#endregion
28
- export { SSOAuthorizationURLOptions };
54
+ export { SSOAuthorizationURLOptions, SSOPKCEAuthorizationURLResult };
29
55
  //# sourceMappingURL=authorization-url-options.interface.d.ts.map
@@ -2,6 +2,12 @@
2
2
  interface GetProfileAndTokenOptions {
3
3
  clientId: string;
4
4
  code: string;
5
+ /**
6
+ * PKCE code verifier for public clients.
7
+ * Pass the codeVerifier that was generated with getAuthorizationUrlWithPKCE().
8
+ * When provided, client_secret is not sent (public client mode).
9
+ */
10
+ codeVerifier?: string;
5
11
  }
6
12
  //#endregion
7
13
  export { GetProfileAndTokenOptions };
@@ -2,6 +2,12 @@
2
2
  interface GetProfileAndTokenOptions {
3
3
  clientId: string;
4
4
  code: string;
5
+ /**
6
+ * PKCE code verifier for public clients.
7
+ * Pass the codeVerifier that was generated with getAuthorizationUrlWithPKCE().
8
+ * When provided, client_secret is not sent (public client mode).
9
+ */
10
+ codeVerifier?: string;
5
11
  }
6
12
  //#endregion
7
13
  export { GetProfileAndTokenOptions };
@@ -1,4 +1,4 @@
1
- import { SSOAuthorizationURLOptions } from "./authorization-url-options.interface.cjs";
1
+ import { SSOAuthorizationURLOptions, SSOPKCEAuthorizationURLResult } from "./authorization-url-options.interface.cjs";
2
2
  import { ConnectionType } from "./connection-type.enum.cjs";
3
3
  import { Connection, ConnectionDomain, ConnectionResponse } from "./connection.interface.cjs";
4
4
  import { GetProfileOptions } from "./get-profile-options.interface.cjs";
@@ -6,4 +6,4 @@ import { GetProfileAndTokenOptions } from "./get-profile-and-token-options.inter
6
6
  import { ListConnectionsOptions, SerializedListConnectionsOptions } from "./list-connections-options.interface.cjs";
7
7
  import { Profile, ProfileResponse } from "./profile.interface.cjs";
8
8
  import { ProfileAndToken, ProfileAndTokenResponse } from "./profile-and-token.interface.cjs";
9
- export { Connection, ConnectionDomain, ConnectionResponse, ConnectionType, GetProfileAndTokenOptions, GetProfileOptions, ListConnectionsOptions, Profile, ProfileAndToken, ProfileAndTokenResponse, ProfileResponse, SSOAuthorizationURLOptions, SerializedListConnectionsOptions };
9
+ export { Connection, ConnectionDomain, ConnectionResponse, ConnectionType, GetProfileAndTokenOptions, GetProfileOptions, ListConnectionsOptions, Profile, ProfileAndToken, ProfileAndTokenResponse, ProfileResponse, SSOAuthorizationURLOptions, type SSOPKCEAuthorizationURLResult, SerializedListConnectionsOptions };
@@ -1,4 +1,4 @@
1
- import { SSOAuthorizationURLOptions } from "./authorization-url-options.interface.js";
1
+ import { SSOAuthorizationURLOptions, SSOPKCEAuthorizationURLResult } from "./authorization-url-options.interface.js";
2
2
  import { ConnectionType } from "./connection-type.enum.js";
3
3
  import { Connection, ConnectionDomain, ConnectionResponse } from "./connection.interface.js";
4
4
  import { GetProfileOptions } from "./get-profile-options.interface.js";
@@ -6,4 +6,4 @@ import { GetProfileAndTokenOptions } from "./get-profile-and-token-options.inter
6
6
  import { ListConnectionsOptions, SerializedListConnectionsOptions } from "./list-connections-options.interface.js";
7
7
  import { Profile, ProfileResponse } from "./profile.interface.js";
8
8
  import { ProfileAndToken, ProfileAndTokenResponse } from "./profile-and-token.interface.js";
9
- export { Connection, ConnectionDomain, ConnectionResponse, ConnectionType, GetProfileAndTokenOptions, GetProfileOptions, ListConnectionsOptions, Profile, ProfileAndToken, ProfileAndTokenResponse, ProfileResponse, SSOAuthorizationURLOptions, SerializedListConnectionsOptions };
9
+ export { Connection, ConnectionDomain, ConnectionResponse, ConnectionType, GetProfileAndTokenOptions, GetProfileOptions, ListConnectionsOptions, Profile, ProfileAndToken, ProfileAndTokenResponse, ProfileResponse, SSOAuthorizationURLOptions, type SSOPKCEAuthorizationURLResult, SerializedListConnectionsOptions };
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