@schemavaults/auth-common 0.7.27
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/dist/audience-schema.d.ts +3 -0
- package/dist/audience-schema.js +12 -0
- package/dist/audience-schema.js.map +1 -0
- package/dist/auth_acquire_tokens_grant_types.d.ts +80 -0
- package/dist/auth_acquire_tokens_grant_types.js +48 -0
- package/dist/auth_acquire_tokens_grant_types.js.map +1 -0
- package/dist/authenticate_result.d.ts +15 -0
- package/dist/authenticate_result.js +12 -0
- package/dist/authenticate_result.js.map +1 -0
- package/dist/credentials/email_credentials.d.ts +12 -0
- package/dist/credentials/email_credentials.js +10 -0
- package/dist/credentials/email_credentials.js.map +1 -0
- package/dist/credentials/index.d.ts +3 -0
- package/dist/credentials/index.js +4 -0
- package/dist/credentials/index.js.map +1 -0
- package/dist/credentials/password_requirements.d.ts +2 -0
- package/dist/credentials/password_requirements.js +17 -0
- package/dist/credentials/password_requirements.js.map +1 -0
- package/dist/credentials/register_credentials.d.ts +28 -0
- package/dist/credentials/register_credentials.js +13 -0
- package/dist/credentials/register_credentials.js.map +1 -0
- package/dist/frontend-client-state.d.ts +4 -0
- package/dist/frontend-client-state.js +2 -0
- package/dist/frontend-client-state.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/invite-code/index.d.ts +4 -0
- package/dist/invite-code/index.js +3 -0
- package/dist/invite-code/index.js.map +1 -0
- package/dist/invite-code/invite-code-definition.d.ts +21 -0
- package/dist/invite-code/invite-code-definition.js +18 -0
- package/dist/invite-code/invite-code-definition.js.map +1 -0
- package/dist/invite-code/invite-code-format.d.ts +3 -0
- package/dist/invite-code/invite-code-format.js +9 -0
- package/dist/invite-code/invite-code-format.js.map +1 -0
- package/dist/is_crypto_api_available.d.ts +1 -0
- package/dist/is_crypto_api_available.js +31 -0
- package/dist/is_crypto_api_available.js.map +1 -0
- package/dist/middleware/auth-middleware-error.d.ts +4 -0
- package/dist/middleware/auth-middleware-error.js +12 -0
- package/dist/middleware/auth-middleware-error.js.map +1 -0
- package/dist/middleware/auth-middleware.d.ts +36 -0
- package/dist/middleware/auth-middleware.js +177 -0
- package/dist/middleware/auth-middleware.js.map +1 -0
- package/dist/middleware/compare-path.d.ts +2 -0
- package/dist/middleware/compare-path.js +14 -0
- package/dist/middleware/compare-path.js.map +1 -0
- package/dist/middleware/decode-first-of-several-jwts.d.ts +10 -0
- package/dist/middleware/decode-first-of-several-jwts.js +56 -0
- package/dist/middleware/decode-first-of-several-jwts.js.map +1 -0
- package/dist/middleware/decode-token-type.d.ts +9 -0
- package/dist/middleware/decode-token-type.js +2 -0
- package/dist/middleware/decode-token-type.js.map +1 -0
- package/dist/middleware/default-auth-middleware-rules.d.ts +7 -0
- package/dist/middleware/default-auth-middleware-rules.js +24 -0
- package/dist/middleware/default-auth-middleware-rules.js.map +1 -0
- package/dist/middleware/determine-auth-status.d.ts +13 -0
- package/dist/middleware/determine-auth-status.js +91 -0
- package/dist/middleware/determine-auth-status.js.map +1 -0
- package/dist/middleware/index.d.ts +10 -0
- package/dist/middleware/index.js +6 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/middleware-rules.d.ts +30 -0
- package/dist/middleware/middleware-rules.js +117 -0
- package/dist/middleware/middleware-rules.js.map +1 -0
- package/dist/middleware/parse-navigation-path.d.ts +3 -0
- package/dist/middleware/parse-navigation-path.js +28 -0
- package/dist/middleware/parse-navigation-path.js.map +1 -0
- package/dist/middleware/token-source.d.ts +6 -0
- package/dist/middleware/token-source.js +2 -0
- package/dist/middleware/token-source.js.map +1 -0
- package/dist/organizations/index.d.ts +5 -0
- package/dist/organizations/index.js +4 -0
- package/dist/organizations/index.js.map +1 -0
- package/dist/organizations/organization_constants.d.ts +4 -0
- package/dist/organizations/organization_constants.js +5 -0
- package/dist/organizations/organization_constants.js.map +1 -0
- package/dist/organizations/organization_definition.d.ts +15 -0
- package/dist/organizations/organization_definition.js +20 -0
- package/dist/organizations/organization_definition.js.map +1 -0
- package/dist/organizations/organization_id.d.ts +4 -0
- package/dist/organizations/organization_id.js +17 -0
- package/dist/organizations/organization_id.js.map +1 -0
- package/dist/organizations/schemavaults_org_id.d.ts +1 -0
- package/dist/organizations/schemavaults_org_id.js +2 -0
- package/dist/organizations/schemavaults_org_id.js.map +1 -0
- package/dist/pkce/code_challenge.d.ts +31 -0
- package/dist/pkce/code_challenge.js +43 -0
- package/dist/pkce/code_challenge.js.map +1 -0
- package/dist/pkce/code_verifier.d.ts +27 -0
- package/dist/pkce/code_verifier.js +76 -0
- package/dist/pkce/code_verifier.js.map +1 -0
- package/dist/pkce/index.d.ts +5 -0
- package/dist/pkce/index.js +3 -0
- package/dist/pkce/index.js.map +1 -0
- package/dist/pkce/pkce.d.ts +63 -0
- package/dist/pkce/pkce.js +141 -0
- package/dist/pkce/pkce.js.map +1 -0
- package/dist/pkce/sha256_digest/index.d.ts +1 -0
- package/dist/pkce/sha256_digest/index.js +2 -0
- package/dist/pkce/sha256_digest/index.js.map +1 -0
- package/dist/pkce/sha256_digest/sha256_digest.d.ts +3 -0
- package/dist/pkce/sha256_digest/sha256_digest.js +30 -0
- package/dist/pkce/sha256_digest/sha256_digest.js.map +1 -0
- package/dist/request_tokens_result.d.ts +342 -0
- package/dist/request_tokens_result.js +52 -0
- package/dist/request_tokens_result.js.map +1 -0
- package/dist/sha256_digest/cryptojs_pkg_sha256.d.ts +2 -0
- package/dist/sha256_digest/cryptojs_pkg_sha256.js +11 -0
- package/dist/sha256_digest/cryptojs_pkg_sha256.js.map +1 -0
- package/dist/sha256_digest/index.d.ts +1 -0
- package/dist/sha256_digest/index.js +2 -0
- package/dist/sha256_digest/index.js.map +1 -0
- package/dist/sha256_digest/sha256_digest.d.ts +3 -0
- package/dist/sha256_digest/sha256_digest.js +28 -0
- package/dist/sha256_digest/sha256_digest.js.map +1 -0
- package/dist/sha256_digest/webcrypto_sha256.d.ts +1 -0
- package/dist/sha256_digest/webcrypto_sha256.js +5 -0
- package/dist/sha256_digest/webcrypto_sha256.js.map +1 -0
- package/dist/token-data/index.d.ts +3 -0
- package/dist/token-data/index.js +3 -0
- package/dist/token-data/index.js.map +1 -0
- package/dist/token-data/token-data.d.ts +102 -0
- package/dist/token-data/token-data.js +29 -0
- package/dist/token-data/token-data.js.map +1 -0
- package/dist/token-data/token-expiry.d.ts +16 -0
- package/dist/token-data/token-expiry.js +48 -0
- package/dist/token-data/token-expiry.js.map +1 -0
- package/dist/user_data/index.d.ts +1 -0
- package/dist/user_data/index.js +2 -0
- package/dist/user_data/index.js.map +1 -0
- package/dist/user_data/user_data.d.ts +58 -0
- package/dist/user_data/user_data.js +33 -0
- package/dist/user_data/user_data.js.map +1 -0
- package/dist/utils/maybeStripQuotes.d.ts +2 -0
- package/dist/utils/maybeStripQuotes.js +14 -0
- package/dist/utils/maybeStripQuotes.js.map +1 -0
- package/package.json +43 -0
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
function stripSearchParams(path_url) {
|
|
2
|
+
if (!path_url.includes("?")) {
|
|
3
|
+
return path_url;
|
|
4
|
+
}
|
|
5
|
+
return path_url.split("?")[0];
|
|
6
|
+
}
|
|
7
|
+
export function parseNavigationPath(path_url) {
|
|
8
|
+
if (typeof path_url !== "string") {
|
|
9
|
+
throw new Error(`parseNavigationPath: path_url must be a string, received type ${typeof path_url}`);
|
|
10
|
+
}
|
|
11
|
+
let url = path_url;
|
|
12
|
+
if (url.startsWith("//")) {
|
|
13
|
+
url = url.slice(2);
|
|
14
|
+
}
|
|
15
|
+
else if (url.startsWith("/")) {
|
|
16
|
+
url = url.slice(1);
|
|
17
|
+
}
|
|
18
|
+
if (url.endsWith("/")) {
|
|
19
|
+
url = url.slice(0, -1);
|
|
20
|
+
}
|
|
21
|
+
if (url === "") {
|
|
22
|
+
return [];
|
|
23
|
+
}
|
|
24
|
+
url = stripSearchParams(url);
|
|
25
|
+
return url.split("/");
|
|
26
|
+
}
|
|
27
|
+
export default parseNavigationPath;
|
|
28
|
+
//# sourceMappingURL=parse-navigation-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"parse-navigation-path.js","sourceRoot":"","sources":["../../src/middleware/parse-navigation-path.ts"],"names":[],"mappings":"AAEA,SAAS,iBAAiB,CAAC,QAAgB;IACzC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC5B,OAAO,QAAQ,CAAC;IAClB,CAAC;IACD,OAAO,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,QAAgB;IAClD,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,iEAAiE,OAAO,QAAQ,EAAE,CACnF,CAAC;IACJ,CAAC;IACD,IAAI,GAAG,GAAW,QAAQ,CAAC;IAE3B,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACzB,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;SAAM,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/B,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QACtB,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IACzB,CAAC;IACD,IAAI,GAAG,KAAK,EAAE,EAAE,CAAC;QACf,OAAO,EAAE,CAAC;IACZ,CAAC;IAED,GAAG,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IAE7B,OAAO,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,eAAe,mBAAmB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-source.js","sourceRoot":"","sources":["../../src/middleware/token-source.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { organizationIdSchema, isValidOrganizationID } from "./organization_id";
|
|
2
|
+
export type { OrganizationID } from "./organization_id";
|
|
3
|
+
export { organizationDefinitionSchema } from "./organization_definition";
|
|
4
|
+
export type { OrganizationDefinition } from "./organization_definition";
|
|
5
|
+
export { SCHEMAVAULTS_ORGANIZATION_ID } from "./schemavaults_org_id";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/organizations/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAGhF,OAAO,EAAE,4BAA4B,EAAE,MAAM,2BAA2B,CAAC;AAGzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization_constants.js","sourceRoot":"","sources":["../../src/organizations/organization_constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAA2B,CAAC;AAC1E,MAAM,CAAC,MAAM,8BAA8B,GAAG,EAA4B,CAAC;AAE3E,MAAM,CAAC,MAAM,gCAAgC,GAAG,CAA2B,CAAC;AAC5E,MAAM,CAAC,MAAM,gCAAgC,GAAG,EAA4B,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const organizationDefinitionSchema: z.ZodObject<{
|
|
3
|
+
organization_id: z.ZodEffects<z.ZodString, string, string>;
|
|
4
|
+
name: z.ZodString;
|
|
5
|
+
created_at: z.ZodNumber;
|
|
6
|
+
}, "strict", z.ZodTypeAny, {
|
|
7
|
+
organization_id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
created_at: number;
|
|
10
|
+
}, {
|
|
11
|
+
organization_id: string;
|
|
12
|
+
name: string;
|
|
13
|
+
created_at: number;
|
|
14
|
+
}>;
|
|
15
|
+
export type OrganizationDefinition = z.infer<typeof organizationDefinitionSchema>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { organizationIdSchema } from "./organization_id";
|
|
3
|
+
import { MAXIMUM_ORGANIZATION_NAME_LENGTH, MINIMUM_ORGANIZATION_NAME_LENGTH, } from "./organization_constants";
|
|
4
|
+
const organizationNameSchema = z
|
|
5
|
+
.string()
|
|
6
|
+
.min(MINIMUM_ORGANIZATION_NAME_LENGTH, `Organization name must be at least ${MINIMUM_ORGANIZATION_NAME_LENGTH} character${MINIMUM_ORGANIZATION_NAME_LENGTH >= 2 ? "s" : ""} long.`)
|
|
7
|
+
.max(MAXIMUM_ORGANIZATION_NAME_LENGTH, `Organization name may not be longer than ${MAXIMUM_ORGANIZATION_NAME_LENGTH} characters long.`);
|
|
8
|
+
export const organizationDefinitionSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
organization_id: organizationIdSchema,
|
|
11
|
+
name: organizationNameSchema,
|
|
12
|
+
created_at: z.number().positive(),
|
|
13
|
+
})
|
|
14
|
+
.required({
|
|
15
|
+
organization_id: true,
|
|
16
|
+
name: true,
|
|
17
|
+
created_at: true,
|
|
18
|
+
})
|
|
19
|
+
.strict();
|
|
20
|
+
//# sourceMappingURL=organization_definition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization_definition.js","sourceRoot":"","sources":["../../src/organizations/organization_definition.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AACzD,OAAO,EACL,gCAAgC,EAChC,gCAAgC,GACjC,MAAM,0BAA0B,CAAC;AAElC,MAAM,sBAAsB,GAAG,CAAC;KAC7B,MAAM,EAAE;KACR,GAAG,CACF,gCAAgC,EAChC,sCAAsC,gCAAgC,aAAa,gCAAgC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,QAAQ,CAC5I;KACA,GAAG,CACF,gCAAgC,EAChC,4CAA4C,gCAAgC,mBAAmB,CAChG,CAAC;AAEJ,MAAM,CAAC,MAAM,4BAA4B,GAAG,CAAC;KAC1C,MAAM,CAAC;IACN,eAAe,EAAE,oBAAoB;IACrC,IAAI,EAAE,sBAAsB;IAC5B,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAClC,CAAC;KACD,QAAQ,CAAC;IACR,eAAe,EAAE,IAAI;IACrB,IAAI,EAAE,IAAI;IACV,UAAU,EAAE,IAAI;CACjB,CAAC;KACD,MAAM,EAAE,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const organizationIdSchema: z.ZodEffects<z.ZodString, string, string>;
|
|
3
|
+
export type OrganizationID = z.infer<typeof organizationIdSchema>;
|
|
4
|
+
export declare function isValidOrganizationID(organization_id: string): organization_id is OrganizationID;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { MAXIMUM_ORGANIZATION_ID_LENGTH, MINIMUM_ORGANIZATION_ID_LENGTH, } from "./organization_constants";
|
|
3
|
+
export const organizationIdSchema = z
|
|
4
|
+
.string()
|
|
5
|
+
.min(MINIMUM_ORGANIZATION_ID_LENGTH, `Organization ID must be at least ${MINIMUM_ORGANIZATION_ID_LENGTH} characters long.`)
|
|
6
|
+
.max(MAXIMUM_ORGANIZATION_ID_LENGTH, `Organization ID may not be longer than ${MAXIMUM_ORGANIZATION_ID_LENGTH} characters long.`)
|
|
7
|
+
.regex(/^[a-z][a-z0-9_-]+$/, "Organization ID must start with a letter, and may only contain lowercase alphanumeric characters, numbers, hyphens and underscores.")
|
|
8
|
+
.refine((orgId) => {
|
|
9
|
+
if (orgId.endsWith("_") || orgId.endsWith("-")) {
|
|
10
|
+
return false;
|
|
11
|
+
}
|
|
12
|
+
return true;
|
|
13
|
+
}, "Organization ID may not end with a hyphen or dash.");
|
|
14
|
+
export function isValidOrganizationID(organization_id) {
|
|
15
|
+
return organizationIdSchema.safeParse(organization_id).success;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=organization_id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organization_id.js","sourceRoot":"","sources":["../../src/organizations/organization_id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EACL,8BAA8B,EAC9B,8BAA8B,GAC/B,MAAM,0BAA0B,CAAC;AAElC,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC;KAClC,MAAM,EAAE;KACR,GAAG,CACF,8BAA8B,EAC9B,oCAAoC,8BAA8B,mBAAmB,CACtF;KACA,GAAG,CACF,8BAA8B,EAC9B,0CAA0C,8BAA8B,mBAAmB,CAC5F;KACA,KAAK,CACJ,oBAAoB,EACpB,qIAAqI,CACtI;KACA,MAAM,CAAC,CAAC,KAAa,EAAW,EAAE;IACjC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC,EAAE,oDAAoD,CAAC,CAAC;AAI3D,MAAM,UAAU,qBAAqB,CACnC,eAAuB;IAEvB,OAAO,oBAAoB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC;AACjE,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const SCHEMAVAULTS_ORGANIZATION_ID: "schemavaults";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schemavaults_org_id.js","sourceRoot":"","sources":["../../src/organizations/schemavaults_org_id.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,4BAA4B,GACvC,cAAgD,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { type CodeVerifierWithDetails, type CodeVerifier } from "./code_verifier";
|
|
3
|
+
export declare const code_challenge_method: "S256";
|
|
4
|
+
export interface CreateCodeChallengeInputOptions {
|
|
5
|
+
code_verifier: Partial<CodeVerifierWithDetails> & {
|
|
6
|
+
code_verifier: CodeVerifier;
|
|
7
|
+
challenge_time: number;
|
|
8
|
+
};
|
|
9
|
+
sha256_digest: (code_verifier: string) => Promise<string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function create_code_challenge(verifier_opts: CreateCodeChallengeInputOptions): Promise<CodeChallengeWithDetails>;
|
|
12
|
+
export declare const codeChallengeSchema: z.ZodEffects<z.ZodString, string, string>;
|
|
13
|
+
export type CodeChallenge = z.infer<typeof codeChallengeSchema>;
|
|
14
|
+
export declare const codeChallengeWithDetailsSchema: z.ZodObject<{
|
|
15
|
+
code_challenge: z.ZodEffects<z.ZodString, string, string>;
|
|
16
|
+
code_challenge_method: z.ZodLiteral<"S256">;
|
|
17
|
+
challenge_time: z.ZodNumber;
|
|
18
|
+
}, "strict", z.ZodTypeAny, {
|
|
19
|
+
challenge_time: number;
|
|
20
|
+
code_challenge: string;
|
|
21
|
+
code_challenge_method: "S256";
|
|
22
|
+
}, {
|
|
23
|
+
challenge_time: number;
|
|
24
|
+
code_challenge: string;
|
|
25
|
+
code_challenge_method: "S256";
|
|
26
|
+
}>;
|
|
27
|
+
export type CodeChallengeWithDetails = {
|
|
28
|
+
code_challenge: CodeChallenge;
|
|
29
|
+
code_challenge_method: typeof code_challenge_method;
|
|
30
|
+
challenge_time: number;
|
|
31
|
+
};
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { MAX_PKCE_CODE_VERIFIER_AGE } from "./code_verifier";
|
|
3
|
+
export const code_challenge_method = 'S256';
|
|
4
|
+
// Create code challenge for Oauth2 PKCE
|
|
5
|
+
// https://datatracker.ietf.org/doc/html/rfc7636#section-4.2
|
|
6
|
+
export async function create_code_challenge(verifier_opts) {
|
|
7
|
+
if (!verifier_opts.code_verifier) {
|
|
8
|
+
throw new Error("[create_code_challenge] Missing code_verifier");
|
|
9
|
+
}
|
|
10
|
+
const { expires_at, max_age, code_verifier, challenge_time } = verifier_opts.code_verifier;
|
|
11
|
+
code_verifier;
|
|
12
|
+
if (typeof expires_at === 'number') {
|
|
13
|
+
if (expires_at < Date.now()) {
|
|
14
|
+
throw new Error("Code verifier has expired");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
if (typeof max_age === 'number' && max_age !== MAX_PKCE_CODE_VERIFIER_AGE) {
|
|
18
|
+
throw new Error("Code verifier has invalid max_age");
|
|
19
|
+
}
|
|
20
|
+
const base64url_encoded_hash = await verifier_opts.sha256_digest(code_verifier);
|
|
21
|
+
if (typeof challenge_time !== 'number') {
|
|
22
|
+
throw new Error("'challenge_time' is a required field!");
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
code_challenge: base64url_encoded_hash,
|
|
26
|
+
code_challenge_method,
|
|
27
|
+
challenge_time
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const MIN_CODE_CHALLENGE_LENGTH = 43;
|
|
31
|
+
const MAX_CODE_CHALLENGE_LENGTH = 1024;
|
|
32
|
+
export const codeChallengeSchema = z.string()
|
|
33
|
+
.min(MIN_CODE_CHALLENGE_LENGTH)
|
|
34
|
+
.max(MAX_CODE_CHALLENGE_LENGTH)
|
|
35
|
+
.refine(value => /^[A-Za-z0-9_-]+$/.test(value), {
|
|
36
|
+
message: `Code challenge is not base64url encoded string`,
|
|
37
|
+
});
|
|
38
|
+
export const codeChallengeWithDetailsSchema = z.object({
|
|
39
|
+
code_challenge: codeChallengeSchema,
|
|
40
|
+
code_challenge_method: z.literal(code_challenge_method),
|
|
41
|
+
challenge_time: z.number().nonnegative()
|
|
42
|
+
}).required().strict();
|
|
43
|
+
//# sourceMappingURL=code_challenge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code_challenge.js","sourceRoot":"","sources":["../../src/pkce/code_challenge.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAgC,0BAA0B,EAAqB,MAAM,iBAAiB,CAAC;AAE9G,MAAM,CAAC,MAAM,qBAAqB,GAAG,MAAe,CAAC;AAOrD,wCAAwC;AACxC,4DAA4D;AAC5D,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,aAA8C;IAE9C,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnE,CAAC;IAED,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,GAAG,aAAa,CAAC,aAAa,CAAC;IAC3F,aAAoC,CAAC;IACrC,IAAI,OAAO,UAAU,KAAK,QAAQ,EAAE,CAAC;QACnC,IAAI,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;QAC/C,CAAC;IACH,CAAC;IAED,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAK,OAAO,KAAK,0BAA0B,EAAE,CAAC;QAC3E,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;IACvD,CAAC;IAED,MAAM,sBAAsB,GAAG,MAAM,aAAa,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC;IAEhF,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;QACvC,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO;QACL,cAAc,EAAE,sBAAsB;QACtC,qBAAqB;QACrB,cAAc;KACf,CAAC;AACJ,CAAC;AAED,MAAM,yBAAyB,GAAG,EAAW,CAAC;AAC9C,MAAM,yBAAyB,GAAG,IAAa,CAAC;AAEhD,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,CAAC,MAAM,EAAE;KAC1C,GAAG,CAAC,yBAAyB,CAAC;KAC9B,GAAG,CAAC,yBAAyB,CAAC;KAC9B,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;IAC/C,OAAO,EAAE,gDAAgD;CAC1D,CAAC,CAAC;AAIL,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,CAAC,MAAM,CAAC;IACrD,cAAc,EAAE,mBAAmB;IACnC,qBAAqB,EAAE,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC;IACvD,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,WAAW,EAAE;CACzC,CAAC,CAAC,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAA"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export declare const MAX_PKCE_CODE_VERIFIER_AGE: number;
|
|
3
|
+
export interface CreateCodeVerifierInputOptions {
|
|
4
|
+
challenge_time?: number;
|
|
5
|
+
generateRandomCodeVerifier?: () => string;
|
|
6
|
+
debug?: boolean;
|
|
7
|
+
}
|
|
8
|
+
export declare function create_code_verifier({ challenge_time, generateRandomCodeVerifier, debug, }: CreateCodeVerifierInputOptions): CodeVerifierWithDetails;
|
|
9
|
+
export declare const codeVerifierSchema: z.ZodEffects<z.ZodString, string, string>;
|
|
10
|
+
export type CodeVerifier = z.infer<typeof codeVerifierSchema>;
|
|
11
|
+
export declare const codeVerifierWithDetailsSchema: z.ZodObject<{
|
|
12
|
+
challenge_time: z.ZodNumber;
|
|
13
|
+
code_verifier: z.ZodEffects<z.ZodString, string, string>;
|
|
14
|
+
expires_at: z.ZodNumber;
|
|
15
|
+
max_age: z.ZodNumber;
|
|
16
|
+
}, "strict", z.ZodTypeAny, {
|
|
17
|
+
challenge_time: number;
|
|
18
|
+
code_verifier: string;
|
|
19
|
+
expires_at: number;
|
|
20
|
+
max_age: number;
|
|
21
|
+
}, {
|
|
22
|
+
challenge_time: number;
|
|
23
|
+
code_verifier: string;
|
|
24
|
+
expires_at: number;
|
|
25
|
+
max_age: number;
|
|
26
|
+
}>;
|
|
27
|
+
export type CodeVerifierWithDetails = z.infer<typeof codeVerifierWithDetailsSchema>;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import isCryptoApiAvailable from "../is_crypto_api_available";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
const MIN_CODE_VERIFIER_LENGTH = 43;
|
|
4
|
+
const MAX_CODE_VERIFIER_LENGTH = 1024;
|
|
5
|
+
export const MAX_PKCE_CODE_VERIFIER_AGE = 1000 * 60 * 60; // 1 hour
|
|
6
|
+
function secureContextRandomCharacters() {
|
|
7
|
+
return Buffer.from(crypto.getRandomValues(new Uint8Array(512))).toString("base64");
|
|
8
|
+
}
|
|
9
|
+
function generatePseudoRandomBase64String() {
|
|
10
|
+
const randomCodeVerifierLength = Math.floor(Math.random() * (MAX_CODE_VERIFIER_LENGTH - MIN_CODE_VERIFIER_LENGTH + 1)) + MIN_CODE_VERIFIER_LENGTH;
|
|
11
|
+
const clamped_n_chars = Math.max(MIN_CODE_VERIFIER_LENGTH, Math.min(MAX_CODE_VERIFIER_LENGTH, randomCodeVerifierLength));
|
|
12
|
+
const n_chars = clamped_n_chars;
|
|
13
|
+
const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
14
|
+
let result = "";
|
|
15
|
+
for (let i = 0; i < n_chars; i++) {
|
|
16
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
17
|
+
}
|
|
18
|
+
return result;
|
|
19
|
+
}
|
|
20
|
+
// Create code verifier for Oauth2 PKCE
|
|
21
|
+
// https://datatracker.ietf.org/doc/html/rfc7636#section-4.1
|
|
22
|
+
export function create_code_verifier({ challenge_time, generateRandomCodeVerifier, debug = false, }) {
|
|
23
|
+
try {
|
|
24
|
+
let code_verifier = typeof generateRandomCodeVerifier === "function"
|
|
25
|
+
? generateRandomCodeVerifier()
|
|
26
|
+
: (() => {
|
|
27
|
+
if (isCryptoApiAvailable()) {
|
|
28
|
+
return secureContextRandomCharacters();
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
return generatePseudoRandomBase64String();
|
|
32
|
+
}
|
|
33
|
+
})();
|
|
34
|
+
const base64url_encoded_verifier = code_verifier.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
35
|
+
if (debug) {
|
|
36
|
+
console.log("Created new code_verifier: ", base64url_encoded_verifier);
|
|
37
|
+
}
|
|
38
|
+
if (base64url_encoded_verifier.length < MIN_CODE_VERIFIER_LENGTH ||
|
|
39
|
+
base64url_encoded_verifier.length > MAX_CODE_VERIFIER_LENGTH) {
|
|
40
|
+
throw new Error(`Invalid code_verifier length: ${base64url_encoded_verifier.length}`);
|
|
41
|
+
}
|
|
42
|
+
const now = typeof challenge_time === "number" ? challenge_time : Date.now();
|
|
43
|
+
return {
|
|
44
|
+
code_verifier: base64url_encoded_verifier,
|
|
45
|
+
challenge_time: now,
|
|
46
|
+
expires_at: now + MAX_PKCE_CODE_VERIFIER_AGE - 1,
|
|
47
|
+
max_age: MAX_PKCE_CODE_VERIFIER_AGE,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
console.error("Failed to generate a new code_verifier with crypto: ", e);
|
|
52
|
+
throw new Error("Failed to generate a new code_verifier with crypto");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export const codeVerifierSchema = z
|
|
56
|
+
.string()
|
|
57
|
+
.min(MIN_CODE_VERIFIER_LENGTH)
|
|
58
|
+
.max(MAX_CODE_VERIFIER_LENGTH)
|
|
59
|
+
.refine((value) => /^[A-Za-z0-9_-]+$/.test(value), {
|
|
60
|
+
message: `Code verifier is not base64url encoded string`,
|
|
61
|
+
});
|
|
62
|
+
export const codeVerifierWithDetailsSchema = z
|
|
63
|
+
.object({
|
|
64
|
+
code_verifier: codeVerifierSchema,
|
|
65
|
+
challenge_time: z.number().nonnegative(),
|
|
66
|
+
expires_at: z.number().nonnegative(),
|
|
67
|
+
max_age: z.number().nonnegative(),
|
|
68
|
+
})
|
|
69
|
+
.required({
|
|
70
|
+
code_verifier: true,
|
|
71
|
+
challenge_time: true,
|
|
72
|
+
expires_at: true,
|
|
73
|
+
max_age: true,
|
|
74
|
+
})
|
|
75
|
+
.strict();
|
|
76
|
+
//# sourceMappingURL=code_verifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code_verifier.js","sourceRoot":"","sources":["../../src/pkce/code_verifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { PKCE_ProofKeyManager } from './pkce';
|
|
2
|
+
export type * from './pkce';
|
|
3
|
+
export type { CodeChallenge, CodeChallengeWithDetails } from './code_challenge';
|
|
4
|
+
export type { CodeVerifier, CodeVerifierWithDetails } from './code_verifier';
|
|
5
|
+
export { MAX_PKCE_CODE_VERIFIER_AGE } from './code_verifier';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pkce/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,QAAQ,CAAC;AAK9C,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { code_challenge_method, type CodeChallengeWithDetails } from "./code_challenge";
|
|
2
|
+
import { type CodeVerifier, type CodeVerifierWithDetails } from "./code_verifier";
|
|
3
|
+
interface CheckWhetherVerifierMatchesChallengeInputOptions {
|
|
4
|
+
input_code_verifier: string;
|
|
5
|
+
saved_code_challenge: string;
|
|
6
|
+
challenge_time: number;
|
|
7
|
+
}
|
|
8
|
+
export declare class PKCE_ProofKeyManager {
|
|
9
|
+
private code_verifier;
|
|
10
|
+
static createCodeVerifier(challenge_time?: number): CodeVerifierWithDetails;
|
|
11
|
+
static createCodeChallenge(code_verifier: CodeVerifierWithDetails): Promise<CodeChallengeWithDetails>;
|
|
12
|
+
constructor(code_verifier?: Partial<CodeVerifierWithDetails> & {
|
|
13
|
+
challenge_time: number;
|
|
14
|
+
code_verifier: CodeVerifier;
|
|
15
|
+
});
|
|
16
|
+
getCodeChallenge(): Promise<CodeChallengeWithDetails>;
|
|
17
|
+
get challenge_time(): number;
|
|
18
|
+
get expiry_time(): number;
|
|
19
|
+
static get codeVerifierSchema(): import("zod").ZodEffects<import("zod").ZodString, string, string>;
|
|
20
|
+
static get codeVerifierWithDetailsSchema(): import("zod").ZodObject<{
|
|
21
|
+
challenge_time: import("zod").ZodNumber;
|
|
22
|
+
code_verifier: import("zod").ZodEffects<import("zod").ZodString, string, string>;
|
|
23
|
+
expires_at: import("zod").ZodNumber;
|
|
24
|
+
max_age: import("zod").ZodNumber;
|
|
25
|
+
}, "strict", import("zod").ZodTypeAny, {
|
|
26
|
+
challenge_time: number;
|
|
27
|
+
code_verifier: string;
|
|
28
|
+
expires_at: number;
|
|
29
|
+
max_age: number;
|
|
30
|
+
}, {
|
|
31
|
+
challenge_time: number;
|
|
32
|
+
code_verifier: string;
|
|
33
|
+
expires_at: number;
|
|
34
|
+
max_age: number;
|
|
35
|
+
}>;
|
|
36
|
+
static get codeChallengeSchema(): import("zod").ZodEffects<import("zod").ZodString, string, string>;
|
|
37
|
+
static get codeChallengeWithOptionsSchema(): import("zod").ZodObject<{
|
|
38
|
+
code_challenge: import("zod").ZodEffects<import("zod").ZodString, string, string>;
|
|
39
|
+
code_challenge_method: import("zod").ZodLiteral<"S256">;
|
|
40
|
+
challenge_time: import("zod").ZodNumber;
|
|
41
|
+
}, "strict", import("zod").ZodTypeAny, {
|
|
42
|
+
challenge_time: number;
|
|
43
|
+
code_challenge: string;
|
|
44
|
+
code_challenge_method: "S256";
|
|
45
|
+
}, {
|
|
46
|
+
challenge_time: number;
|
|
47
|
+
code_challenge: string;
|
|
48
|
+
code_challenge_method: "S256";
|
|
49
|
+
}>;
|
|
50
|
+
static get max_age(): number;
|
|
51
|
+
static get codeChallengeMethod(): typeof code_challenge_method;
|
|
52
|
+
static isValidCodeVerifierFormat(maybe_code_verifier: unknown): maybe_code_verifier is CodeVerifierWithDetails;
|
|
53
|
+
static isValidCodeChallengeFormat(maybe_code_challenge: unknown): maybe_code_challenge is CodeChallengeWithDetails;
|
|
54
|
+
/**
|
|
55
|
+
*
|
|
56
|
+
* @name doesVerifierMatchChallenge
|
|
57
|
+
* @param input_code_verifier Frontend client sends code_verifier, to prove they created the initial code_challenge
|
|
58
|
+
* @param saved_code_challenge The code_challenge that was generated and associated with the user's authorization code
|
|
59
|
+
* @returns sha256_hash(input_code_verifier) === saved_code_challenge
|
|
60
|
+
*/
|
|
61
|
+
static doesVerifierMatchChallenge(opts: CheckWhetherVerifierMatchesChallengeInputOptions): Promise<boolean>;
|
|
62
|
+
}
|
|
63
|
+
export {};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { create_code_challenge, codeChallengeSchema, code_challenge_method, codeChallengeWithDetailsSchema, } from "./code_challenge";
|
|
2
|
+
import { create_code_verifier, codeVerifierSchema, MAX_PKCE_CODE_VERIFIER_AGE, codeVerifierWithDetailsSchema, } from "./code_verifier";
|
|
3
|
+
import { sha256_digest } from "../sha256_digest";
|
|
4
|
+
// Handles the creation of a PKCE code verifier and challenge
|
|
5
|
+
export class PKCE_ProofKeyManager {
|
|
6
|
+
code_verifier;
|
|
7
|
+
static createCodeVerifier(challenge_time) {
|
|
8
|
+
return create_code_verifier({ challenge_time });
|
|
9
|
+
}
|
|
10
|
+
static async createCodeChallenge(code_verifier) {
|
|
11
|
+
const createCodeChallengeOptions = {
|
|
12
|
+
code_verifier,
|
|
13
|
+
sha256_digest: sha256_digest,
|
|
14
|
+
};
|
|
15
|
+
const code_challenge = await create_code_challenge(createCodeChallengeOptions);
|
|
16
|
+
return code_challenge;
|
|
17
|
+
}
|
|
18
|
+
// Create a new PKCE_ProofKeyManager instance
|
|
19
|
+
// See PKCE_ProofKeyManager.createCodeVerifier to pre-generate a code_verifier
|
|
20
|
+
constructor(code_verifier) {
|
|
21
|
+
if (typeof code_verifier === "undefined") {
|
|
22
|
+
// If no code_verifier is provided, create a new one
|
|
23
|
+
this.code_verifier = PKCE_ProofKeyManager.createCodeVerifier(Date.now());
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
// If a code_verifier is provided, ensure it satisfies the CodeVerifier interface
|
|
27
|
+
code_verifier;
|
|
28
|
+
const verifier = code_verifier.code_verifier;
|
|
29
|
+
if (!verifier || typeof code_verifier.code_verifier !== "string") {
|
|
30
|
+
throw new Error("ProofKeyManager did not receive a code verifier to start PKCE flow!");
|
|
31
|
+
}
|
|
32
|
+
const challenge_time = code_verifier.challenge_time;
|
|
33
|
+
if (typeof challenge_time !== "number") {
|
|
34
|
+
throw new Error("Did not receive a 'challenge_time' associated with code verifier!");
|
|
35
|
+
}
|
|
36
|
+
this.code_verifier = {
|
|
37
|
+
...code_verifier,
|
|
38
|
+
code_verifier: verifier,
|
|
39
|
+
challenge_time,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
async getCodeChallenge() {
|
|
44
|
+
const code_verifier = this.code_verifier;
|
|
45
|
+
if (!code_verifier) {
|
|
46
|
+
throw new Error("Input code verifier not found within PKCE_ProofKeyManager!");
|
|
47
|
+
}
|
|
48
|
+
if (!code_verifier.code_verifier) {
|
|
49
|
+
throw new Error("Code verifier not found!");
|
|
50
|
+
}
|
|
51
|
+
if (typeof code_verifier.challenge_time !== "number") {
|
|
52
|
+
throw new Error("Code challenge time not found!");
|
|
53
|
+
}
|
|
54
|
+
const codeChallengeOptions = {
|
|
55
|
+
code_verifier: {
|
|
56
|
+
...code_verifier,
|
|
57
|
+
code_verifier: code_verifier.code_verifier,
|
|
58
|
+
challenge_time: code_verifier.challenge_time,
|
|
59
|
+
},
|
|
60
|
+
sha256_digest: sha256_digest,
|
|
61
|
+
};
|
|
62
|
+
return await create_code_challenge(codeChallengeOptions);
|
|
63
|
+
}
|
|
64
|
+
get challenge_time() {
|
|
65
|
+
if (!this.code_verifier.challenge_time) {
|
|
66
|
+
throw new Error("challenge_time not set");
|
|
67
|
+
}
|
|
68
|
+
if (typeof this.code_verifier.challenge_time !== "number") {
|
|
69
|
+
throw new Error("Invalid challenge_time");
|
|
70
|
+
}
|
|
71
|
+
return this.code_verifier.challenge_time;
|
|
72
|
+
}
|
|
73
|
+
get expiry_time() {
|
|
74
|
+
if (!this.code_verifier.expires_at) {
|
|
75
|
+
throw new Error("expires_at not set");
|
|
76
|
+
}
|
|
77
|
+
return this.code_verifier.expires_at;
|
|
78
|
+
}
|
|
79
|
+
static get codeVerifierSchema() {
|
|
80
|
+
return codeVerifierSchema;
|
|
81
|
+
}
|
|
82
|
+
static get codeVerifierWithDetailsSchema() {
|
|
83
|
+
return codeVerifierWithDetailsSchema;
|
|
84
|
+
}
|
|
85
|
+
static get codeChallengeSchema() {
|
|
86
|
+
return codeChallengeSchema;
|
|
87
|
+
}
|
|
88
|
+
static get codeChallengeWithOptionsSchema() {
|
|
89
|
+
return codeChallengeWithDetailsSchema;
|
|
90
|
+
}
|
|
91
|
+
static get max_age() {
|
|
92
|
+
return MAX_PKCE_CODE_VERIFIER_AGE;
|
|
93
|
+
}
|
|
94
|
+
static get codeChallengeMethod() {
|
|
95
|
+
return code_challenge_method;
|
|
96
|
+
}
|
|
97
|
+
static isValidCodeVerifierFormat(maybe_code_verifier) {
|
|
98
|
+
return PKCE_ProofKeyManager.codeVerifierWithDetailsSchema.safeParse(maybe_code_verifier).success;
|
|
99
|
+
}
|
|
100
|
+
static isValidCodeChallengeFormat(maybe_code_challenge) {
|
|
101
|
+
return this.codeChallengeWithOptionsSchema.safeParse(maybe_code_challenge)
|
|
102
|
+
.success;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
*
|
|
106
|
+
* @name doesVerifierMatchChallenge
|
|
107
|
+
* @param input_code_verifier Frontend client sends code_verifier, to prove they created the initial code_challenge
|
|
108
|
+
* @param saved_code_challenge The code_challenge that was generated and associated with the user's authorization code
|
|
109
|
+
* @returns sha256_hash(input_code_verifier) === saved_code_challenge
|
|
110
|
+
*/
|
|
111
|
+
static async doesVerifierMatchChallenge(opts) {
|
|
112
|
+
const { input_code_verifier, saved_code_challenge, challenge_time } = opts;
|
|
113
|
+
if (typeof input_code_verifier !== "string" || !input_code_verifier) {
|
|
114
|
+
throw new Error("Input code verifier is not a string");
|
|
115
|
+
}
|
|
116
|
+
const parsed_input_verifier = PKCE_ProofKeyManager.codeVerifierSchema.safeParse(input_code_verifier);
|
|
117
|
+
if (!parsed_input_verifier.success) {
|
|
118
|
+
console.error("Invalid input code verifier: ", parsed_input_verifier.error);
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
try {
|
|
122
|
+
// Put the input code verifier through the same process
|
|
123
|
+
// that (should have) created the initial code_challenge
|
|
124
|
+
const pkce_flow = new PKCE_ProofKeyManager({
|
|
125
|
+
code_verifier: input_code_verifier,
|
|
126
|
+
challenge_time,
|
|
127
|
+
});
|
|
128
|
+
const generated_challenge = await pkce_flow.getCodeChallenge();
|
|
129
|
+
const saved_challenge = {
|
|
130
|
+
code_challenge: saved_code_challenge,
|
|
131
|
+
code_challenge_method,
|
|
132
|
+
};
|
|
133
|
+
return (generated_challenge.code_challenge === saved_challenge.code_challenge);
|
|
134
|
+
}
|
|
135
|
+
catch (e) {
|
|
136
|
+
console.error(e);
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
//# sourceMappingURL=pkce.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pkce.js","sourceRoot":"","sources":["../../src/pkce/pkce.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,qBAAqB,EACrB,mBAAmB,EACnB,qBAAqB,EAGrB,8BAA8B,GAC/B,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAEL,oBAAoB,EACpB,kBAAkB,EAClB,0BAA0B,EAE1B,6BAA6B,GAC9B,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAQhD,6DAA6D;AAC7D,MAAM,OAAO,oBAAoB;IACvB,aAAa,CAGnB;IAEK,MAAM,CAAC,kBAAkB,CAC9B,cAAuB;QAEvB,OAAO,oBAAoB,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;IAClD,CAAC;IAEM,MAAM,CAAC,KAAK,CAAC,mBAAmB,CACrC,aAAsC;QAEtC,MAAM,0BAA0B,GAAoC;YAClE,aAAa;YACb,aAAa,EAAE,aAAa;SAC7B,CAAC;QACF,MAAM,cAAc,GAClB,MAAM,qBAAqB,CAAC,0BAA0B,CAAC,CAAC;QAC1D,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,6CAA6C;IAC7C,8EAA8E;IAC9E,YACE,aAGC;QAED,IAAI,OAAO,aAAa,KAAK,WAAW,EAAE,CAAC;YACzC,oDAAoD;YACpD,IAAI,CAAC,aAAa,GAAG,oBAAoB,CAAC,kBAAkB,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3E,CAAC;aAAM,CAAC;YACN,iFAAiF;YACjF,aAA8B,CAAC;YAE/B,MAAM,QAAQ,GAA6B,aAAa,CAAC,aAAa,CAAC;YACvE,IAAI,CAAC,QAAQ,IAAI,OAAO,aAAa,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;gBACjE,MAAM,IAAI,KAAK,CACb,qEAAqE,CACtE,CAAC;YACJ,CAAC;YAED,MAAM,cAAc,GAAG,aAAa,CAAC,cAAc,CAAC;YACpD,IAAI,OAAO,cAAc,KAAK,QAAQ,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CACb,mEAAmE,CACpE,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,aAAa,GAAG;gBACnB,GAAG,aAAa;gBAChB,aAAa,EAAE,QAAQ;gBACvB,cAAc;aACf,CAAC;QACJ,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,gBAAgB;QAC3B,MAAM,aAAa,GACjB,IAAI,CAAC,aAAa,CAAC;QACrB,IAAI,CAAC,aAAa,EAAE,CAAC;YACnB,MAAM,IAAI,KAAK,CACb,4DAA4D,CAC7D,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,aAAa,CAAC,aAAa,EAAE,CAAC;YACjC,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;QAC9C,CAAC;QACD,IAAI,OAAO,aAAa,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;QACpD,CAAC;QACD,MAAM,oBAAoB,GAAoC;YAC5D,aAAa,EAAE;gBACb,GAAG,aAAa;gBAChB,aAAa,EAAE,aAAa,CAAC,aAAa;gBAC1C,cAAc,EAAE,aAAa,CAAC,cAAc;aAC7C;YACD,aAAa,EAAE,aAAa;SAC7B,CAAC;QACF,OAAO,MAAM,qBAAqB,CAAC,oBAAoB,CAAC,CAAC;IAC3D,CAAC;IAED,IAAW,cAAc;QACvB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE,CAAC;YACvC,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QACD,IAAI,OAAO,IAAI,CAAC,aAAa,CAAC,cAAc,KAAK,QAAQ,EAAE,CAAC;YAC1D,MAAM,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,IAAI,CAAC,aAAa,CAAC,cAAc,CAAC;IAC3C,CAAC;IAED,IAAW,WAAW;QACpB,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC;QACxC,CAAC;QACD,OAAO,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC;IACvC,CAAC;IAEM,MAAM,KAAK,kBAAkB;QAClC,OAAO,kBAAkB,CAAC;IAC5B,CAAC;IAEM,MAAM,KAAK,6BAA6B;QAC7C,OAAO,6BAA6B,CAAC;IACvC,CAAC;IAEM,MAAM,KAAK,mBAAmB;QACnC,OAAO,mBAAmB,CAAC;IAC7B,CAAC;IAEM,MAAM,KAAK,8BAA8B;QAC9C,OAAO,8BAA8B,CAAC;IACxC,CAAC;IAEM,MAAM,KAAK,OAAO;QACvB,OAAO,0BAA0B,CAAC;IACpC,CAAC;IAEM,MAAM,KAAK,mBAAmB;QACnC,OAAO,qBAAqB,CAAC;IAC/B,CAAC;IAEM,MAAM,CAAC,yBAAyB,CACrC,mBAA4B;QAE5B,OAAO,oBAAoB,CAAC,6BAA6B,CAAC,SAAS,CACjE,mBAAmB,CACpB,CAAC,OAAO,CAAC;IACZ,CAAC;IAEM,MAAM,CAAC,0BAA0B,CACtC,oBAA6B;QAE7B,OAAO,IAAI,CAAC,8BAA8B,CAAC,SAAS,CAAC,oBAAoB,CAAC;aACvE,OAAO,CAAC;IACb,CAAC;IAED;;;;;;OAMG;IACI,MAAM,CAAC,KAAK,CAAC,0BAA0B,CAC5C,IAAsD;QAEtD,MAAM,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC;QAE3E,IAAI,OAAO,mBAAmB,KAAK,QAAQ,IAAI,CAAC,mBAAmB,EAAE,CAAC;YACpE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;QACzD,CAAC;QAED,MAAM,qBAAqB,GACzB,oBAAoB,CAAC,kBAAkB,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;QACzE,IAAI,CAAC,qBAAqB,CAAC,OAAO,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CACX,+BAA+B,EAC/B,qBAAqB,CAAC,KAAK,CAC5B,CAAC;YACF,OAAO,KAAK,CAAC;QACf,CAAC;QAED,IAAI,CAAC;YACH,uDAAuD;YACvD,wDAAwD;YACxD,MAAM,SAAS,GAAG,IAAI,oBAAoB,CAAC;gBACzC,aAAa,EAAE,mBAAmB;gBAClC,cAAc;aACf,CAAC,CAAC;YAEH,MAAM,mBAAmB,GACvB,MAAM,SAAS,CAAC,gBAAgB,EAAE,CAAC;YAErC,MAAM,eAAe,GAAsC;gBACzD,cAAc,EAAE,oBAAoB;gBACpC,qBAAqB;aACtB,CAAC;YAEF,OAAO,CACL,mBAAmB,CAAC,cAAc,KAAK,eAAe,CAAC,cAAc,CACtE,CAAC;QACJ,CAAC;QAAC,OAAO,CAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACjB,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { sha256_digest, sha256_digest as default } from "./sha256_digest";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/pkce/sha256_digest/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,aAAa,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import sha256Digest from "crypto-js/sha256";
|
|
2
|
+
import base64Stringify from "crypto-js/enc-base64";
|
|
3
|
+
export const digest_algorithm = "SHA-256";
|
|
4
|
+
export async function sha256_digest(code_verifier) {
|
|
5
|
+
let sha256;
|
|
6
|
+
try {
|
|
7
|
+
sha256 = async (code_verifier) => {
|
|
8
|
+
const sha_digest = base64Stringify.stringify(sha256Digest(code_verifier));
|
|
9
|
+
if (typeof sha_digest !== "string") {
|
|
10
|
+
throw new Error("Expected final output of sha256 digest in insecure context to be a string");
|
|
11
|
+
}
|
|
12
|
+
return sha_digest;
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
console.error("Failed to load sha256 hash function: ", e);
|
|
17
|
+
throw new Error("Failed to load sha256 hash function");
|
|
18
|
+
}
|
|
19
|
+
if (typeof sha256 !== "function" && typeof sha256 !== "object") {
|
|
20
|
+
throw new Error("Failed to import sha256 library to use inplace of crypto.subtle.digest in insecure HTTP context");
|
|
21
|
+
}
|
|
22
|
+
const output = await sha256(code_verifier);
|
|
23
|
+
if (typeof output !== "string") {
|
|
24
|
+
throw new TypeError("Expected output to be a string!");
|
|
25
|
+
}
|
|
26
|
+
// url_encode
|
|
27
|
+
return output.replace(/[^A-Za-z0-9_-]/g, "_");
|
|
28
|
+
}
|
|
29
|
+
export default sha256_digest;
|
|
30
|
+
//# sourceMappingURL=sha256_digest.js.map
|