@better-auth/core 1.7.0-beta.3 → 1.7.0-beta.5
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/api/index.d.mts +3 -3
- package/dist/context/global.mjs +1 -1
- package/dist/db/adapter/factory.mjs +62 -0
- package/dist/db/adapter/index.d.mts +35 -1
- package/dist/db/adapter/types.d.mts +1 -1
- package/dist/db/get-tables.mjs +3 -3
- package/dist/db/schema/account.d.mts +1 -1
- package/dist/db/schema/account.mjs +1 -1
- package/dist/db/type.d.mts +12 -0
- package/dist/env/env-impl.mjs +1 -1
- package/dist/error/codes.d.mts +6 -0
- package/dist/error/codes.mjs +6 -0
- package/dist/index.d.mts +2 -2
- package/dist/instrumentation/tracer.mjs +1 -1
- package/dist/oauth2/authorization-params.d.mts +12 -0
- package/dist/oauth2/authorization-params.mjs +12 -0
- package/dist/oauth2/basic-credentials.d.mts +30 -0
- package/dist/oauth2/basic-credentials.mjs +64 -0
- package/dist/oauth2/client-assertion.d.mts +38 -22
- package/dist/oauth2/client-assertion.mjs +63 -28
- package/dist/oauth2/client-credentials-token.d.mts +19 -40
- package/dist/oauth2/client-credentials-token.mjs +18 -29
- package/dist/oauth2/create-authorization-url.d.mts +13 -2
- package/dist/oauth2/create-authorization-url.mjs +28 -7
- package/dist/oauth2/index.d.mts +13 -8
- package/dist/oauth2/index.mjs +11 -7
- package/dist/oauth2/oauth-provider.d.mts +149 -11
- package/dist/oauth2/refresh-access-token.d.mts +20 -40
- package/dist/oauth2/refresh-access-token.mjs +20 -33
- package/dist/oauth2/scopes.d.mts +76 -0
- package/dist/oauth2/scopes.mjs +96 -0
- package/dist/oauth2/token-endpoint-auth.d.mts +17 -0
- package/dist/oauth2/token-endpoint-auth.mjs +89 -0
- package/dist/oauth2/utils.d.mts +9 -1
- package/dist/oauth2/utils.mjs +14 -2
- package/dist/oauth2/validate-authorization-code.d.mts +17 -52
- package/dist/oauth2/validate-authorization-code.mjs +17 -30
- package/dist/oauth2/verify-id-token.d.mts +26 -0
- package/dist/oauth2/verify-id-token.mjs +62 -0
- package/dist/oauth2/verify.d.mts +14 -0
- package/dist/oauth2/verify.mjs +38 -12
- package/dist/social-providers/apple.d.mts +18 -20
- package/dist/social-providers/apple.mjs +15 -28
- package/dist/social-providers/atlassian.d.mts +8 -2
- package/dist/social-providers/atlassian.mjs +9 -6
- package/dist/social-providers/cognito.d.mts +29 -3
- package/dist/social-providers/cognito.mjs +30 -34
- package/dist/social-providers/discord.d.mts +8 -2
- package/dist/social-providers/discord.mjs +20 -6
- package/dist/social-providers/dropbox.d.mts +8 -2
- package/dist/social-providers/dropbox.mjs +10 -9
- package/dist/social-providers/facebook.d.mts +24 -3
- package/dist/social-providers/facebook.mjs +51 -24
- package/dist/social-providers/figma.d.mts +8 -2
- package/dist/social-providers/figma.mjs +8 -7
- package/dist/social-providers/github.d.mts +8 -2
- package/dist/social-providers/github.mjs +9 -8
- package/dist/social-providers/gitlab.d.mts +8 -2
- package/dist/social-providers/gitlab.mjs +8 -7
- package/dist/social-providers/google.d.mts +32 -4
- package/dist/social-providers/google.mjs +26 -29
- package/dist/social-providers/huggingface.d.mts +8 -2
- package/dist/social-providers/huggingface.mjs +11 -10
- package/dist/social-providers/index.d.mts +322 -75
- package/dist/social-providers/kakao.d.mts +8 -2
- package/dist/social-providers/kakao.mjs +11 -10
- package/dist/social-providers/kick.d.mts +8 -2
- package/dist/social-providers/kick.mjs +7 -6
- package/dist/social-providers/line.d.mts +11 -3
- package/dist/social-providers/line.mjs +14 -15
- package/dist/social-providers/linear.d.mts +8 -2
- package/dist/social-providers/linear.mjs +7 -6
- package/dist/social-providers/linkedin.d.mts +8 -2
- package/dist/social-providers/linkedin.mjs +12 -11
- package/dist/social-providers/microsoft-entra-id.d.mts +33 -7
- package/dist/social-providers/microsoft-entra-id.mjs +28 -38
- package/dist/social-providers/naver.d.mts +8 -2
- package/dist/social-providers/naver.mjs +7 -6
- package/dist/social-providers/notion.d.mts +8 -2
- package/dist/social-providers/notion.mjs +9 -6
- package/dist/social-providers/paybin.d.mts +8 -2
- package/dist/social-providers/paybin.mjs +12 -11
- package/dist/social-providers/paypal.d.mts +8 -3
- package/dist/social-providers/paypal.mjs +10 -14
- package/dist/social-providers/polar.d.mts +8 -2
- package/dist/social-providers/polar.mjs +11 -10
- package/dist/social-providers/railway.d.mts +8 -2
- package/dist/social-providers/railway.mjs +11 -10
- package/dist/social-providers/reddit.d.mts +8 -2
- package/dist/social-providers/reddit.mjs +11 -9
- package/dist/social-providers/roblox.d.mts +8 -2
- package/dist/social-providers/roblox.mjs +15 -5
- package/dist/social-providers/salesforce.d.mts +8 -2
- package/dist/social-providers/salesforce.mjs +11 -10
- package/dist/social-providers/slack.d.mts +8 -2
- package/dist/social-providers/slack.mjs +18 -15
- package/dist/social-providers/spotify.d.mts +8 -2
- package/dist/social-providers/spotify.mjs +7 -6
- package/dist/social-providers/tiktok.d.mts +8 -2
- package/dist/social-providers/tiktok.mjs +21 -5
- package/dist/social-providers/twitch.d.mts +8 -2
- package/dist/social-providers/twitch.mjs +7 -6
- package/dist/social-providers/twitter.d.mts +7 -2
- package/dist/social-providers/twitter.mjs +11 -10
- package/dist/social-providers/vercel.d.mts +8 -2
- package/dist/social-providers/vercel.mjs +7 -9
- package/dist/social-providers/vk.d.mts +8 -2
- package/dist/social-providers/vk.mjs +7 -6
- package/dist/social-providers/wechat.d.mts +8 -2
- package/dist/social-providers/wechat.mjs +16 -6
- package/dist/social-providers/zoom.d.mts +10 -3
- package/dist/social-providers/zoom.mjs +14 -15
- package/dist/types/context.d.mts +33 -11
- package/dist/types/index.d.mts +1 -1
- package/dist/types/init-options.d.mts +121 -6
- package/dist/utils/ip.d.mts +5 -4
- package/dist/utils/ip.mjs +3 -3
- package/dist/utils/redirect-uri.d.mts +20 -0
- package/dist/utils/redirect-uri.mjs +48 -0
- package/dist/utils/string.d.mts +5 -1
- package/dist/utils/string.mjs +20 -1
- package/dist/utils/url.d.mts +18 -1
- package/dist/utils/url.mjs +30 -1
- package/package.json +13 -12
- package/src/db/adapter/factory.ts +126 -0
- package/src/db/adapter/index.ts +32 -0
- package/src/db/adapter/types.ts +1 -0
- package/src/db/get-tables.ts +8 -3
- package/src/db/schema/account.ts +14 -2
- package/src/db/type.ts +12 -0
- package/src/env/env-impl.ts +1 -2
- package/src/error/codes.ts +6 -0
- package/src/oauth2/authorization-params.ts +28 -0
- package/src/oauth2/basic-credentials.ts +87 -0
- package/src/oauth2/client-assertion.ts +131 -58
- package/src/oauth2/client-credentials-token.ts +48 -72
- package/src/oauth2/create-authorization-url.ts +30 -8
- package/src/oauth2/index.ts +42 -10
- package/src/oauth2/oauth-provider.ts +161 -12
- package/src/oauth2/refresh-access-token.ts +52 -78
- package/src/oauth2/scopes.ts +118 -0
- package/src/oauth2/token-endpoint-auth.ts +221 -0
- package/src/oauth2/utils.ts +21 -5
- package/src/oauth2/validate-authorization-code.ts +55 -85
- package/src/oauth2/verify-id-token.ts +111 -0
- package/src/oauth2/verify.ts +82 -15
- package/src/social-providers/apple.ts +32 -45
- package/src/social-providers/atlassian.ts +20 -9
- package/src/social-providers/cognito.ts +51 -48
- package/src/social-providers/discord.ts +37 -22
- package/src/social-providers/dropbox.ts +20 -12
- package/src/social-providers/facebook.ts +108 -57
- package/src/social-providers/figma.ts +21 -10
- package/src/social-providers/github.ts +16 -10
- package/src/social-providers/gitlab.ts +16 -8
- package/src/social-providers/google.ts +67 -46
- package/src/social-providers/huggingface.ts +20 -9
- package/src/social-providers/kakao.ts +18 -9
- package/src/social-providers/kick.ts +20 -8
- package/src/social-providers/line.ts +39 -37
- package/src/social-providers/linear.ts +20 -7
- package/src/social-providers/linkedin.ts +16 -10
- package/src/social-providers/microsoft-entra-id.ts +66 -64
- package/src/social-providers/naver.ts +14 -7
- package/src/social-providers/notion.ts +20 -7
- package/src/social-providers/paybin.ts +16 -11
- package/src/social-providers/paypal.ts +12 -25
- package/src/social-providers/polar.ts +20 -9
- package/src/social-providers/railway.ts +20 -9
- package/src/social-providers/reddit.ts +22 -10
- package/src/social-providers/roblox.ts +31 -15
- package/src/social-providers/salesforce.ts +21 -10
- package/src/social-providers/slack.ts +31 -16
- package/src/social-providers/spotify.ts +20 -7
- package/src/social-providers/tiktok.ts +32 -13
- package/src/social-providers/twitch.ts +14 -9
- package/src/social-providers/twitter.ts +18 -8
- package/src/social-providers/vercel.ts +24 -11
- package/src/social-providers/vk.ts +20 -7
- package/src/social-providers/wechat.ts +28 -8
- package/src/social-providers/zoom.ts +28 -19
- package/src/types/context.ts +33 -12
- package/src/types/index.ts +7 -0
- package/src/types/init-options.ts +148 -5
- package/src/utils/ip.ts +12 -13
- package/src/utils/redirect-uri.ts +54 -0
- package/src/utils/string.ts +37 -0
- package/src/utils/url.ts +28 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { SignJWT, importJWK, importPKCS8 } from "jose";
|
|
2
2
|
//#region src/oauth2/client-assertion.ts
|
|
3
3
|
/** Asymmetric signing algorithms compatible with private_key_jwt (RFC 7523). */
|
|
4
|
-
const
|
|
4
|
+
const PRIVATE_KEY_JWT_SIGNING_ALGORITHMS = [
|
|
5
5
|
"RS256",
|
|
6
6
|
"RS384",
|
|
7
7
|
"RS512",
|
|
@@ -13,20 +13,46 @@ const ASSERTION_SIGNING_ALGORITHMS = [
|
|
|
13
13
|
"ES512",
|
|
14
14
|
"EdDSA"
|
|
15
15
|
];
|
|
16
|
+
function assertSupportedPrivateKeyJwtAlgorithm(candidate) {
|
|
17
|
+
if (!PRIVATE_KEY_JWT_SIGNING_ALGORITHMS.includes(candidate)) throw new Error(`Unsupported private_key_jwt signing algorithm: ${candidate}. Use one of ${PRIVATE_KEY_JWT_SIGNING_ALGORITHMS.join(", ")}.`);
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Validates `private_key_jwt` options eagerly and returns the algorithm to
|
|
21
|
+
* use for signing.
|
|
22
|
+
*
|
|
23
|
+
* Asserts that key material is configured, that any explicit `algorithm` is
|
|
24
|
+
* supported, that any JWK-embedded `alg` is supported, and that the two
|
|
25
|
+
* agree when both are set.
|
|
26
|
+
*/
|
|
27
|
+
function resolveValidPrivateKeyJwtOptions(options) {
|
|
28
|
+
if (!options.privateKeyJwk && !options.privateKeyPem) throw new Error("private_key_jwt requires either privateKeyJwk or privateKeyPem");
|
|
29
|
+
if (options.algorithm) assertSupportedPrivateKeyJwtAlgorithm(options.algorithm);
|
|
30
|
+
const jwkAlg = options.privateKeyJwk?.alg;
|
|
31
|
+
if (typeof jwkAlg === "string") assertSupportedPrivateKeyJwtAlgorithm(jwkAlg);
|
|
32
|
+
if (options.algorithm && typeof jwkAlg === "string" && options.algorithm !== jwkAlg) throw new Error(`JWK alg "${jwkAlg}" does not match configured algorithm "${options.algorithm}". Remove the JWK alg field, or pass an algorithm that matches the JWK.`);
|
|
33
|
+
return options.algorithm ?? (typeof jwkAlg === "string" ? jwkAlg : "RS256");
|
|
34
|
+
}
|
|
16
35
|
const CLIENT_ASSERTION_TYPE = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer";
|
|
17
36
|
/**
|
|
18
37
|
* Signs an RFC 7523 client assertion JWT for `private_key_jwt` authentication.
|
|
19
38
|
*
|
|
20
|
-
* The JWT contains
|
|
21
|
-
*
|
|
39
|
+
* The JWT contains these claims:
|
|
40
|
+
*
|
|
41
|
+
* - iss=clientId
|
|
42
|
+
* - sub=clientId
|
|
43
|
+
* - aud=tokenEndpoint
|
|
44
|
+
* - exp=now + 120s
|
|
45
|
+
* - jti=unique
|
|
46
|
+
* - iat=now
|
|
22
47
|
*/
|
|
23
|
-
async function
|
|
48
|
+
async function signPrivateKeyJwtClientAssertion({ clientId, tokenEndpoint, privateKeyJwk, privateKeyPem, kid, algorithm, expiresIn = 120 }) {
|
|
49
|
+
const resolvedAlg = resolveValidPrivateKeyJwtOptions({
|
|
50
|
+
privateKeyJwk,
|
|
51
|
+
privateKeyPem,
|
|
52
|
+
algorithm
|
|
53
|
+
});
|
|
24
54
|
const resolvedKid = kid ?? privateKeyJwk?.kid;
|
|
25
|
-
const
|
|
26
|
-
let key;
|
|
27
|
-
if (privateKeyJwk) key = await importJWK(privateKeyJwk, resolvedAlg);
|
|
28
|
-
else if (privateKeyPem) key = await importPKCS8(privateKeyPem, resolvedAlg);
|
|
29
|
-
else throw new Error("private_key_jwt requires either privateKeyJwk or privateKeyPem");
|
|
55
|
+
const key = privateKeyJwk ? await importJWK(privateKeyJwk, resolvedAlg) : await importPKCS8(privateKeyPem, resolvedAlg);
|
|
30
56
|
const now = Math.floor(Date.now() / 1e3);
|
|
31
57
|
const jti = crypto.randomUUID();
|
|
32
58
|
const header = {
|
|
@@ -37,28 +63,37 @@ async function signClientAssertion({ clientId, tokenEndpoint, privateKeyJwk, pri
|
|
|
37
63
|
return new SignJWT({}).setProtectedHeader(header).setIssuer(clientId).setSubject(clientId).setAudience(tokenEndpoint).setIssuedAt(now).setExpirationTime(now + expiresIn).setJti(jti).sign(key);
|
|
38
64
|
}
|
|
39
65
|
/**
|
|
40
|
-
*
|
|
41
|
-
*
|
|
66
|
+
* Creates a client assertion getter for `private_key_jwt` authentication.
|
|
67
|
+
*
|
|
68
|
+
* Validates options eagerly (key material, supported algorithm, JWK alg
|
|
69
|
+
* agreement) so misconfiguration surfaces at construction rather than on the
|
|
70
|
+
* first token request. The returned function signs a fresh RFC 7523 JWT
|
|
71
|
+
* assertion for every token endpoint request.
|
|
72
|
+
*/
|
|
73
|
+
function createPrivateKeyJwtClientAssertionGetter(options) {
|
|
74
|
+
resolveValidPrivateKeyJwtOptions({
|
|
75
|
+
privateKeyJwk: options.privateKeyJwk,
|
|
76
|
+
privateKeyPem: options.privateKeyPem,
|
|
77
|
+
algorithm: options.algorithm
|
|
78
|
+
});
|
|
79
|
+
return ({ clientId, tokenEndpoint }) => signPrivateKeyJwtClientAssertion({
|
|
80
|
+
clientId,
|
|
81
|
+
tokenEndpoint,
|
|
82
|
+
privateKeyJwk: options.privateKeyJwk,
|
|
83
|
+
privateKeyPem: options.privateKeyPem,
|
|
84
|
+
kid: options.kid,
|
|
85
|
+
algorithm: options.algorithm,
|
|
86
|
+
expiresIn: options.expiresIn
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Resolves a client assertion getter into `client_assertion` + `client_assertion_type` params for injection into a token request body.
|
|
42
91
|
*/
|
|
43
|
-
async function
|
|
44
|
-
let assertion = clientAssertion.assertion;
|
|
45
|
-
if (!assertion) {
|
|
46
|
-
const audEndpoint = tokenEndpoint ?? clientAssertion.tokenEndpoint;
|
|
47
|
-
if (!audEndpoint) throw new Error("private_key_jwt requires a tokenEndpoint for the JWT audience claim");
|
|
48
|
-
assertion = await signClientAssertion({
|
|
49
|
-
clientId,
|
|
50
|
-
tokenEndpoint: audEndpoint,
|
|
51
|
-
privateKeyJwk: clientAssertion.privateKeyJwk,
|
|
52
|
-
privateKeyPem: clientAssertion.privateKeyPem,
|
|
53
|
-
kid: clientAssertion.kid,
|
|
54
|
-
algorithm: clientAssertion.algorithm,
|
|
55
|
-
expiresIn: clientAssertion.expiresIn
|
|
56
|
-
});
|
|
57
|
-
}
|
|
92
|
+
async function resolveClientAssertionParams({ getClientAssertion, context }) {
|
|
58
93
|
return {
|
|
59
|
-
client_assertion:
|
|
94
|
+
client_assertion: await getClientAssertion(context),
|
|
60
95
|
client_assertion_type: CLIENT_ASSERTION_TYPE
|
|
61
96
|
};
|
|
62
97
|
}
|
|
63
98
|
//#endregion
|
|
64
|
-
export {
|
|
99
|
+
export { CLIENT_ASSERTION_TYPE, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, createPrivateKeyJwtClientAssertionGetter, resolveClientAssertionParams, signPrivateKeyJwtClientAssertion };
|
|
@@ -1,59 +1,38 @@
|
|
|
1
|
-
import { ClientAssertionConfig } from "./client-assertion.mjs";
|
|
2
1
|
import { AwaitableFunction } from "../types/helper.mjs";
|
|
3
2
|
import { OAuth2Tokens, ProviderOptions } from "./oauth-provider.mjs";
|
|
3
|
+
import { TokenEndpointAuth, TokenEndpointSecretAuthentication } from "./token-endpoint-auth.mjs";
|
|
4
4
|
|
|
5
5
|
//#region src/oauth2/client-credentials-token.d.ts
|
|
6
|
-
|
|
7
|
-
options,
|
|
8
|
-
scope,
|
|
9
|
-
authentication,
|
|
10
|
-
clientAssertion,
|
|
11
|
-
tokenEndpoint,
|
|
12
|
-
resource
|
|
13
|
-
}: {
|
|
6
|
+
interface ClientCredentialsTokenRequestInput {
|
|
14
7
|
options: AwaitableFunction<ProviderOptions>;
|
|
15
8
|
scope?: string | undefined;
|
|
16
|
-
authentication?:
|
|
17
|
-
|
|
9
|
+
authentication?: TokenEndpointSecretAuthentication | undefined;
|
|
10
|
+
tokenEndpointAuth?: TokenEndpointAuth | undefined;
|
|
18
11
|
tokenEndpoint?: string | undefined;
|
|
19
12
|
resource?: (string | string[]) | undefined;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
*/
|
|
27
|
-
declare function createClientCredentialsTokenRequest({
|
|
13
|
+
}
|
|
14
|
+
interface ClientCredentialsTokenInput extends ClientCredentialsTokenRequestInput {
|
|
15
|
+
tokenEndpoint: string;
|
|
16
|
+
scope: string;
|
|
17
|
+
}
|
|
18
|
+
declare function clientCredentialsTokenRequest({
|
|
28
19
|
options,
|
|
29
20
|
scope,
|
|
30
21
|
authentication,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
scope?: string | undefined;
|
|
36
|
-
authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
|
|
37
|
-
resource?: (string | string[]) | undefined;
|
|
38
|
-
extraParams?: Record<string, string> | undefined;
|
|
39
|
-
}): {
|
|
22
|
+
tokenEndpointAuth,
|
|
23
|
+
tokenEndpoint,
|
|
24
|
+
resource
|
|
25
|
+
}: ClientCredentialsTokenRequestInput): Promise<{
|
|
40
26
|
body: URLSearchParams;
|
|
41
|
-
headers: Record<string,
|
|
42
|
-
}
|
|
27
|
+
headers: Record<string, string>;
|
|
28
|
+
}>;
|
|
43
29
|
declare function clientCredentialsToken({
|
|
44
30
|
options,
|
|
45
31
|
tokenEndpoint,
|
|
46
32
|
scope,
|
|
47
33
|
authentication,
|
|
48
|
-
|
|
34
|
+
tokenEndpointAuth,
|
|
49
35
|
resource
|
|
50
|
-
}:
|
|
51
|
-
options: AwaitableFunction<ProviderOptions>;
|
|
52
|
-
tokenEndpoint: string;
|
|
53
|
-
scope: string;
|
|
54
|
-
authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
|
|
55
|
-
clientAssertion?: ClientAssertionConfig | undefined;
|
|
56
|
-
resource?: (string | string[]) | undefined;
|
|
57
|
-
}): Promise<OAuth2Tokens>;
|
|
36
|
+
}: ClientCredentialsTokenInput): Promise<OAuth2Tokens>;
|
|
58
37
|
//#endregion
|
|
59
|
-
export { clientCredentialsToken, clientCredentialsTokenRequest
|
|
38
|
+
export { clientCredentialsToken, clientCredentialsTokenRequest };
|
|
@@ -1,30 +1,25 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { base64 } from "@better-auth/utils/base64";
|
|
1
|
+
import { applyTokenEndpointAuth } from "./token-endpoint-auth.mjs";
|
|
3
2
|
import { betterFetch } from "@better-fetch/fetch";
|
|
4
3
|
//#region src/oauth2/client-credentials-token.ts
|
|
5
|
-
async function clientCredentialsTokenRequest({ options, scope, authentication,
|
|
4
|
+
async function clientCredentialsTokenRequest({ options, scope, authentication, tokenEndpointAuth, tokenEndpoint, resource }) {
|
|
6
5
|
options = typeof options === "function" ? await options() : options;
|
|
7
|
-
|
|
8
|
-
if (authentication === "private_key_jwt") {
|
|
9
|
-
if (!clientAssertion) throw new Error("private_key_jwt authentication requires a clientAssertion configuration");
|
|
10
|
-
extraParams = await resolveAssertionParams({
|
|
11
|
-
clientAssertion,
|
|
12
|
-
clientId: Array.isArray(options.clientId) ? options.clientId[0] : options.clientId,
|
|
13
|
-
tokenEndpoint
|
|
14
|
-
});
|
|
15
|
-
}
|
|
16
|
-
return createClientCredentialsTokenRequest({
|
|
6
|
+
const request = buildClientCredentialsTokenRequest({
|
|
17
7
|
options,
|
|
18
8
|
scope,
|
|
19
|
-
|
|
20
|
-
resource,
|
|
21
|
-
extraParams
|
|
9
|
+
resource
|
|
22
10
|
});
|
|
11
|
+
await applyTokenEndpointAuth({
|
|
12
|
+
body: request.body,
|
|
13
|
+
headers: request.headers,
|
|
14
|
+
options,
|
|
15
|
+
tokenEndpoint: tokenEndpoint ?? "",
|
|
16
|
+
grantType: "client_credentials",
|
|
17
|
+
tokenEndpointAuth,
|
|
18
|
+
authentication
|
|
19
|
+
});
|
|
20
|
+
return request;
|
|
23
21
|
}
|
|
24
|
-
|
|
25
|
-
* @deprecated use async'd clientCredentialsTokenRequest instead
|
|
26
|
-
*/
|
|
27
|
-
function createClientCredentialsTokenRequest({ options, scope, authentication, resource, extraParams }) {
|
|
22
|
+
function buildClientCredentialsTokenRequest({ options, scope, resource, extraParams }) {
|
|
28
23
|
const body = new URLSearchParams();
|
|
29
24
|
const headers = {
|
|
30
25
|
"content-type": "application/x-www-form-urlencoded",
|
|
@@ -34,12 +29,6 @@ function createClientCredentialsTokenRequest({ options, scope, authentication, r
|
|
|
34
29
|
scope && body.set("scope", scope);
|
|
35
30
|
if (resource) if (typeof resource === "string") body.append("resource", resource);
|
|
36
31
|
else for (const _resource of resource) body.append("resource", _resource);
|
|
37
|
-
const primaryClientId = Array.isArray(options.clientId) ? options.clientId[0] : options.clientId;
|
|
38
|
-
if (authentication === "basic") headers["authorization"] = `Basic ${base64.encode(`${primaryClientId}:${options.clientSecret ?? ""}`)}`;
|
|
39
|
-
else {
|
|
40
|
-
body.set("client_id", primaryClientId);
|
|
41
|
-
if (authentication !== "private_key_jwt" && options.clientSecret) body.set("client_secret", options.clientSecret);
|
|
42
|
-
}
|
|
43
32
|
if (extraParams) {
|
|
44
33
|
for (const [key, value] of Object.entries(extraParams)) if (!body.has(key)) body.append(key, value);
|
|
45
34
|
}
|
|
@@ -48,12 +37,12 @@ function createClientCredentialsTokenRequest({ options, scope, authentication, r
|
|
|
48
37
|
headers
|
|
49
38
|
};
|
|
50
39
|
}
|
|
51
|
-
async function clientCredentialsToken({ options, tokenEndpoint, scope, authentication,
|
|
40
|
+
async function clientCredentialsToken({ options, tokenEndpoint, scope, authentication, tokenEndpointAuth, resource }) {
|
|
52
41
|
const { body, headers } = await clientCredentialsTokenRequest({
|
|
53
42
|
options,
|
|
54
43
|
scope,
|
|
55
44
|
authentication,
|
|
56
|
-
|
|
45
|
+
tokenEndpointAuth,
|
|
57
46
|
tokenEndpoint,
|
|
58
47
|
resource
|
|
59
48
|
});
|
|
@@ -75,4 +64,4 @@ async function clientCredentialsToken({ options, tokenEndpoint, scope, authentic
|
|
|
75
64
|
return tokens;
|
|
76
65
|
}
|
|
77
66
|
//#endregion
|
|
78
|
-
export { clientCredentialsToken, clientCredentialsTokenRequest
|
|
67
|
+
export { clientCredentialsToken, clientCredentialsTokenRequest };
|
|
@@ -1,6 +1,14 @@
|
|
|
1
1
|
import { AwaitableFunction } from "../types/helper.mjs";
|
|
2
2
|
import { ProviderOptions } from "./oauth-provider.mjs";
|
|
3
3
|
//#region src/oauth2/create-authorization-url.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Query-parameter names that are populated by the framework as part of the
|
|
6
|
+
* authorization request and must not be overridden by caller-supplied
|
|
7
|
+
* `additionalParams`. Overriding `state`, PKCE, or `redirect_uri` would
|
|
8
|
+
* break the callback correlation and session pinning guarantees.
|
|
9
|
+
*/
|
|
10
|
+
declare const RESERVED_AUTHORIZATION_PARAMS: readonly ["state", "client_id", "redirect_uri", "response_type", "code_challenge", "code_challenge_method", "scope"];
|
|
11
|
+
declare const RESERVED_AUTHORIZATION_PARAMS_SET: ReadonlySet<string>;
|
|
4
12
|
declare function createAuthorizationURL({
|
|
5
13
|
id,
|
|
6
14
|
options,
|
|
@@ -39,6 +47,9 @@ declare function createAuthorizationURL({
|
|
|
39
47
|
responseMode?: string | undefined;
|
|
40
48
|
additionalParams?: Record<string, string> | undefined;
|
|
41
49
|
scopeJoiner?: string | undefined;
|
|
42
|
-
}): Promise<
|
|
50
|
+
}): Promise<{
|
|
51
|
+
url: URL;
|
|
52
|
+
requestedScopes: string[];
|
|
53
|
+
}>;
|
|
43
54
|
//#endregion
|
|
44
|
-
export { createAuthorizationURL };
|
|
55
|
+
export { RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, createAuthorizationURL };
|
|
@@ -1,13 +1,30 @@
|
|
|
1
|
-
import { generateCodeChallenge } from "./utils.mjs";
|
|
1
|
+
import { generateCodeChallenge, getPrimaryClientId } from "./utils.mjs";
|
|
2
2
|
//#region src/oauth2/create-authorization-url.ts
|
|
3
|
+
/**
|
|
4
|
+
* Query-parameter names that are populated by the framework as part of the
|
|
5
|
+
* authorization request and must not be overridden by caller-supplied
|
|
6
|
+
* `additionalParams`. Overriding `state`, PKCE, or `redirect_uri` would
|
|
7
|
+
* break the callback correlation and session pinning guarantees.
|
|
8
|
+
*/
|
|
9
|
+
const RESERVED_AUTHORIZATION_PARAMS = [
|
|
10
|
+
"state",
|
|
11
|
+
"client_id",
|
|
12
|
+
"redirect_uri",
|
|
13
|
+
"response_type",
|
|
14
|
+
"code_challenge",
|
|
15
|
+
"code_challenge_method",
|
|
16
|
+
"scope"
|
|
17
|
+
];
|
|
18
|
+
const RESERVED_AUTHORIZATION_PARAMS_SET = new Set(RESERVED_AUTHORIZATION_PARAMS);
|
|
3
19
|
async function createAuthorizationURL({ id, options, authorizationEndpoint, state, codeVerifier, scopes, claims, redirectURI, duration, prompt, accessType, responseType, display, loginHint, hd, responseMode, additionalParams, scopeJoiner }) {
|
|
4
20
|
options = typeof options === "function" ? await options() : options;
|
|
5
21
|
const url = new URL(options.authorizationEndpoint || authorizationEndpoint);
|
|
6
22
|
url.searchParams.set("response_type", responseType || "code");
|
|
7
|
-
const primaryClientId =
|
|
23
|
+
const primaryClientId = getPrimaryClientId(options.clientId);
|
|
24
|
+
if (!primaryClientId) throw new Error("OAuth provider requires clientId");
|
|
8
25
|
url.searchParams.set("client_id", primaryClientId);
|
|
9
26
|
url.searchParams.set("state", state);
|
|
10
|
-
if (scopes) url.searchParams.set("scope", scopes.join(scopeJoiner || " "));
|
|
27
|
+
if (scopes?.length) url.searchParams.set("scope", scopes.join(scopeJoiner || " "));
|
|
11
28
|
url.searchParams.set("redirect_uri", options.redirectURI || redirectURI);
|
|
12
29
|
duration && url.searchParams.set("duration", duration);
|
|
13
30
|
display && url.searchParams.set("display", display);
|
|
@@ -32,10 +49,14 @@ async function createAuthorizationURL({ id, options, authorizationEndpoint, stat
|
|
|
32
49
|
...claimsObj
|
|
33
50
|
} }));
|
|
34
51
|
}
|
|
35
|
-
if (additionalParams)
|
|
52
|
+
if (additionalParams) for (const [key, value] of Object.entries(additionalParams)) {
|
|
53
|
+
if (RESERVED_AUTHORIZATION_PARAMS_SET.has(key)) continue;
|
|
36
54
|
url.searchParams.set(key, value);
|
|
37
|
-
}
|
|
38
|
-
return
|
|
55
|
+
}
|
|
56
|
+
return {
|
|
57
|
+
url,
|
|
58
|
+
requestedScopes: scopes ?? []
|
|
59
|
+
};
|
|
39
60
|
}
|
|
40
61
|
//#endregion
|
|
41
|
-
export { createAuthorizationURL };
|
|
62
|
+
export { RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, createAuthorizationURL };
|
package/dist/oauth2/index.d.mts
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
1
|
+
import { additionalAuthorizationParamsSchema } from "./authorization-params.mjs";
|
|
2
|
+
import { decodeBasicCredentials, encodeBasicCredentials } from "./basic-credentials.mjs";
|
|
3
|
+
import { CLIENT_ASSERTION_TYPE, ClientAssertionContext, ClientAssertionGetter, ClientAssertionGrantType, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, PrivateKeyJwtClientAssertionGetterOptions, PrivateKeyJwtSigningAlgorithm, createPrivateKeyJwtClientAssertionGetter, resolveClientAssertionParams, signPrivateKeyJwtClientAssertion } from "./client-assertion.mjs";
|
|
4
|
+
import { AuthorizationURLResult, GrantAuthority, OAuth2Tokens, OAuth2UserInfo, OAuthIdTokenConfig, ProviderGrantAuthority, ProviderOptions, UpstreamProvider } from "./oauth-provider.mjs";
|
|
5
|
+
import { TokenEndpointAuth, TokenEndpointAuthMethod, TokenEndpointSecretAuthentication } from "./token-endpoint-auth.mjs";
|
|
6
|
+
import { clientCredentialsToken, clientCredentialsTokenRequest } from "./client-credentials-token.mjs";
|
|
7
|
+
import { RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, createAuthorizationURL } from "./create-authorization-url.mjs";
|
|
8
|
+
import { refreshAccessToken, refreshAccessTokenRequest } from "./refresh-access-token.mjs";
|
|
9
|
+
import { includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, resolveRequestedScopes, unionGrantedScopes } from "./scopes.mjs";
|
|
10
|
+
import { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId } from "./utils.mjs";
|
|
11
|
+
import { authorizationCodeRequest, validateAuthorizationCode, validateToken } from "./validate-authorization-code.mjs";
|
|
8
12
|
import { getJwks, verifyAccessToken, verifyJwsAccessToken } from "./verify.mjs";
|
|
9
|
-
|
|
13
|
+
import { supportsIdTokenSignIn, verifyProviderIdToken } from "./verify-id-token.mjs";
|
|
14
|
+
export { type AuthorizationURLResult, CLIENT_ASSERTION_TYPE, type ClientAssertionContext, type ClientAssertionGetter, type ClientAssertionGrantType, type GrantAuthority, type OAuth2Tokens, type OAuth2UserInfo, type OAuthIdTokenConfig, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, type PrivateKeyJwtClientAssertionGetterOptions, type PrivateKeyJwtSigningAlgorithm, type ProviderGrantAuthority, type ProviderOptions, RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, type TokenEndpointAuth, type TokenEndpointAuthMethod, type TokenEndpointSecretAuthentication, type UpstreamProvider, additionalAuthorizationParamsSchema, applyDefaultAccessTokenExpiry, authorizationCodeRequest, clientCredentialsToken, clientCredentialsTokenRequest, createAuthorizationURL, createPrivateKeyJwtClientAssertionGetter, decodeBasicCredentials, encodeBasicCredentials, generateCodeChallenge, getJwks, getOAuth2Tokens, getPrimaryClientId, includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, refreshAccessToken, refreshAccessTokenRequest, resolveClientAssertionParams, resolveRequestedScopes, signPrivateKeyJwtClientAssertion, supportsIdTokenSignIn, unionGrantedScopes, validateAuthorizationCode, validateToken, verifyAccessToken, verifyJwsAccessToken, verifyProviderIdToken };
|
package/dist/oauth2/index.mjs
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, resolveRequestedScopes, unionGrantedScopes } from "./scopes.mjs";
|
|
2
|
+
import { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId } from "./utils.mjs";
|
|
3
|
+
import { RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, createAuthorizationURL } from "./create-authorization-url.mjs";
|
|
4
|
+
import { additionalAuthorizationParamsSchema } from "./authorization-params.mjs";
|
|
5
|
+
import { decodeBasicCredentials, encodeBasicCredentials } from "./basic-credentials.mjs";
|
|
6
|
+
import { CLIENT_ASSERTION_TYPE, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, createPrivateKeyJwtClientAssertionGetter, resolveClientAssertionParams, signPrivateKeyJwtClientAssertion } from "./client-assertion.mjs";
|
|
7
|
+
import { clientCredentialsToken, clientCredentialsTokenRequest } from "./client-credentials-token.mjs";
|
|
8
|
+
import { refreshAccessToken, refreshAccessTokenRequest } from "./refresh-access-token.mjs";
|
|
9
|
+
import { authorizationCodeRequest, validateAuthorizationCode, validateToken } from "./validate-authorization-code.mjs";
|
|
7
10
|
import { getJwks, verifyAccessToken, verifyJwsAccessToken } from "./verify.mjs";
|
|
8
|
-
|
|
11
|
+
import { supportsIdTokenSignIn, verifyProviderIdToken } from "./verify-id-token.mjs";
|
|
12
|
+
export { CLIENT_ASSERTION_TYPE, PRIVATE_KEY_JWT_SIGNING_ALGORITHMS, RESERVED_AUTHORIZATION_PARAMS, RESERVED_AUTHORIZATION_PARAMS_SET, additionalAuthorizationParamsSchema, applyDefaultAccessTokenExpiry, authorizationCodeRequest, clientCredentialsToken, clientCredentialsTokenRequest, createAuthorizationURL, createPrivateKeyJwtClientAssertionGetter, decodeBasicCredentials, encodeBasicCredentials, generateCodeChallenge, getJwks, getOAuth2Tokens, getPrimaryClientId, includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, refreshAccessToken, refreshAccessTokenRequest, resolveClientAssertionParams, resolveRequestedScopes, signPrivateKeyJwtClientAssertion, supportsIdTokenSignIn, unionGrantedScopes, validateAuthorizationCode, validateToken, verifyAccessToken, verifyJwsAccessToken, verifyProviderIdToken };
|
|
@@ -1,5 +1,53 @@
|
|
|
1
1
|
import { Awaitable, LiteralString } from "../types/helper.mjs";
|
|
2
|
+
import { JWTVerifyGetKey } from "jose";
|
|
3
|
+
|
|
2
4
|
//#region src/oauth2/oauth-provider.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* id_token verification config for a social provider.
|
|
7
|
+
*
|
|
8
|
+
* Declares how a client-submitted id_token is verified. The shared verifier
|
|
9
|
+
* (`verifyProviderIdToken`) consumes this instead of each provider implementing its own
|
|
10
|
+
* boolean check, so verification is centralized and fail-closed: a provider without a config
|
|
11
|
+
* cannot accept a forged token by omission.
|
|
12
|
+
*/
|
|
13
|
+
type OAuthIdTokenConfig = {
|
|
14
|
+
/**
|
|
15
|
+
* JWKS resolver used to verify the JWS signature. Accepts a jose
|
|
16
|
+
* `createRemoteJWKSet` resolver or a key-resolving function
|
|
17
|
+
* `(protectedHeader) => key`.
|
|
18
|
+
*/
|
|
19
|
+
jwks: JWTVerifyGetKey; /** Expected `iss`. Omit for providers whose issuer varies per tenant. */
|
|
20
|
+
issuer?: (string | string[]) | undefined; /** Expected `aud`, usually the client ID. */
|
|
21
|
+
audience: string | string[]; /** Permitted JWS algorithms. Defaults to the token's `alg` header. */
|
|
22
|
+
algorithms?: string[] | undefined; /** Maximum token age passed to jose (e.g. `"1h"`). */
|
|
23
|
+
maxTokenAge?: string | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* How the `nonce` claim is compared to the expected nonce.
|
|
26
|
+
* - `"exact"` (default): strict equality.
|
|
27
|
+
* - `"exact-or-sha256"`: matches the raw nonce or its SHA-256 hex digest (Apple).
|
|
28
|
+
*/
|
|
29
|
+
nonceComparison?: ("exact" | "exact-or-sha256") | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Accept non-JWS (opaque) tokens without signature verification. Identity is then
|
|
32
|
+
* resolved by getUserInfo from the access token via the provider userinfo endpoint,
|
|
33
|
+
* which validates it (e.g. Facebook Graph access tokens).
|
|
34
|
+
*/
|
|
35
|
+
allowOpaqueToken?: boolean | undefined;
|
|
36
|
+
/**
|
|
37
|
+
* Provider-specific claim check applied after the signature, issuer,
|
|
38
|
+
* audience, max-age, and nonce checks pass. Return `false` to reject the
|
|
39
|
+
* token. Used to enforce constraints the standard checks cannot express,
|
|
40
|
+
* e.g. Google's hosted-domain (`hd`) restriction. Omitted by providers
|
|
41
|
+
* that have no extra claim requirement.
|
|
42
|
+
*/
|
|
43
|
+
verifyClaims?: ((claims: Record<string, unknown>) => boolean) | undefined;
|
|
44
|
+
} | {
|
|
45
|
+
/**
|
|
46
|
+
* Custom verifier for providers that cannot verify against a local JWKS, such as a
|
|
47
|
+
* remote verification endpoint (e.g. LINE).
|
|
48
|
+
*/
|
|
49
|
+
verify: (token: string, nonce?: string) => Promise<boolean>;
|
|
50
|
+
};
|
|
3
51
|
interface OAuth2Tokens {
|
|
4
52
|
tokenType?: string | undefined;
|
|
5
53
|
accessToken?: string | undefined;
|
|
@@ -21,8 +69,58 @@ type OAuth2UserInfo = {
|
|
|
21
69
|
image?: string | undefined;
|
|
22
70
|
emailVerified: boolean;
|
|
23
71
|
};
|
|
24
|
-
|
|
72
|
+
/**
|
|
73
|
+
* The result of building a provider authorization URL.
|
|
74
|
+
*
|
|
75
|
+
* `requestedScopes` is the effective set of scopes encoded in the URL (the
|
|
76
|
+
* provider's built-in defaults + configured `options.scope` + per-request
|
|
77
|
+
* `scopes`, composed by `resolveRequestedScopes`). Callers persist it so the
|
|
78
|
+
* callback can fall back to the request when the provider omits `scope` from
|
|
79
|
+
* its token response (RFC 6749 §5.1).
|
|
80
|
+
*/
|
|
81
|
+
interface AuthorizationURLResult {
|
|
82
|
+
url: URL;
|
|
83
|
+
requestedScopes: string[];
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* How much an RP trusts a provider's echoed token-response `scope` when
|
|
87
|
+
* persisting `account.grantedScopes`.
|
|
88
|
+
*
|
|
89
|
+
* - `"full-grant"`: the echo is the user's complete current grant, so the seam
|
|
90
|
+
* replaces the stored grant with it. This is the only path that may narrow
|
|
91
|
+
* the grant. Declare it only for providers whose token response reports the
|
|
92
|
+
* full combined grant, e.g. Google with `include_granted_scopes`.
|
|
93
|
+
* - `"projection"`: the echo is this request's subset, so the seam unions it
|
|
94
|
+
* onto the stored grant. The safe default for every provider.
|
|
95
|
+
* - `"absent-echo"`: the provider omitted `scope`, so the grant equals what was
|
|
96
|
+
* requested (RFC 6749 §5.1) and the seam unions the requested set. Resolved
|
|
97
|
+
* at runtime by the persistence seam, never declared by a provider.
|
|
98
|
+
*
|
|
99
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
|
|
100
|
+
*/
|
|
101
|
+
type GrantAuthority = "full-grant" | "projection" | "absent-echo";
|
|
102
|
+
/**
|
|
103
|
+
* The authority a provider may declare for its own echoed scope. `"absent-echo"`
|
|
104
|
+
* is excluded because it is a runtime condition (an omitted echo), not a
|
|
105
|
+
* provider trait.
|
|
106
|
+
*/
|
|
107
|
+
type ProviderGrantAuthority = Exclude<GrantAuthority, "absent-echo">;
|
|
108
|
+
interface UpstreamProvider<T extends Record<string, any> = Record<string, any>, O extends Record<string, any> = Partial<ProviderOptions>> {
|
|
25
109
|
id: LiteralString;
|
|
110
|
+
/**
|
|
111
|
+
* The path the provider redirects back to, relative to the app base URL,
|
|
112
|
+
* e.g. `/callback/google`.
|
|
113
|
+
*/
|
|
114
|
+
callbackPath: string;
|
|
115
|
+
/**
|
|
116
|
+
* How the persistence seam treats this provider's echoed token-response
|
|
117
|
+
* `scope`. Declare `"full-grant"` only when the echo is the user's complete
|
|
118
|
+
* current grant (e.g. Google with `include_granted_scopes`); otherwise the
|
|
119
|
+
* echo is unioned onto the stored grant.
|
|
120
|
+
*
|
|
121
|
+
* @default "projection"
|
|
122
|
+
*/
|
|
123
|
+
grantAuthority?: ProviderGrantAuthority | undefined;
|
|
26
124
|
createAuthorizationURL: (data: {
|
|
27
125
|
state: string;
|
|
28
126
|
codeVerifier: string;
|
|
@@ -30,7 +128,14 @@ interface OAuthProvider<T extends Record<string, any> = Record<string, any>, O e
|
|
|
30
128
|
redirectURI: string;
|
|
31
129
|
display?: string | undefined;
|
|
32
130
|
loginHint?: string | undefined;
|
|
33
|
-
|
|
131
|
+
/**
|
|
132
|
+
* Extra query parameters to append to the authorization URL.
|
|
133
|
+
* Providers forward these to the shared `createAuthorizationURL` helper,
|
|
134
|
+
* which drops any keys present in `RESERVED_AUTHORIZATION_PARAMS`
|
|
135
|
+
* before applying them.
|
|
136
|
+
*/
|
|
137
|
+
additionalParams?: Record<string, string> | undefined;
|
|
138
|
+
}) => Awaitable<AuthorizationURLResult>;
|
|
34
139
|
name: string;
|
|
35
140
|
validateAuthorizationCode: (data: {
|
|
36
141
|
code: string;
|
|
@@ -58,14 +163,12 @@ interface OAuthProvider<T extends Record<string, any> = Record<string, any>, O e
|
|
|
58
163
|
* Custom function to refresh a token
|
|
59
164
|
*/
|
|
60
165
|
refreshAccessToken?: ((refreshToken: string) => Promise<OAuth2Tokens>) | undefined;
|
|
61
|
-
revokeToken?: ((token: string) => Promise<void>) | undefined;
|
|
62
166
|
/**
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
* @returns True if the id token is valid, false otherwise
|
|
167
|
+
* Declarative id_token verification config consumed by the shared
|
|
168
|
+
* `verifyProviderIdToken` verifier. Providers set this instead of implementing a boolean
|
|
169
|
+
* verify method, which keeps verification centralized and fail-closed.
|
|
67
170
|
*/
|
|
68
|
-
|
|
171
|
+
idToken?: OAuthIdTokenConfig | undefined;
|
|
69
172
|
/**
|
|
70
173
|
* The expected issuer identifier for this provider (RFC 9207).
|
|
71
174
|
* When set, the callback handler validates the `iss` query parameter
|
|
@@ -81,6 +184,17 @@ interface OAuthProvider<T extends Record<string, any> = Record<string, any>, O e
|
|
|
81
184
|
* Disable sign up for new users.
|
|
82
185
|
*/
|
|
83
186
|
disableSignUp?: boolean | undefined;
|
|
187
|
+
/**
|
|
188
|
+
* Accept callbacks that arrive without a `state` parameter. When true,
|
|
189
|
+
* the shared OAuth callback handler restarts the flow server-side with
|
|
190
|
+
* fresh `state` and PKCE instead of rejecting the request. Intended for
|
|
191
|
+
* providers that initiate OAuth without RP-side flow kickoff (e.g.
|
|
192
|
+
* Clever). Leave unset for any provider that always initiates from the
|
|
193
|
+
* RP.
|
|
194
|
+
*
|
|
195
|
+
* @default false
|
|
196
|
+
*/
|
|
197
|
+
allowIdpInitiated?: boolean | undefined;
|
|
84
198
|
/**
|
|
85
199
|
* Options for the provider
|
|
86
200
|
*/
|
|
@@ -90,9 +204,10 @@ type ProviderOptions<Profile extends Record<string, any> = any> = {
|
|
|
90
204
|
/**
|
|
91
205
|
* The client ID of your application.
|
|
92
206
|
*
|
|
93
|
-
*
|
|
207
|
+
* Some providers accept multiple platform client IDs. The first entry is the
|
|
208
|
+
* primary client ID used for token endpoint client authentication.
|
|
94
209
|
*/
|
|
95
|
-
clientId?:
|
|
210
|
+
clientId?: LiteralString | string[] | undefined;
|
|
96
211
|
/**
|
|
97
212
|
* The client secret of your application
|
|
98
213
|
*/
|
|
@@ -193,6 +308,29 @@ type ProviderOptions<Profile extends Record<string, any> = any> = {
|
|
|
193
308
|
* @default false
|
|
194
309
|
*/
|
|
195
310
|
overrideUserInfoOnSignIn?: boolean | undefined;
|
|
311
|
+
/**
|
|
312
|
+
* Require this provider's email to be verified before a session is created.
|
|
313
|
+
*
|
|
314
|
+
* When the provider reports the email as unverified, the user and account are
|
|
315
|
+
* still created/linked, but no session is issued: the OAuth callback redirects
|
|
316
|
+
* with `?error=email_not_verified` and id-token sign-in returns a `403`
|
|
317
|
+
* `EMAIL_NOT_VERIFIED`. A verification email is (re)sent per the
|
|
318
|
+
* `emailVerification` settings (`sendOnSignUp` / `sendOnSignIn`).
|
|
319
|
+
*
|
|
320
|
+
* The gate checks the local user's verification state, not the provider's
|
|
321
|
+
* claim on each request: a user already verified through another method (or a
|
|
322
|
+
* prior verified sign-in) keeps access even if the provider later reports the
|
|
323
|
+
* email as unverified.
|
|
324
|
+
*
|
|
325
|
+
* This is opt-in per provider and is independent of
|
|
326
|
+
* `emailAndPassword.requireEmailVerification`; enabling that does not gate
|
|
327
|
+
* social sign-in. Only enable it for providers that report a trustworthy
|
|
328
|
+
* `email_verified` signal: several providers always report the email as
|
|
329
|
+
* unverified, which would block every sign-in.
|
|
330
|
+
*
|
|
331
|
+
* @default false
|
|
332
|
+
*/
|
|
333
|
+
requireEmailVerification?: boolean | undefined;
|
|
196
334
|
};
|
|
197
335
|
//#endregion
|
|
198
|
-
export { OAuth2Tokens, OAuth2UserInfo,
|
|
336
|
+
export { AuthorizationURLResult, GrantAuthority, OAuth2Tokens, OAuth2UserInfo, OAuthIdTokenConfig, ProviderGrantAuthority, ProviderOptions, UpstreamProvider };
|