@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.
- package/README.md +54 -0
- package/lib/api-keys/api-keys.cjs +3 -0
- package/lib/api-keys/api-keys.cjs.map +1 -1
- package/lib/api-keys/api-keys.d.cts +2 -1
- package/lib/api-keys/api-keys.d.ts +2 -1
- package/lib/api-keys/api-keys.js +3 -0
- package/lib/api-keys/api-keys.js.map +1 -1
- package/lib/api-keys/interfaces/create-organization-api-key-options.interface.cjs +0 -0
- package/lib/api-keys/interfaces/create-organization-api-key-options.interface.d.cts +16 -0
- package/lib/api-keys/interfaces/create-organization-api-key-options.interface.d.ts +16 -0
- package/lib/api-keys/interfaces/create-organization-api-key-options.interface.js +1 -0
- package/lib/api-keys/interfaces/created-api-key.interface.cjs +0 -0
- package/lib/api-keys/interfaces/created-api-key.interface.d.cts +34 -0
- package/lib/api-keys/interfaces/created-api-key.interface.d.ts +34 -0
- package/lib/api-keys/interfaces/created-api-key.interface.js +1 -0
- package/lib/api-keys/interfaces/index.cjs +0 -0
- package/lib/api-keys/interfaces/index.d.cts +6 -0
- package/lib/api-keys/interfaces/index.d.ts +6 -0
- package/lib/api-keys/interfaces/index.js +1 -0
- package/lib/api-keys/interfaces/list-organization-api-keys-options.interface.cjs +0 -0
- package/lib/api-keys/interfaces/list-organization-api-keys-options.interface.d.cts +9 -0
- package/lib/api-keys/interfaces/list-organization-api-keys-options.interface.d.ts +9 -0
- package/lib/api-keys/interfaces/list-organization-api-keys-options.interface.js +1 -0
- package/lib/api-keys/serializers/create-organization-api-key-options.serializer.cjs +12 -0
- package/lib/api-keys/serializers/create-organization-api-key-options.serializer.cjs.map +1 -0
- package/lib/api-keys/serializers/create-organization-api-key-options.serializer.d.cts +7 -0
- package/lib/api-keys/serializers/create-organization-api-key-options.serializer.d.ts +7 -0
- package/lib/api-keys/serializers/create-organization-api-key-options.serializer.js +11 -0
- package/lib/api-keys/serializers/create-organization-api-key-options.serializer.js.map +1 -0
- package/lib/api-keys/serializers/created-api-key.serializer.cjs +20 -0
- package/lib/api-keys/serializers/created-api-key.serializer.cjs.map +1 -0
- package/lib/api-keys/serializers/created-api-key.serializer.d.cts +7 -0
- package/lib/api-keys/serializers/created-api-key.serializer.d.ts +7 -0
- package/lib/api-keys/serializers/created-api-key.serializer.js +19 -0
- package/lib/api-keys/serializers/created-api-key.serializer.js.map +1 -0
- package/lib/api-keys/serializers/index.cjs +9 -0
- package/lib/api-keys/serializers/index.d.cts +5 -0
- package/lib/api-keys/serializers/index.d.ts +5 -0
- package/lib/api-keys/serializers/index.js +6 -0
- package/lib/common/exceptions/api-key-required.exception.cjs +15 -0
- package/lib/common/exceptions/api-key-required.exception.cjs.map +1 -0
- package/lib/common/exceptions/api-key-required.exception.d.cts +10 -0
- package/lib/common/exceptions/api-key-required.exception.d.ts +10 -0
- package/lib/common/exceptions/api-key-required.exception.js +14 -0
- package/lib/common/exceptions/api-key-required.exception.js.map +1 -0
- package/lib/common/exceptions/index.cjs +2 -0
- package/lib/common/exceptions/index.d.cts +2 -1
- package/lib/common/exceptions/index.d.ts +2 -1
- package/lib/common/exceptions/index.js +2 -1
- package/lib/common/interfaces/event.interface.d.cts +28 -3
- package/lib/common/interfaces/event.interface.d.ts +28 -3
- package/lib/common/interfaces/get-options.interface.d.cts +2 -0
- package/lib/common/interfaces/get-options.interface.d.ts +2 -0
- package/lib/common/interfaces/index.d.cts +2 -2
- package/lib/common/interfaces/index.d.ts +2 -2
- package/lib/common/interfaces/post-options.interface.d.cts +2 -0
- package/lib/common/interfaces/post-options.interface.d.ts +2 -0
- package/lib/common/interfaces/put-options.interface.d.cts +2 -0
- package/lib/common/interfaces/put-options.interface.d.ts +2 -0
- package/lib/common/interfaces/workos-options.interface.d.cts +1 -0
- package/lib/common/interfaces/workos-options.interface.d.ts +1 -0
- package/lib/common/net/http-client.cjs.map +1 -1
- package/lib/common/net/http-client.js.map +1 -1
- package/lib/common/serializers/event.serializer.cjs +13 -5
- package/lib/common/serializers/event.serializer.cjs.map +1 -1
- package/lib/common/serializers/event.serializer.js +13 -5
- package/lib/common/serializers/event.serializer.js.map +1 -1
- package/lib/directory-sync/directory-sync.cjs +1 -1
- package/lib/directory-sync/directory-sync.js +1 -1
- package/lib/factory.cjs +10 -0
- package/lib/factory.cjs.map +1 -0
- package/lib/factory.d.cts +83 -0
- package/lib/factory.d.ts +83 -0
- package/lib/factory.js +10 -0
- package/lib/factory.js.map +1 -0
- package/lib/feature-flags/feature-flags.cjs +37 -0
- package/lib/feature-flags/feature-flags.cjs.map +1 -0
- package/lib/feature-flags/feature-flags.d.cts +21 -0
- package/lib/feature-flags/feature-flags.d.ts +21 -0
- package/lib/feature-flags/feature-flags.js +37 -0
- package/lib/feature-flags/feature-flags.js.map +1 -0
- package/lib/feature-flags/interfaces/add-flag-target-options.interface.cjs +0 -0
- package/lib/feature-flags/interfaces/add-flag-target-options.interface.d.cts +8 -0
- package/lib/feature-flags/interfaces/add-flag-target-options.interface.d.ts +8 -0
- package/lib/feature-flags/interfaces/add-flag-target-options.interface.js +1 -0
- package/lib/feature-flags/interfaces/feature-flag.interface.d.cts +8 -2
- package/lib/feature-flags/interfaces/feature-flag.interface.d.ts +8 -2
- package/lib/feature-flags/interfaces/index.d.cts +4 -1
- package/lib/feature-flags/interfaces/index.d.ts +4 -1
- package/lib/feature-flags/interfaces/list-feature-flags-options.interface.cjs +0 -0
- package/lib/feature-flags/interfaces/list-feature-flags-options.interface.d.cts +7 -0
- package/lib/feature-flags/interfaces/list-feature-flags-options.interface.d.ts +7 -0
- package/lib/feature-flags/interfaces/list-feature-flags-options.interface.js +1 -0
- package/lib/feature-flags/interfaces/remove-flag-target-options.interface.cjs +0 -0
- package/lib/feature-flags/interfaces/remove-flag-target-options.interface.d.cts +8 -0
- package/lib/feature-flags/interfaces/remove-flag-target-options.interface.d.ts +8 -0
- package/lib/feature-flags/interfaces/remove-flag-target-options.interface.js +1 -0
- package/lib/feature-flags/serializers/feature-flag.serializer.cjs +3 -0
- package/lib/feature-flags/serializers/feature-flag.serializer.cjs.map +1 -1
- package/lib/feature-flags/serializers/feature-flag.serializer.js +3 -0
- package/lib/feature-flags/serializers/feature-flag.serializer.js.map +1 -1
- package/lib/feature-flags/serializers/index.cjs +3 -0
- package/lib/feature-flags/serializers/index.d.cts +2 -0
- package/lib/feature-flags/serializers/index.d.ts +2 -0
- package/lib/feature-flags/serializers/index.js +3 -0
- package/lib/fga/serializers/query-result.serializer.cjs.map +1 -1
- package/lib/fga/serializers/query-result.serializer.js.map +1 -1
- package/lib/index.cjs +18 -9
- package/lib/index.cjs.map +1 -1
- package/lib/index.d.cts +18 -5
- package/lib/index.d.ts +18 -5
- package/lib/index.js +16 -10
- package/lib/index.js.map +1 -1
- package/lib/index.worker.cjs +15 -9
- package/lib/index.worker.cjs.map +1 -1
- package/lib/index.worker.d.cts +10 -5
- package/lib/index.worker.d.ts +10 -5
- package/lib/index.worker.js +13 -10
- package/lib/index.worker.js.map +1 -1
- package/lib/organizations/organizations.cjs +14 -2
- package/lib/organizations/organizations.cjs.map +1 -1
- package/lib/organizations/organizations.d.cts +6 -0
- package/lib/organizations/organizations.d.ts +6 -0
- package/lib/organizations/organizations.js +14 -2
- package/lib/organizations/organizations.js.map +1 -1
- package/lib/organizations/serializers/index.cjs +1 -1
- package/lib/organizations/serializers/index.js +1 -1
- package/lib/pkce/pkce.cjs +54 -0
- package/lib/pkce/pkce.cjs.map +1 -0
- package/lib/pkce/pkce.d.cts +38 -0
- package/lib/pkce/pkce.d.ts +38 -0
- package/lib/pkce/pkce.js +53 -0
- package/lib/pkce/pkce.js.map +1 -0
- package/lib/sso/interfaces/authorization-url-options.interface.d.cts +34 -8
- package/lib/sso/interfaces/authorization-url-options.interface.d.ts +34 -8
- package/lib/sso/interfaces/get-profile-and-token-options.interface.d.cts +6 -0
- package/lib/sso/interfaces/get-profile-and-token-options.interface.d.ts +6 -0
- package/lib/sso/interfaces/index.d.cts +2 -2
- package/lib/sso/interfaces/index.d.ts +2 -2
- package/lib/sso/sso.cjs +90 -8
- package/lib/sso/sso.cjs.map +1 -1
- package/lib/sso/sso.d.cts +41 -2
- package/lib/sso/sso.d.ts +41 -2
- package/lib/sso/sso.js +90 -8
- package/lib/sso/sso.js.map +1 -1
- package/lib/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.d.cts +2 -2
- package/lib/user-management/interfaces/authenticate-with-code-and-verifier-options.interface.d.ts +2 -2
- package/lib/user-management/interfaces/authenticate-with-options-base.interface.d.cts +19 -3
- package/lib/user-management/interfaces/authenticate-with-options-base.interface.d.ts +19 -3
- package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.cjs +0 -0
- package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.d.cts +16 -0
- package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.d.ts +16 -0
- package/lib/user-management/interfaces/authenticate-with-refresh-token-public-client-options.interface.js +1 -0
- package/lib/user-management/interfaces/authorization-url-options.interface.d.cts +30 -5
- package/lib/user-management/interfaces/authorization-url-options.interface.d.ts +30 -5
- package/lib/user-management/interfaces/index.d.cts +5 -3
- package/lib/user-management/interfaces/index.d.ts +5 -3
- package/lib/user-management/interfaces/logout-url-options.interface.cjs +0 -0
- package/lib/user-management/interfaces/logout-url-options.interface.d.cts +8 -0
- package/lib/user-management/interfaces/logout-url-options.interface.d.ts +8 -0
- package/lib/user-management/interfaces/logout-url-options.interface.js +1 -0
- package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.cjs.map +1 -1
- package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.d.cts +2 -1
- package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.d.ts +2 -1
- package/lib/user-management/serializers/authenticate-with-code-and-verifier-options.serializer.js.map +1 -1
- package/lib/user-management/serializers/authenticate-with-code-options.serializer.cjs.map +1 -1
- package/lib/user-management/serializers/authenticate-with-code-options.serializer.d.cts +2 -1
- package/lib/user-management/serializers/authenticate-with-code-options.serializer.d.ts +2 -1
- package/lib/user-management/serializers/authenticate-with-code-options.serializer.js.map +1 -1
- package/lib/user-management/serializers/authenticate-with-email-verification.serializer.cjs.map +1 -1
- package/lib/user-management/serializers/authenticate-with-email-verification.serializer.d.cts +2 -1
- package/lib/user-management/serializers/authenticate-with-email-verification.serializer.d.ts +2 -1
- package/lib/user-management/serializers/authenticate-with-email-verification.serializer.js.map +1 -1
- package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.cjs.map +1 -1
- package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.d.cts +2 -1
- package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.d.ts +2 -1
- package/lib/user-management/serializers/authenticate-with-magic-auth-options.serializer.js.map +1 -1
- package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.cjs.map +1 -1
- package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.d.cts +2 -1
- package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.d.ts +2 -1
- package/lib/user-management/serializers/authenticate-with-organization-selection-options.serializer.js.map +1 -1
- package/lib/user-management/serializers/authenticate-with-password-options.serializer.cjs.map +1 -1
- package/lib/user-management/serializers/authenticate-with-password-options.serializer.d.cts +2 -1
- package/lib/user-management/serializers/authenticate-with-password-options.serializer.d.ts +2 -1
- package/lib/user-management/serializers/authenticate-with-password-options.serializer.js.map +1 -1
- package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.cjs +14 -0
- package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.cjs.map +1 -0
- package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.d.cts +8 -0
- package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.d.ts +8 -0
- package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.js +13 -0
- package/lib/user-management/serializers/authenticate-with-refresh-token-public-client-options.serializer.js.map +1 -0
- package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.cjs.map +1 -1
- package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.d.cts +2 -1
- package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.d.ts +2 -1
- package/lib/user-management/serializers/authenticate-with-refresh-token.options.serializer.js.map +1 -1
- package/lib/user-management/serializers/authenticate-with-totp-options.serializer.cjs.map +1 -1
- package/lib/user-management/serializers/authenticate-with-totp-options.serializer.d.cts +2 -1
- package/lib/user-management/serializers/authenticate-with-totp-options.serializer.d.ts +2 -1
- package/lib/user-management/serializers/authenticate-with-totp-options.serializer.js.map +1 -1
- package/lib/user-management/serializers/index.cjs +2 -0
- package/lib/user-management/serializers/index.d.cts +2 -1
- package/lib/user-management/serializers/index.d.ts +2 -1
- package/lib/user-management/serializers/index.js +2 -1
- package/lib/user-management/session.cjs +3 -10
- package/lib/user-management/session.cjs.map +1 -1
- package/lib/user-management/session.js +3 -10
- package/lib/user-management/session.js.map +1 -1
- package/lib/user-management/user-management.cjs +186 -31
- package/lib/user-management/user-management.cjs.map +1 -1
- package/lib/user-management/user-management.d.cts +71 -2
- package/lib/user-management/user-management.d.ts +71 -2
- package/lib/user-management/user-management.js +186 -31
- package/lib/user-management/user-management.js.map +1 -1
- package/lib/vault/vault.cjs +4 -0
- package/lib/vault/vault.cjs.map +1 -1
- package/lib/vault/vault.d.cts +1 -0
- package/lib/vault/vault.d.ts +1 -0
- package/lib/vault/vault.js +4 -0
- package/lib/vault/vault.js.map +1 -1
- package/lib/webhooks/webhooks.cjs +1 -1
- package/lib/webhooks/webhooks.js +1 -1
- package/lib/workos.cjs +68 -26
- package/lib/workos.cjs.map +1 -1
- package/lib/workos.d.cts +37 -8
- package/lib/workos.d.ts +37 -8
- package/lib/workos.js +68 -26
- package/lib/workos.js.map +1 -1
- package/package.json +4 -21
- package/lib/_virtual/rolldown_runtime.cjs +0 -19
- package/lib/_virtual/rolldown_runtime.js +0 -18
- package/lib/client/index.cjs +0 -15
- package/lib/client/index.d.cts +0 -3
- package/lib/client/index.d.ts +0 -3
- package/lib/client/index.js +0 -4
- package/lib/client/sso.cjs +0 -40
- package/lib/client/sso.cjs.map +0 -1
- package/lib/client/sso.d.cts +0 -21
- package/lib/client/sso.d.ts +0 -21
- package/lib/client/sso.js +0 -34
- package/lib/client/sso.js.map +0 -1
- package/lib/client/user-management.cjs +0 -80
- package/lib/client/user-management.cjs.map +0 -1
- package/lib/client/user-management.d.cts +0 -58
- package/lib/client/user-management.d.ts +0 -58
- package/lib/client/user-management.js +0 -72
- package/lib/client/user-management.js.map +0 -1
- package/lib/index.client.cjs +0 -15
- package/lib/index.client.d.cts +0 -3
- package/lib/index.client.d.ts +0 -3
- 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
|
package/lib/pkce/pkce.js
ADDED
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
+
};
|
|
42
|
+
type SSOWithOrganization = SSOAuthorizationURLBaseFields & PKCEFields & {
|
|
17
43
|
organization: string;
|
|
18
44
|
connection?: never;
|
|
19
45
|
provider?: never;
|
|
20
|
-
}
|
|
21
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
41
|
+
};
|
|
42
|
+
type SSOWithOrganization = SSOAuthorizationURLBaseFields & PKCEFields & {
|
|
17
43
|
organization: string;
|
|
18
44
|
connection?: never;
|
|
19
45
|
provider?: never;
|
|
20
|
-
}
|
|
21
|
-
|
|
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
|
|
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
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 }) {
|
package/lib/sso/sso.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sso.cjs","names":["workos: WorkOS","AutoPaginatable","fetchAndDeserialize","deserializeConnection","serializeListConnectionsOptions","deserializeProfileAndToken","deserializeProfile"],"sources":["../../src/sso/sso.ts"],"sourcesContent":["import
|
|
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
|