@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,61 +1,41 @@
|
|
|
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/refresh-access-token.d.ts
|
|
6
|
-
|
|
7
|
-
refreshToken,
|
|
8
|
-
options,
|
|
9
|
-
authentication,
|
|
10
|
-
clientAssertion,
|
|
11
|
-
tokenEndpoint,
|
|
12
|
-
extraParams,
|
|
13
|
-
resource
|
|
14
|
-
}: {
|
|
6
|
+
interface RefreshAccessTokenRequestInput {
|
|
15
7
|
refreshToken: string;
|
|
16
8
|
options: AwaitableFunction<Partial<ProviderOptions>>;
|
|
17
|
-
authentication?:
|
|
18
|
-
|
|
9
|
+
authentication?: TokenEndpointSecretAuthentication | undefined;
|
|
10
|
+
tokenEndpointAuth?: TokenEndpointAuth | undefined;
|
|
19
11
|
tokenEndpoint?: string | undefined;
|
|
20
12
|
extraParams?: Record<string, string> | undefined;
|
|
21
13
|
resource?: (string | string[]) | undefined;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
*/
|
|
29
|
-
declare function createRefreshAccessTokenRequest({
|
|
14
|
+
}
|
|
15
|
+
interface RefreshAccessTokenInput extends RefreshAccessTokenRequestInput {
|
|
16
|
+
options: Partial<ProviderOptions>;
|
|
17
|
+
tokenEndpoint: string;
|
|
18
|
+
}
|
|
19
|
+
declare function refreshAccessTokenRequest({
|
|
30
20
|
refreshToken,
|
|
31
21
|
options,
|
|
32
22
|
authentication,
|
|
23
|
+
tokenEndpointAuth,
|
|
24
|
+
tokenEndpoint,
|
|
33
25
|
extraParams,
|
|
34
26
|
resource
|
|
35
|
-
}: {
|
|
36
|
-
refreshToken: string;
|
|
37
|
-
options: ProviderOptions;
|
|
38
|
-
authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
|
|
39
|
-
extraParams?: Record<string, string> | undefined;
|
|
40
|
-
resource?: (string | string[]) | undefined;
|
|
41
|
-
}): {
|
|
27
|
+
}: RefreshAccessTokenRequestInput): Promise<{
|
|
42
28
|
body: URLSearchParams;
|
|
43
|
-
headers: Record<string,
|
|
44
|
-
}
|
|
29
|
+
headers: Record<string, string>;
|
|
30
|
+
}>;
|
|
45
31
|
declare function refreshAccessToken({
|
|
46
32
|
refreshToken,
|
|
47
33
|
options,
|
|
48
34
|
tokenEndpoint,
|
|
49
35
|
authentication,
|
|
50
|
-
|
|
51
|
-
extraParams
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
options: Partial<ProviderOptions>;
|
|
55
|
-
tokenEndpoint: string;
|
|
56
|
-
authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
|
|
57
|
-
clientAssertion?: ClientAssertionConfig | undefined;
|
|
58
|
-
extraParams?: Record<string, string> | undefined;
|
|
59
|
-
}): Promise<OAuth2Tokens>;
|
|
36
|
+
tokenEndpointAuth,
|
|
37
|
+
extraParams,
|
|
38
|
+
resource
|
|
39
|
+
}: RefreshAccessTokenInput): Promise<OAuth2Tokens>;
|
|
60
40
|
//#endregion
|
|
61
|
-
export {
|
|
41
|
+
export { refreshAccessToken, refreshAccessTokenRequest };
|
|
@@ -1,33 +1,26 @@
|
|
|
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/refresh-access-token.ts
|
|
5
|
-
async function refreshAccessTokenRequest({ refreshToken, options, authentication,
|
|
4
|
+
async function refreshAccessTokenRequest({ refreshToken, options, authentication, tokenEndpointAuth, tokenEndpoint, extraParams, resource }) {
|
|
6
5
|
options = typeof options === "function" ? await options() : options;
|
|
7
|
-
|
|
8
|
-
if (!clientAssertion) throw new Error("private_key_jwt authentication requires a clientAssertion configuration");
|
|
9
|
-
const assertionParams = await resolveAssertionParams({
|
|
10
|
-
clientAssertion,
|
|
11
|
-
clientId: Array.isArray(options.clientId) ? options.clientId[0] : options.clientId,
|
|
12
|
-
tokenEndpoint
|
|
13
|
-
});
|
|
14
|
-
extraParams = {
|
|
15
|
-
...extraParams,
|
|
16
|
-
...assertionParams
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
return createRefreshAccessTokenRequest({
|
|
6
|
+
const request = buildRefreshAccessTokenRequest({
|
|
20
7
|
refreshToken,
|
|
21
8
|
options,
|
|
22
|
-
authentication,
|
|
23
9
|
extraParams,
|
|
24
10
|
resource
|
|
25
11
|
});
|
|
12
|
+
await applyTokenEndpointAuth({
|
|
13
|
+
body: request.body,
|
|
14
|
+
headers: request.headers,
|
|
15
|
+
options,
|
|
16
|
+
tokenEndpoint: tokenEndpoint ?? "",
|
|
17
|
+
grantType: "refresh_token",
|
|
18
|
+
tokenEndpointAuth,
|
|
19
|
+
authentication
|
|
20
|
+
});
|
|
21
|
+
return request;
|
|
26
22
|
}
|
|
27
|
-
|
|
28
|
-
* @deprecated use async'd refreshAccessTokenRequest instead
|
|
29
|
-
*/
|
|
30
|
-
function createRefreshAccessTokenRequest({ refreshToken, options, authentication, extraParams, resource }) {
|
|
23
|
+
function buildRefreshAccessTokenRequest({ refreshToken, options, extraParams, resource }) {
|
|
31
24
|
const body = new URLSearchParams();
|
|
32
25
|
const headers = {
|
|
33
26
|
"content-type": "application/x-www-form-urlencoded",
|
|
@@ -35,13 +28,6 @@ function createRefreshAccessTokenRequest({ refreshToken, options, authentication
|
|
|
35
28
|
};
|
|
36
29
|
body.set("grant_type", "refresh_token");
|
|
37
30
|
body.set("refresh_token", refreshToken);
|
|
38
|
-
const primaryClientId = Array.isArray(options.clientId) ? options.clientId[0] : options.clientId;
|
|
39
|
-
if (authentication === "basic") if (primaryClientId) headers["authorization"] = "Basic " + base64.encode(`${primaryClientId}:${options.clientSecret ?? ""}`);
|
|
40
|
-
else headers["authorization"] = "Basic " + base64.encode(`:${options.clientSecret ?? ""}`);
|
|
41
|
-
else {
|
|
42
|
-
body.set("client_id", primaryClientId);
|
|
43
|
-
if (authentication !== "private_key_jwt" && options.clientSecret) body.set("client_secret", options.clientSecret);
|
|
44
|
-
}
|
|
45
31
|
if (resource) if (typeof resource === "string") body.append("resource", resource);
|
|
46
32
|
else for (const _resource of resource) body.append("resource", _resource);
|
|
47
33
|
if (extraParams) for (const [key, value] of Object.entries(extraParams)) body.set(key, value);
|
|
@@ -50,14 +36,15 @@ function createRefreshAccessTokenRequest({ refreshToken, options, authentication
|
|
|
50
36
|
headers
|
|
51
37
|
};
|
|
52
38
|
}
|
|
53
|
-
async function refreshAccessToken({ refreshToken, options, tokenEndpoint, authentication,
|
|
39
|
+
async function refreshAccessToken({ refreshToken, options, tokenEndpoint, authentication, tokenEndpointAuth, extraParams, resource }) {
|
|
54
40
|
const { body, headers } = await refreshAccessTokenRequest({
|
|
55
41
|
refreshToken,
|
|
56
42
|
options,
|
|
57
43
|
authentication,
|
|
58
|
-
|
|
44
|
+
tokenEndpointAuth,
|
|
59
45
|
tokenEndpoint,
|
|
60
|
-
extraParams
|
|
46
|
+
extraParams,
|
|
47
|
+
resource
|
|
61
48
|
});
|
|
62
49
|
const { data, error } = await betterFetch(tokenEndpoint, {
|
|
63
50
|
method: "POST",
|
|
@@ -69,7 +56,7 @@ async function refreshAccessToken({ refreshToken, options, tokenEndpoint, authen
|
|
|
69
56
|
accessToken: data.access_token,
|
|
70
57
|
refreshToken: data.refresh_token,
|
|
71
58
|
tokenType: data.token_type,
|
|
72
|
-
scopes: data.scope?.split(" "),
|
|
59
|
+
scopes: Array.isArray(data.scope) ? data.scope : data.scope?.split(" "),
|
|
73
60
|
idToken: data.id_token
|
|
74
61
|
};
|
|
75
62
|
if (data.expires_in) {
|
|
@@ -83,4 +70,4 @@ async function refreshAccessToken({ refreshToken, options, tokenEndpoint, authen
|
|
|
83
70
|
return tokens;
|
|
84
71
|
}
|
|
85
72
|
//#endregion
|
|
86
|
-
export {
|
|
73
|
+
export { refreshAccessToken, refreshAccessTokenRequest };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { ProviderOptions } from "./oauth-provider.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/oauth2/scopes.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Parse a provider's `scope` token-response field into a string array.
|
|
6
|
+
*
|
|
7
|
+
* RFC 6749 §3.3 defines `scope` as a space-delimited string, but providers
|
|
8
|
+
* vary: some (e.g. Twitch) return an already-split array. Accept both, plus the
|
|
9
|
+
* omitted/empty case, without ever calling `.split` on a non-string. Returns
|
|
10
|
+
* `[]` when no scope is present.
|
|
11
|
+
*
|
|
12
|
+
* @see https://github.com/better-auth/better-auth/issues/9076
|
|
13
|
+
*/
|
|
14
|
+
declare function parseScopeField(scope: unknown): string[];
|
|
15
|
+
/**
|
|
16
|
+
* Normalize a scope set into a single deduped, sorted array.
|
|
17
|
+
*
|
|
18
|
+
* Scope order is insignificant per RFC 6749 §3.3, so normalize for idempotent
|
|
19
|
+
* writes and trivial comparisons: trim each token, drop empties, dedupe, and
|
|
20
|
+
* sort ascending. Returns `[]` when the union is empty.
|
|
21
|
+
*
|
|
22
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
23
|
+
*/
|
|
24
|
+
declare function normalizeScopes(stored: string[] | null | undefined, incoming?: string[] | undefined): string[];
|
|
25
|
+
/**
|
|
26
|
+
* Union the stored granted-scope set with the scopes observed on an
|
|
27
|
+
* authorization or token exchange.
|
|
28
|
+
*
|
|
29
|
+
* The provider's echoed `scope` is authoritative when present. RFC 6749 §3.3
|
|
30
|
+
* and §5.1 say an omitted or empty echo means the grant equals what was
|
|
31
|
+
* requested, so fall back to `requested` in that case. The result unions onto
|
|
32
|
+
* the stored grant (never narrows on a normal write) and is normalized per
|
|
33
|
+
* {@link normalizeScopes}.
|
|
34
|
+
*
|
|
35
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
36
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
|
|
37
|
+
*/
|
|
38
|
+
declare function unionGrantedScopes(stored: string[] | null | undefined, echoed: string[] | undefined, requested: string[] | undefined): string[];
|
|
39
|
+
/**
|
|
40
|
+
* Coerce a stored granted-scope value into a usable array.
|
|
41
|
+
*
|
|
42
|
+
* `account.grantedScopes` is nullable (legacy rows and non-OAuth accounts read
|
|
43
|
+
* as unset), and on dialects that store the array as a JSON string a malformed
|
|
44
|
+
* operator backfill could deserialize to a non-array. Both collapse to `[]`
|
|
45
|
+
* here so every reader works against a real `string[]` without re-deriving the
|
|
46
|
+
* guard.
|
|
47
|
+
*/
|
|
48
|
+
declare function readGrantedScopes(stored: string[] | null | undefined): string[];
|
|
49
|
+
/**
|
|
50
|
+
* Test whether a normalized granted-scope set contains a specific scope.
|
|
51
|
+
*
|
|
52
|
+
* Matching is exact and case-sensitive per RFC 6749 §3.3. The argument is the
|
|
53
|
+
* normalized `account.grantedScopes` array; a raw provider `scope` string must
|
|
54
|
+
* be run through {@link parseScopeField} first.
|
|
55
|
+
*
|
|
56
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
57
|
+
*/
|
|
58
|
+
declare function includesGrantedScope(granted: string[] | null | undefined, scope: string): boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Compose the effective scope set to encode in a single authorization URL.
|
|
61
|
+
*
|
|
62
|
+
* Precedence: the provider's built-in defaults (unless `disableDefaultScope`),
|
|
63
|
+
* then the integrator's configured `options.scope`, then the per-request
|
|
64
|
+
* `scopes`. The result is the value persisted into OAuth state as the RFC 6749
|
|
65
|
+
* §5.1 fallback, so it is preserved verbatim (not normalized) to match what is
|
|
66
|
+
* sent to the provider.
|
|
67
|
+
*
|
|
68
|
+
* `defaultScopes` is a parameter rather than a provider-contract field so the
|
|
69
|
+
* runtime-synthesized generic OAuth provider, which has no static default set,
|
|
70
|
+
* can pass its configured scopes here.
|
|
71
|
+
*
|
|
72
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
|
|
73
|
+
*/
|
|
74
|
+
declare function resolveRequestedScopes(options: Pick<ProviderOptions, "scope" | "disableDefaultScope"> | undefined, defaultScopes: string[], perRequestScopes: string[] | undefined): string[];
|
|
75
|
+
//#endregion
|
|
76
|
+
export { includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, resolveRequestedScopes, unionGrantedScopes };
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
//#region src/oauth2/scopes.ts
|
|
2
|
+
/**
|
|
3
|
+
* Parse a provider's `scope` token-response field into a string array.
|
|
4
|
+
*
|
|
5
|
+
* RFC 6749 §3.3 defines `scope` as a space-delimited string, but providers
|
|
6
|
+
* vary: some (e.g. Twitch) return an already-split array. Accept both, plus the
|
|
7
|
+
* omitted/empty case, without ever calling `.split` on a non-string. Returns
|
|
8
|
+
* `[]` when no scope is present.
|
|
9
|
+
*
|
|
10
|
+
* @see https://github.com/better-auth/better-auth/issues/9076
|
|
11
|
+
*/
|
|
12
|
+
function parseScopeField(scope) {
|
|
13
|
+
if (Array.isArray(scope)) return scope.filter((s) => typeof s === "string" && s !== "");
|
|
14
|
+
if (typeof scope === "string") return scope.split(" ").filter(Boolean);
|
|
15
|
+
return [];
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Normalize a scope set into a single deduped, sorted array.
|
|
19
|
+
*
|
|
20
|
+
* Scope order is insignificant per RFC 6749 §3.3, so normalize for idempotent
|
|
21
|
+
* writes and trivial comparisons: trim each token, drop empties, dedupe, and
|
|
22
|
+
* sort ascending. Returns `[]` when the union is empty.
|
|
23
|
+
*
|
|
24
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
25
|
+
*/
|
|
26
|
+
function normalizeScopes(stored, incoming) {
|
|
27
|
+
const normalized = /* @__PURE__ */ new Set();
|
|
28
|
+
for (const scope of [...stored ?? [], ...incoming ?? []]) {
|
|
29
|
+
const trimmed = scope.trim();
|
|
30
|
+
if (trimmed) normalized.add(trimmed);
|
|
31
|
+
}
|
|
32
|
+
return [...normalized].sort();
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Union the stored granted-scope set with the scopes observed on an
|
|
36
|
+
* authorization or token exchange.
|
|
37
|
+
*
|
|
38
|
+
* The provider's echoed `scope` is authoritative when present. RFC 6749 §3.3
|
|
39
|
+
* and §5.1 say an omitted or empty echo means the grant equals what was
|
|
40
|
+
* requested, so fall back to `requested` in that case. The result unions onto
|
|
41
|
+
* the stored grant (never narrows on a normal write) and is normalized per
|
|
42
|
+
* {@link normalizeScopes}.
|
|
43
|
+
*
|
|
44
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
45
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
|
|
46
|
+
*/
|
|
47
|
+
function unionGrantedScopes(stored, echoed, requested) {
|
|
48
|
+
return normalizeScopes(stored, echoed?.length ? echoed : requested);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Coerce a stored granted-scope value into a usable array.
|
|
52
|
+
*
|
|
53
|
+
* `account.grantedScopes` is nullable (legacy rows and non-OAuth accounts read
|
|
54
|
+
* as unset), and on dialects that store the array as a JSON string a malformed
|
|
55
|
+
* operator backfill could deserialize to a non-array. Both collapse to `[]`
|
|
56
|
+
* here so every reader works against a real `string[]` without re-deriving the
|
|
57
|
+
* guard.
|
|
58
|
+
*/
|
|
59
|
+
function readGrantedScopes(stored) {
|
|
60
|
+
return Array.isArray(stored) ? stored : [];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Test whether a normalized granted-scope set contains a specific scope.
|
|
64
|
+
*
|
|
65
|
+
* Matching is exact and case-sensitive per RFC 6749 §3.3. The argument is the
|
|
66
|
+
* normalized `account.grantedScopes` array; a raw provider `scope` string must
|
|
67
|
+
* be run through {@link parseScopeField} first.
|
|
68
|
+
*
|
|
69
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-3.3
|
|
70
|
+
*/
|
|
71
|
+
function includesGrantedScope(granted, scope) {
|
|
72
|
+
return granted?.includes(scope) ?? false;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Compose the effective scope set to encode in a single authorization URL.
|
|
76
|
+
*
|
|
77
|
+
* Precedence: the provider's built-in defaults (unless `disableDefaultScope`),
|
|
78
|
+
* then the integrator's configured `options.scope`, then the per-request
|
|
79
|
+
* `scopes`. The result is the value persisted into OAuth state as the RFC 6749
|
|
80
|
+
* §5.1 fallback, so it is preserved verbatim (not normalized) to match what is
|
|
81
|
+
* sent to the provider.
|
|
82
|
+
*
|
|
83
|
+
* `defaultScopes` is a parameter rather than a provider-contract field so the
|
|
84
|
+
* runtime-synthesized generic OAuth provider, which has no static default set,
|
|
85
|
+
* can pass its configured scopes here.
|
|
86
|
+
*
|
|
87
|
+
* @see https://www.rfc-editor.org/rfc/rfc6749#section-5.1
|
|
88
|
+
*/
|
|
89
|
+
function resolveRequestedScopes(options, defaultScopes, perRequestScopes) {
|
|
90
|
+
const scopes = options?.disableDefaultScope ? [] : [...defaultScopes];
|
|
91
|
+
if (options?.scope) scopes.push(...options.scope);
|
|
92
|
+
if (perRequestScopes) scopes.push(...perRequestScopes);
|
|
93
|
+
return scopes;
|
|
94
|
+
}
|
|
95
|
+
//#endregion
|
|
96
|
+
export { includesGrantedScope, normalizeScopes, parseScopeField, readGrantedScopes, resolveRequestedScopes, unionGrantedScopes };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { ClientAssertionGetter } from "./client-assertion.mjs";
|
|
2
|
+
|
|
3
|
+
//#region src/oauth2/token-endpoint-auth.d.ts
|
|
4
|
+
type TokenEndpointAuth = {
|
|
5
|
+
method: "none";
|
|
6
|
+
} | {
|
|
7
|
+
method: "client_secret_basic";
|
|
8
|
+
} | {
|
|
9
|
+
method: "client_secret_post";
|
|
10
|
+
} | {
|
|
11
|
+
method: "private_key_jwt";
|
|
12
|
+
getClientAssertion: ClientAssertionGetter;
|
|
13
|
+
};
|
|
14
|
+
type TokenEndpointAuthMethod = TokenEndpointAuth["method"];
|
|
15
|
+
type TokenEndpointSecretAuthentication = "basic" | "post";
|
|
16
|
+
//#endregion
|
|
17
|
+
export { TokenEndpointAuth, TokenEndpointAuthMethod, TokenEndpointSecretAuthentication };
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { getPrimaryClientId } from "./utils.mjs";
|
|
2
|
+
import { encodeBasicCredentials } from "./basic-credentials.mjs";
|
|
3
|
+
import { resolveClientAssertionParams } from "./client-assertion.mjs";
|
|
4
|
+
//#region src/oauth2/token-endpoint-auth.ts
|
|
5
|
+
function getDefaultTokenEndpointAuth(options, authentication) {
|
|
6
|
+
if (authentication === "basic") return { method: "client_secret_basic" };
|
|
7
|
+
if (options.clientSecret) return { method: "client_secret_post" };
|
|
8
|
+
return { method: "none" };
|
|
9
|
+
}
|
|
10
|
+
function assertNoClientSecret(method, options, body) {
|
|
11
|
+
if (options.clientSecret || body.has("client_secret")) throw new Error(`${method} token endpoint authentication cannot be combined with clientSecret`);
|
|
12
|
+
}
|
|
13
|
+
function setClientId(body, clientId) {
|
|
14
|
+
if (clientId) body.set("client_id", clientId);
|
|
15
|
+
}
|
|
16
|
+
function assertClientSecretConfigured(method, options) {
|
|
17
|
+
if (!options.clientSecret) throw new Error(`${method} token endpoint authentication requires clientSecret`);
|
|
18
|
+
}
|
|
19
|
+
function assertClientIdConfigured(method, clientId) {
|
|
20
|
+
if (!clientId) throw new Error(`${method} token endpoint authentication requires clientId`);
|
|
21
|
+
}
|
|
22
|
+
function setClientSecretPostAuth({ body, options, clientId, requireClientSecret }) {
|
|
23
|
+
if (requireClientSecret) assertClientSecretConfigured("client_secret_post", options);
|
|
24
|
+
if (options.clientSecret) {
|
|
25
|
+
assertClientIdConfigured("client_secret_post", clientId);
|
|
26
|
+
setClientId(body, clientId);
|
|
27
|
+
body.set("client_secret", options.clientSecret);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function setClientSecretBasicAuth({ headers, options, clientId, body }) {
|
|
31
|
+
if (body.has("client_secret")) throw new Error("client_secret_basic token endpoint authentication cannot be combined with client_secret body parameters");
|
|
32
|
+
assertClientSecretConfigured("client_secret_basic", options);
|
|
33
|
+
assertClientIdConfigured("client_secret_basic", clientId);
|
|
34
|
+
headers.authorization = encodeBasicCredentials(clientId, options.clientSecret);
|
|
35
|
+
}
|
|
36
|
+
function assertCompleteManualClientAssertion(body) {
|
|
37
|
+
if (body.has("client_assertion") !== body.has("client_assertion_type")) throw new Error("client_assertion and client_assertion_type must both be provided");
|
|
38
|
+
}
|
|
39
|
+
async function applyTokenEndpointAuth({ body, headers, options, tokenEndpoint, grantType, tokenEndpointAuth, authentication }) {
|
|
40
|
+
assertCompleteManualClientAssertion(body);
|
|
41
|
+
const clientId = getPrimaryClientId(options.clientId);
|
|
42
|
+
if (body.has("client_assertion")) {
|
|
43
|
+
if (tokenEndpointAuth) throw new Error("client_assertion body parameters cannot be combined with tokenEndpointAuth");
|
|
44
|
+
assertNoClientSecret("private_key_jwt", options, body);
|
|
45
|
+
setClientId(body, clientId);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const auth = tokenEndpointAuth ?? getDefaultTokenEndpointAuth(options, authentication);
|
|
49
|
+
if (auth.method === "private_key_jwt") {
|
|
50
|
+
assertNoClientSecret(auth.method, options, body);
|
|
51
|
+
assertClientIdConfigured(auth.method, clientId);
|
|
52
|
+
if (!tokenEndpoint) throw new Error("private_key_jwt token endpoint authentication requires tokenEndpoint");
|
|
53
|
+
const assertionParams = await resolveClientAssertionParams({
|
|
54
|
+
getClientAssertion: auth.getClientAssertion,
|
|
55
|
+
context: {
|
|
56
|
+
clientId,
|
|
57
|
+
tokenEndpoint,
|
|
58
|
+
grantType
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
setClientId(body, clientId);
|
|
62
|
+
for (const [key, value] of Object.entries(assertionParams)) body.set(key, value);
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
if (auth.method === "none") {
|
|
66
|
+
assertNoClientSecret(auth.method, options, body);
|
|
67
|
+
if (grantType === "client_credentials") throw new Error("none token endpoint authentication cannot be used with client_credentials grant");
|
|
68
|
+
assertClientIdConfigured(auth.method, clientId);
|
|
69
|
+
setClientId(body, clientId);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (auth.method === "client_secret_basic") {
|
|
73
|
+
setClientSecretBasicAuth({
|
|
74
|
+
headers,
|
|
75
|
+
options,
|
|
76
|
+
clientId,
|
|
77
|
+
body
|
|
78
|
+
});
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
setClientSecretPostAuth({
|
|
82
|
+
body,
|
|
83
|
+
options,
|
|
84
|
+
clientId,
|
|
85
|
+
requireClientSecret: tokenEndpointAuth?.method === "client_secret_post"
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
//#endregion
|
|
89
|
+
export { applyTokenEndpointAuth };
|
package/dist/oauth2/utils.d.mts
CHANGED
|
@@ -2,6 +2,14 @@ import { OAuth2Tokens } from "./oauth-provider.mjs";
|
|
|
2
2
|
|
|
3
3
|
//#region src/oauth2/utils.d.ts
|
|
4
4
|
declare function getOAuth2Tokens(data: Record<string, any>): OAuth2Tokens;
|
|
5
|
+
/**
|
|
6
|
+
* Fill in `accessTokenExpiresAt` from the provider's configured
|
|
7
|
+
* `accessTokenExpiresIn` when the token response omitted `expires_in`. Without a
|
|
8
|
+
* known expiry, `getAccessToken` cannot tell the token is expired and never
|
|
9
|
+
* refreshes it. No-op when the provider already supplied an expiry or no
|
|
10
|
+
* fallback is configured.
|
|
11
|
+
*/
|
|
12
|
+
declare function applyDefaultAccessTokenExpiry(tokens: OAuth2Tokens, accessTokenExpiresIn: number | undefined): OAuth2Tokens;
|
|
5
13
|
/**
|
|
6
14
|
* Return the provider's primary Client ID: the single string, or the entry at
|
|
7
15
|
* array index 0 for the cross-platform form used by ID token audience
|
|
@@ -13,4 +21,4 @@ declare function getOAuth2Tokens(data: Record<string, any>): OAuth2Tokens;
|
|
|
13
21
|
declare function getPrimaryClientId(clientId: unknown): string | undefined;
|
|
14
22
|
declare function generateCodeChallenge(codeVerifier: string): Promise<string>;
|
|
15
23
|
//#endregion
|
|
16
|
-
export { generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId };
|
|
24
|
+
export { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId };
|
package/dist/oauth2/utils.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseScopeField } from "./scopes.mjs";
|
|
1
2
|
import { base64Url } from "@better-auth/utils/base64";
|
|
2
3
|
//#region src/oauth2/utils.ts
|
|
3
4
|
function getOAuth2Tokens(data) {
|
|
@@ -11,12 +12,23 @@ function getOAuth2Tokens(data) {
|
|
|
11
12
|
refreshToken: data.refresh_token,
|
|
12
13
|
accessTokenExpiresAt: data.expires_in ? getDate(data.expires_in) : void 0,
|
|
13
14
|
refreshTokenExpiresAt: data.refresh_token_expires_in ? getDate(data.refresh_token_expires_in) : void 0,
|
|
14
|
-
scopes: data
|
|
15
|
+
scopes: parseScopeField(data.scope),
|
|
15
16
|
idToken: data.id_token,
|
|
16
17
|
raw: data
|
|
17
18
|
};
|
|
18
19
|
}
|
|
19
20
|
/**
|
|
21
|
+
* Fill in `accessTokenExpiresAt` from the provider's configured
|
|
22
|
+
* `accessTokenExpiresIn` when the token response omitted `expires_in`. Without a
|
|
23
|
+
* known expiry, `getAccessToken` cannot tell the token is expired and never
|
|
24
|
+
* refreshes it. No-op when the provider already supplied an expiry or no
|
|
25
|
+
* fallback is configured.
|
|
26
|
+
*/
|
|
27
|
+
function applyDefaultAccessTokenExpiry(tokens, accessTokenExpiresIn) {
|
|
28
|
+
if (!tokens.accessTokenExpiresAt && accessTokenExpiresIn) tokens.accessTokenExpiresAt = new Date(Date.now() + accessTokenExpiresIn * 1e3);
|
|
29
|
+
return tokens;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
20
32
|
* Return the provider's primary Client ID: the single string, or the entry at
|
|
21
33
|
* array index 0 for the cross-platform form used by ID token audience
|
|
22
34
|
* verification. Index 0 is the designated primary and pairs with
|
|
@@ -34,4 +46,4 @@ async function generateCodeChallenge(codeVerifier) {
|
|
|
34
46
|
return base64Url.encode(new Uint8Array(hash), { padding: false });
|
|
35
47
|
}
|
|
36
48
|
//#endregion
|
|
37
|
-
export { generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId };
|
|
49
|
+
export { applyDefaultAccessTokenExpiry, generateCodeChallenge, getOAuth2Tokens, getPrimaryClientId };
|
|
@@ -1,64 +1,41 @@
|
|
|
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
|
import * as jose from "jose";
|
|
5
5
|
|
|
6
6
|
//#region src/oauth2/validate-authorization-code.d.ts
|
|
7
|
-
|
|
8
|
-
code,
|
|
9
|
-
codeVerifier,
|
|
10
|
-
redirectURI,
|
|
11
|
-
options,
|
|
12
|
-
authentication,
|
|
13
|
-
clientAssertion,
|
|
14
|
-
tokenEndpoint,
|
|
15
|
-
deviceId,
|
|
16
|
-
headers,
|
|
17
|
-
additionalParams,
|
|
18
|
-
resource
|
|
19
|
-
}: {
|
|
7
|
+
interface AuthorizationCodeRequestInput {
|
|
20
8
|
code: string;
|
|
21
9
|
redirectURI: string;
|
|
22
10
|
options: AwaitableFunction<Partial<ProviderOptions>>;
|
|
23
11
|
codeVerifier?: string | undefined;
|
|
24
12
|
deviceId?: string | undefined;
|
|
25
|
-
authentication?:
|
|
26
|
-
|
|
13
|
+
authentication?: TokenEndpointSecretAuthentication | undefined;
|
|
14
|
+
tokenEndpointAuth?: TokenEndpointAuth | undefined;
|
|
27
15
|
tokenEndpoint?: string | undefined;
|
|
28
16
|
headers?: Record<string, string> | undefined;
|
|
29
17
|
additionalParams?: Record<string, string> | undefined;
|
|
30
18
|
resource?: (string | string[]) | undefined;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
* @deprecated use async'd authorizationCodeRequest instead
|
|
37
|
-
*/
|
|
38
|
-
declare function createAuthorizationCodeRequest({
|
|
19
|
+
}
|
|
20
|
+
interface ValidateAuthorizationCodeInput extends AuthorizationCodeRequestInput {
|
|
21
|
+
tokenEndpoint: string;
|
|
22
|
+
}
|
|
23
|
+
declare function authorizationCodeRequest({
|
|
39
24
|
code,
|
|
40
25
|
codeVerifier,
|
|
41
26
|
redirectURI,
|
|
42
27
|
options,
|
|
43
28
|
authentication,
|
|
29
|
+
tokenEndpointAuth,
|
|
30
|
+
tokenEndpoint,
|
|
44
31
|
deviceId,
|
|
45
32
|
headers,
|
|
46
33
|
additionalParams,
|
|
47
34
|
resource
|
|
48
|
-
}: {
|
|
49
|
-
code: string;
|
|
50
|
-
redirectURI: string;
|
|
51
|
-
options: Partial<ProviderOptions>;
|
|
52
|
-
codeVerifier?: string | undefined;
|
|
53
|
-
deviceId?: string | undefined;
|
|
54
|
-
authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
|
|
55
|
-
headers?: Record<string, string> | undefined;
|
|
56
|
-
additionalParams?: Record<string, string> | undefined;
|
|
57
|
-
resource?: (string | string[]) | undefined;
|
|
58
|
-
}): {
|
|
35
|
+
}: AuthorizationCodeRequestInput): Promise<{
|
|
59
36
|
body: URLSearchParams;
|
|
60
|
-
headers: Record<string,
|
|
61
|
-
}
|
|
37
|
+
headers: Record<string, string>;
|
|
38
|
+
}>;
|
|
62
39
|
declare function validateAuthorizationCode({
|
|
63
40
|
code,
|
|
64
41
|
codeVerifier,
|
|
@@ -66,27 +43,15 @@ declare function validateAuthorizationCode({
|
|
|
66
43
|
options,
|
|
67
44
|
tokenEndpoint,
|
|
68
45
|
authentication,
|
|
69
|
-
|
|
46
|
+
tokenEndpointAuth,
|
|
70
47
|
deviceId,
|
|
71
48
|
headers,
|
|
72
49
|
additionalParams,
|
|
73
50
|
resource
|
|
74
|
-
}:
|
|
75
|
-
code: string;
|
|
76
|
-
redirectURI: string;
|
|
77
|
-
options: AwaitableFunction<Partial<ProviderOptions>>;
|
|
78
|
-
codeVerifier?: string | undefined;
|
|
79
|
-
deviceId?: string | undefined;
|
|
80
|
-
tokenEndpoint: string;
|
|
81
|
-
authentication?: ("basic" | "post" | "private_key_jwt") | undefined;
|
|
82
|
-
clientAssertion?: ClientAssertionConfig | undefined;
|
|
83
|
-
headers?: Record<string, string> | undefined;
|
|
84
|
-
additionalParams?: Record<string, string> | undefined;
|
|
85
|
-
resource?: (string | string[]) | undefined;
|
|
86
|
-
}): Promise<OAuth2Tokens>;
|
|
51
|
+
}: ValidateAuthorizationCodeInput): Promise<OAuth2Tokens>;
|
|
87
52
|
declare function validateToken(token: string, jwksEndpoint: string, options?: {
|
|
88
53
|
audience?: string | string[];
|
|
89
54
|
issuer?: string | string[];
|
|
90
55
|
}): Promise<jose.JWTVerifyResult<jose.JWTPayload> & jose.ResolvedKey>;
|
|
91
56
|
//#endregion
|
|
92
|
-
export { authorizationCodeRequest,
|
|
57
|
+
export { authorizationCodeRequest, validateAuthorizationCode, validateToken };
|