@better-auth/oauth-provider 1.5.7-beta.1 → 1.6.0
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/client-resource.d.mts +3 -3
- package/dist/client-resource.mjs +3 -3
- package/dist/client.d.mts +3 -3
- package/dist/client.mjs +2 -2
- package/dist/index.d.mts +3 -4
- package/dist/index.mjs +81 -29
- package/dist/oauth-CYgzO8Am.d.mts +2081 -0
- package/dist/{oauth-DrFFxaBJ.d.mts → oauth-Cc0nzj5Q.d.mts} +20 -4
- package/dist/{utils-BpUSdl43.mjs → utils-sQ4gYeh3.mjs} +39 -3
- package/dist/version-DNcPo3T3.mjs +5 -0
- package/package.json +9 -8
- package/dist/client-resource.mjs.map +0 -1
- package/dist/client.mjs.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/oauth-CiaEIjBG.d.mts +0 -1879
- package/dist/utils-BpUSdl43.mjs.map +0 -1
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { a as ResourceServerMetadata } from "./oauth-
|
|
1
|
+
import { a as ResourceServerMetadata } from "./oauth-Cc0nzj5Q.mjs";
|
|
2
2
|
import { JWTPayload, JWTVerifyOptions } from "jose";
|
|
3
3
|
import { Auth } from "better-auth/types";
|
|
4
4
|
|
|
5
5
|
//#region src/client-resource.d.ts
|
|
6
6
|
declare const oauthProviderResourceClient: <T extends Auth | undefined>(auth?: T) => {
|
|
7
7
|
id: "oauth-provider-resource-client";
|
|
8
|
+
version: string;
|
|
8
9
|
getActions(): {
|
|
9
10
|
/**
|
|
10
11
|
* Performs verification of an access token for your APIs. Can perform
|
|
@@ -75,5 +76,4 @@ type ProtectedResourceMetadataOutput<T> = T extends Auth ? (overrides?: Partial<
|
|
|
75
76
|
externalScopes?: string[];
|
|
76
77
|
}) => Promise<ResourceServerMetadata>;
|
|
77
78
|
//#endregion
|
|
78
|
-
export { VerifyAccessTokenRemote, oauthProviderResourceClient };
|
|
79
|
-
//# sourceMappingURL=client-resource.d.mts.map
|
|
79
|
+
export { VerifyAccessTokenRemote, oauthProviderResourceClient };
|
package/dist/client-resource.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { a as getJwtPlugin,
|
|
1
|
+
import { a as getJwtPlugin, o as getOAuthProviderPlugin, v as handleMcpErrors } from "./utils-sQ4gYeh3.mjs";
|
|
2
|
+
import { t as PACKAGE_VERSION } from "./version-DNcPo3T3.mjs";
|
|
2
3
|
import { verifyAccessToken } from "better-auth/oauth2";
|
|
3
4
|
import { APIError } from "better-call";
|
|
4
5
|
import { logger } from "@better-auth/core/env";
|
|
@@ -22,6 +23,7 @@ const oauthProviderResourceClient = (auth) => {
|
|
|
22
23
|
const authServerBasePath = auth?.options.basePath;
|
|
23
24
|
return {
|
|
24
25
|
id: "oauth-provider-resource-client",
|
|
26
|
+
version: PACKAGE_VERSION,
|
|
25
27
|
getActions() {
|
|
26
28
|
return {
|
|
27
29
|
verifyAccessToken: (async (token, opts) => {
|
|
@@ -84,5 +86,3 @@ const oauthProviderResourceClient = (auth) => {
|
|
|
84
86
|
};
|
|
85
87
|
//#endregion
|
|
86
88
|
export { oauthProviderResourceClient };
|
|
87
|
-
|
|
88
|
-
//# sourceMappingURL=client-resource.mjs.map
|
package/dist/client.d.mts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { n as oauthProvider } from "./oauth-
|
|
1
|
+
import { n as oauthProvider } from "./oauth-CYgzO8Am.mjs";
|
|
2
2
|
import * as _better_fetch_fetch0 from "@better-fetch/fetch";
|
|
3
3
|
|
|
4
4
|
//#region src/client.d.ts
|
|
5
5
|
declare const oauthProviderClient: () => {
|
|
6
6
|
id: "oauth-provider-client";
|
|
7
|
+
version: string;
|
|
7
8
|
fetchPlugins: {
|
|
8
9
|
id: string;
|
|
9
10
|
name: string;
|
|
@@ -15,5 +16,4 @@ declare const oauthProviderClient: () => {
|
|
|
15
16
|
$InferServerPlugin: ReturnType<typeof oauthProvider>;
|
|
16
17
|
};
|
|
17
18
|
//#endregion
|
|
18
|
-
export { oauthProviderClient };
|
|
19
|
-
//# sourceMappingURL=client.d.mts.map
|
|
19
|
+
export { oauthProviderClient };
|
package/dist/client.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { t as PACKAGE_VERSION } from "./version-DNcPo3T3.mjs";
|
|
1
2
|
import { safeJSONParse } from "@better-auth/core/utils/json";
|
|
2
3
|
//#region src/client.ts
|
|
3
4
|
function parseSignedQuery(search) {
|
|
@@ -14,6 +15,7 @@ function parseSignedQuery(search) {
|
|
|
14
15
|
const oauthProviderClient = () => {
|
|
15
16
|
return {
|
|
16
17
|
id: "oauth-provider-client",
|
|
18
|
+
version: PACKAGE_VERSION,
|
|
17
19
|
fetchPlugins: [{
|
|
18
20
|
id: "oauth-provider-signin",
|
|
19
21
|
name: "oauth-provider-signin",
|
|
@@ -33,5 +35,3 @@ const oauthProviderClient = () => {
|
|
|
33
35
|
};
|
|
34
36
|
//#endregion
|
|
35
37
|
export { oauthProviderClient };
|
|
36
|
-
|
|
37
|
-
//# sourceMappingURL=client.mjs.map
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { _ as Awaitable, a as ResourceServerMetadata, c as OAuthConsent, d as OAuthRefreshToken, f as Prompt, g as VerificationValue, h as StoreTokenType, i as OIDCMetadata, l as OAuthOpaqueAccessToken, m as Scope, n as GrantType, o as AuthorizePrompt, p as SchemaClient, r as OAuthClient, s as OAuthAuthorizationQuery, t as AuthServerMetadata, u as OAuthOptions } from "./oauth-
|
|
2
|
-
import { n as oauthProvider, t as getOAuthProviderState } from "./oauth-
|
|
1
|
+
import { _ as Awaitable, a as ResourceServerMetadata, c as OAuthConsent, d as OAuthRefreshToken, f as Prompt, g as VerificationValue, h as StoreTokenType, i as OIDCMetadata, l as OAuthOpaqueAccessToken, m as Scope, n as GrantType, o as AuthorizePrompt, p as SchemaClient, r as OAuthClient, s as OAuthAuthorizationQuery, t as AuthServerMetadata, u as OAuthOptions } from "./oauth-Cc0nzj5Q.mjs";
|
|
2
|
+
import { n as oauthProvider, t as getOAuthProviderState } from "./oauth-CYgzO8Am.mjs";
|
|
3
3
|
import { verifyAccessToken } from "better-auth/oauth2";
|
|
4
4
|
import { JWSAlgorithms, JwtOptions } from "better-auth/plugins";
|
|
5
5
|
import { JWTPayload } from "jose";
|
|
@@ -61,5 +61,4 @@ declare const oauthProviderOpenIdConfigMetadata: <Auth extends {
|
|
|
61
61
|
headers?: HeadersInit;
|
|
62
62
|
}) => (_request: Request) => Promise<Response>;
|
|
63
63
|
//#endregion
|
|
64
|
-
export { AuthServerMetadata, AuthorizePrompt, OAuthAuthorizationQuery, OAuthClient, OAuthConsent, OAuthOpaqueAccessToken, OAuthOptions, OAuthRefreshToken, OIDCMetadata, Prompt, ResourceServerMetadata, SchemaClient, Scope, StoreTokenType, VerificationValue, authServerMetadata, getOAuthProviderState, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
|
|
65
|
-
//# sourceMappingURL=index.d.mts.map
|
|
64
|
+
export { AuthServerMetadata, AuthorizePrompt, OAuthAuthorizationQuery, OAuthClient, OAuthConsent, OAuthOpaqueAccessToken, OAuthOptions, OAuthRefreshToken, OIDCMetadata, Prompt, ResourceServerMetadata, SchemaClient, Scope, StoreTokenType, VerificationValue, authServerMetadata, getOAuthProviderState, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { _ as
|
|
1
|
+
import { _ as verifyOAuthQueryParams, a as getJwtPlugin, c as isPKCERequired, d as parsePrompt, f as resolveSessionAuthTime, g as validateClientCredentials, h as storeToken, i as getClient, l as normalizeTimestampValue, m as storeClientSecret, n as decryptStoredClientSecret, p as resolveSubjectIdentifier, r as deleteFromPrompt, s as getStoredToken, t as basicToClientCredentials, u as parseClientMetadata, y as mcpHandler } from "./utils-sQ4gYeh3.mjs";
|
|
2
|
+
import { t as PACKAGE_VERSION } from "./version-DNcPo3T3.mjs";
|
|
2
3
|
import { APIError, createAuthEndpoint, createAuthMiddleware, getOAuthState, getSessionFromCtx, sessionMiddleware } from "better-auth/api";
|
|
3
4
|
import { generateCodeChallenge, getJwks, verifyJwsAccessToken } from "better-auth/oauth2";
|
|
4
5
|
import { APIError as APIError$1 } from "better-call";
|
|
@@ -127,7 +128,9 @@ async function created(ctx, opts) {
|
|
|
127
128
|
error_description: "missing oauth query",
|
|
128
129
|
error: "invalid_request"
|
|
129
130
|
});
|
|
130
|
-
|
|
131
|
+
const query = new URLSearchParams(_query);
|
|
132
|
+
ctx.headers?.set("accept", "application/json");
|
|
133
|
+
ctx.query = deleteFromPrompt(query, "create");
|
|
131
134
|
const { url } = await authorizeEndpoint(ctx, opts);
|
|
132
135
|
return {
|
|
133
136
|
redirect: true,
|
|
@@ -292,9 +295,9 @@ async function createIdToken(ctx, opts, user, client, scopes, nonce, sessionId,
|
|
|
292
295
|
const jwtPluginOptions = opts.disableJwtPlugin ? void 0 : getJwtPlugin(ctx.context).options;
|
|
293
296
|
const payload = {
|
|
294
297
|
...userClaims,
|
|
295
|
-
...customClaims,
|
|
296
298
|
auth_time: authTimeSec,
|
|
297
299
|
acr,
|
|
300
|
+
...customClaims,
|
|
298
301
|
iss: jwtPluginOptions?.jwt?.issuer ?? ctx.context.baseURL,
|
|
299
302
|
sub: resolvedSub,
|
|
300
303
|
aud: client.clientId,
|
|
@@ -471,7 +474,7 @@ async function checkVerificationValue(ctx, opts, code, client_id, redirect_uri)
|
|
|
471
474
|
error: "invalid_user"
|
|
472
475
|
});
|
|
473
476
|
if (verificationValue.query?.redirect_uri && verificationValue.query?.redirect_uri !== redirect_uri) throw new APIError("BAD_REQUEST", {
|
|
474
|
-
error_description: "
|
|
477
|
+
error_description: "redirect_uri mismatch",
|
|
475
478
|
error: "invalid_request"
|
|
476
479
|
});
|
|
477
480
|
return verificationValue;
|
|
@@ -561,7 +564,7 @@ async function handleAuthorizationCodeGrant(ctx, opts) {
|
|
|
561
564
|
error_description: "session no longer exists",
|
|
562
565
|
error: "invalid_request"
|
|
563
566
|
});
|
|
564
|
-
const authTime = verificationValue.authTime != null ?
|
|
567
|
+
const authTime = verificationValue.authTime != null ? normalizeTimestampValue(verificationValue.authTime) : resolveSessionAuthTime(session);
|
|
565
568
|
return createUserTokens(ctx, opts, client, verificationValue.query.scope?.split(" ") ?? [], user, verificationValue.referenceId, session.id, verificationValue.query?.nonce, void 0, authTime);
|
|
566
569
|
}
|
|
567
570
|
/**
|
|
@@ -716,7 +719,7 @@ async function handleRefreshTokenGrant(ctx, opts) {
|
|
|
716
719
|
error_description: "user not found",
|
|
717
720
|
error: "invalid_request"
|
|
718
721
|
});
|
|
719
|
-
const authTime = refreshToken.authTime != null ?
|
|
722
|
+
const authTime = refreshToken.authTime != null ? normalizeTimestampValue(refreshToken.authTime) : void 0;
|
|
720
723
|
return createUserTokens(ctx, opts, client, requestedScopes ?? scopes, user, refreshToken.referenceId, refreshToken.sessionId, void 0, { refreshToken }, authTime);
|
|
721
724
|
}
|
|
722
725
|
//#endregion
|
|
@@ -1169,6 +1172,10 @@ async function checkOAuthClient(client, opts, settings) {
|
|
|
1169
1172
|
error: "invalid_client_metadata",
|
|
1170
1173
|
error_description: `pkce is required for registered clients.`
|
|
1171
1174
|
});
|
|
1175
|
+
if (settings?.isRegister && client.skip_consent) throw new APIError("BAD_REQUEST", {
|
|
1176
|
+
error: "invalid_client_metadata",
|
|
1177
|
+
error_description: "skip_consent cannot be set during dynamic client registration"
|
|
1178
|
+
});
|
|
1172
1179
|
}
|
|
1173
1180
|
async function createOAuthClientEndpoint(ctx, opts, settings) {
|
|
1174
1181
|
const body = ctx.body;
|
|
@@ -2720,12 +2727,21 @@ const oauthProvider = (options) => {
|
|
|
2720
2727
|
if (!opts.disableJwtPlugin && (opts.storeClientSecret === "encrypted" || typeof opts.storeClientSecret === "object" && ("encrypt" in opts.storeClientSecret || "decrypt" in opts.storeClientSecret))) throw new BetterAuthError("encryption method not recommended, please use 'hashed' or the 'hash' function");
|
|
2721
2728
|
return {
|
|
2722
2729
|
id: "oauth-provider",
|
|
2730
|
+
version: PACKAGE_VERSION,
|
|
2723
2731
|
options: opts,
|
|
2724
2732
|
init: (ctx) => {
|
|
2725
|
-
if (ctx.options.
|
|
2733
|
+
if (ctx.options.secondaryStorage && ctx.options.session?.storeSessionInDatabase !== true) throw new BetterAuthError("OAuth Provider requires `session.storeSessionInDatabase: true` when using secondaryStorage");
|
|
2726
2734
|
if (!opts.disableJwtPlugin) {
|
|
2727
|
-
const
|
|
2728
|
-
const
|
|
2735
|
+
const jwtPluginOptions = getJwtPlugin(ctx)?.options;
|
|
2736
|
+
const issuer = jwtPluginOptions?.jwt?.issuer ?? ctx.baseURL;
|
|
2737
|
+
const isDynamicBaseURLInit = jwtPluginOptions?.jwt?.issuer == null && typeof ctx.options.baseURL === "object" && ctx.options.baseURL !== null && "allowedHosts" in ctx.options.baseURL;
|
|
2738
|
+
let issuerPath;
|
|
2739
|
+
try {
|
|
2740
|
+
issuerPath = new URL(issuer).pathname;
|
|
2741
|
+
} catch (error) {
|
|
2742
|
+
if (isDynamicBaseURLInit && issuer === "") return;
|
|
2743
|
+
throw error;
|
|
2744
|
+
}
|
|
2729
2745
|
if (!opts.silenceWarnings?.oauthAuthServerConfig && !(ctx.options.basePath === "/" && issuerPath === "/")) logger.warn(`Please ensure '/.well-known/oauth-authorization-server${issuerPath === "/" ? "" : issuerPath}' exists. Upon completion, clear with silenceWarnings.oauthAuthServerConfig.`);
|
|
2730
2746
|
if (!opts.silenceWarnings?.openidConfig && ctx.options.basePath !== issuerPath && opts.scopes?.includes("openid")) logger.warn(`Please ensure '${issuerPath}${issuerPath.endsWith("/") ? "" : "/"}.well-known/openid-configuration' exists. Upon completion, clear with silenceWarnings.openidConfig.`);
|
|
2731
2747
|
}
|
|
@@ -2762,6 +2778,9 @@ const oauthProvider = (options) => {
|
|
|
2762
2778
|
const session = await ctx.context.internalAdapter.findSession(sessionToken);
|
|
2763
2779
|
if (!session) return;
|
|
2764
2780
|
ctx.context.session = session;
|
|
2781
|
+
const secFetchMode = ctx.request?.headers?.get("sec-fetch-mode")?.toLowerCase();
|
|
2782
|
+
const acceptHeader = ctx.request?.headers?.get("accept")?.toLowerCase() ?? "";
|
|
2783
|
+
if (!(secFetchMode === "navigate" || !secFetchMode && (acceptHeader.includes("text/html") || acceptHeader.includes("application/xhtml+xml")))) ctx.headers?.set("accept", "application/json");
|
|
2765
2784
|
ctx.query = deleteFromPrompt(query, "login");
|
|
2766
2785
|
return await authorizeEndpoint(ctx, opts);
|
|
2767
2786
|
})
|
|
@@ -2790,11 +2809,12 @@ const oauthProvider = (options) => {
|
|
|
2790
2809
|
oauth2Authorize: createAuthEndpoint("/oauth2/authorize", {
|
|
2791
2810
|
method: "GET",
|
|
2792
2811
|
query: z.object({
|
|
2793
|
-
response_type: z.enum(["code"]),
|
|
2812
|
+
response_type: z.enum(["code"]).optional(),
|
|
2794
2813
|
client_id: z.string(),
|
|
2795
2814
|
redirect_uri: SafeUrlSchema.optional(),
|
|
2796
2815
|
scope: z.string().optional(),
|
|
2797
2816
|
state: z.string().optional(),
|
|
2817
|
+
request_uri: z.string().optional(),
|
|
2798
2818
|
code_challenge: z.string().optional(),
|
|
2799
2819
|
code_challenge_method: z.enum(["S256"]).optional(),
|
|
2800
2820
|
nonce: z.string().optional(),
|
|
@@ -2814,7 +2834,7 @@ const oauthProvider = (options) => {
|
|
|
2814
2834
|
{
|
|
2815
2835
|
name: "response_type",
|
|
2816
2836
|
in: "query",
|
|
2817
|
-
required:
|
|
2837
|
+
required: false,
|
|
2818
2838
|
schema: { type: "string" },
|
|
2819
2839
|
description: "OAuth2 response type (e.g., 'code')"
|
|
2820
2840
|
},
|
|
@@ -2849,6 +2869,13 @@ const oauthProvider = (options) => {
|
|
|
2849
2869
|
schema: { type: "string" },
|
|
2850
2870
|
description: "OAuth2 state parameter"
|
|
2851
2871
|
},
|
|
2872
|
+
{
|
|
2873
|
+
name: "request_uri",
|
|
2874
|
+
in: "query",
|
|
2875
|
+
required: false,
|
|
2876
|
+
schema: { type: "string" },
|
|
2877
|
+
description: "Pushed Authorization Request URI referencing stored parameters"
|
|
2878
|
+
},
|
|
2852
2879
|
{
|
|
2853
2880
|
name: "code_challenge",
|
|
2854
2881
|
in: "query",
|
|
@@ -3421,7 +3448,8 @@ const oauthProvider = (options) => {
|
|
|
3421
3448
|
"native",
|
|
3422
3449
|
"user-agent-based"
|
|
3423
3450
|
]).optional(),
|
|
3424
|
-
subject_type: z.enum(["public", "pairwise"]).optional()
|
|
3451
|
+
subject_type: z.enum(["public", "pairwise"]).optional(),
|
|
3452
|
+
skip_consent: z.boolean().optional()
|
|
3425
3453
|
}),
|
|
3426
3454
|
metadata: { openapi: {
|
|
3427
3455
|
description: "Register an OAuth2 application",
|
|
@@ -3683,25 +3711,46 @@ async function authorizeEndpoint(ctx, opts, settings) {
|
|
|
3683
3711
|
error_description: "request not found",
|
|
3684
3712
|
error: "invalid_request"
|
|
3685
3713
|
});
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3714
|
+
let query = ctx.query;
|
|
3715
|
+
if (query.request_uri) {
|
|
3716
|
+
if (!opts.requestUriResolver) return handleRedirect(ctx, getErrorURL(ctx, "invalid_request_uri", "request_uri not supported"));
|
|
3717
|
+
const resolvedParams = await opts.requestUriResolver({
|
|
3718
|
+
requestUri: query.request_uri,
|
|
3719
|
+
clientId: query.client_id ?? "",
|
|
3720
|
+
ctx
|
|
3721
|
+
});
|
|
3722
|
+
if (!resolvedParams) return handleRedirect(ctx, getErrorURL(ctx, "invalid_request_uri", "request_uri is invalid or expired"));
|
|
3723
|
+
const urlClientId = query.client_id;
|
|
3724
|
+
query = resolvedParams;
|
|
3725
|
+
if (urlClientId) query.client_id = urlClientId;
|
|
3726
|
+
}
|
|
3727
|
+
ctx.query = query;
|
|
3728
|
+
await oAuthState.set({ query: serializeAuthorizationQuery(query).toString() });
|
|
3729
|
+
if (!query.client_id) return handleRedirect(ctx, getErrorURL(ctx, "invalid_client", "client_id is required"));
|
|
3730
|
+
if (!query.response_type) return handleRedirect(ctx, getErrorURL(ctx, "invalid_request", "response_type is required"));
|
|
3690
3731
|
const promptSet = ctx.query?.prompt ? parsePrompt(ctx.query?.prompt) : void 0;
|
|
3691
3732
|
const promptNone = promptSet?.has("none") ?? false;
|
|
3692
|
-
if (promptSet?.has("select_account") && !opts.selectAccount?.page)
|
|
3693
|
-
if (!(query.response_type === "code"))
|
|
3733
|
+
if (promptSet?.has("select_account") && !opts.selectAccount?.page) return handleRedirect(ctx, getErrorURL(ctx, `unsupported_prompt_select_account`, "unsupported prompt type"));
|
|
3734
|
+
if (!(query.response_type === "code")) return handleRedirect(ctx, getErrorURL(ctx, "unsupported_response_type", "unsupported response type"));
|
|
3694
3735
|
const client = await getClient(ctx, opts, query.client_id);
|
|
3695
|
-
if (!client)
|
|
3696
|
-
if (client.disabled)
|
|
3697
|
-
if (!client.redirectUris?.find((url) =>
|
|
3736
|
+
if (!client) return handleRedirect(ctx, getErrorURL(ctx, "invalid_client", "client_id is required"));
|
|
3737
|
+
if (client.disabled) return handleRedirect(ctx, getErrorURL(ctx, "client_disabled", "client is disabled"));
|
|
3738
|
+
if (!client.redirectUris?.find((url) => {
|
|
3739
|
+
if (url === query.redirect_uri) return true;
|
|
3740
|
+
try {
|
|
3741
|
+
const registered = new URL(url);
|
|
3742
|
+
const requested = new URL(query.redirect_uri);
|
|
3743
|
+
if ((registered.hostname === "127.0.0.1" || registered.hostname === "[::1]") && registered.hostname === requested.hostname && registered.pathname === requested.pathname && registered.protocol === requested.protocol && registered.search === requested.search) return true;
|
|
3744
|
+
} catch {}
|
|
3745
|
+
return false;
|
|
3746
|
+
}) || !query.redirect_uri) return handleRedirect(ctx, getErrorURL(ctx, "invalid_redirect", "invalid redirect uri"));
|
|
3698
3747
|
let requestedScopes = query.scope?.split(" ").filter((s) => s);
|
|
3699
3748
|
if (requestedScopes) {
|
|
3700
3749
|
const validScopes = new Set(client.scopes ?? opts.scopes);
|
|
3701
3750
|
const invalidScopes = requestedScopes.filter((scope) => {
|
|
3702
3751
|
return !validScopes?.has(scope);
|
|
3703
3752
|
});
|
|
3704
|
-
if (invalidScopes.length)
|
|
3753
|
+
if (invalidScopes.length) return handleRedirect(ctx, formatErrorURL(query.redirect_uri, "invalid_scope", `The following scopes are invalid: ${invalidScopes.join(", ")}`, query.state, getIssuer(ctx, opts)));
|
|
3705
3754
|
}
|
|
3706
3755
|
if (!requestedScopes) {
|
|
3707
3756
|
requestedScopes = client.scopes ?? opts.scopes ?? [];
|
|
@@ -3709,11 +3758,11 @@ async function authorizeEndpoint(ctx, opts, settings) {
|
|
|
3709
3758
|
}
|
|
3710
3759
|
const pkceRequired = isPKCERequired(client, requestedScopes);
|
|
3711
3760
|
if (pkceRequired) {
|
|
3712
|
-
if (!query.code_challenge || !query.code_challenge_method)
|
|
3761
|
+
if (!query.code_challenge || !query.code_challenge_method) return handleRedirect(ctx, formatErrorURL(query.redirect_uri, "invalid_request", pkceRequired.valueOf(), query.state, getIssuer(ctx, opts)));
|
|
3713
3762
|
}
|
|
3714
3763
|
if (query.code_challenge || query.code_challenge_method) {
|
|
3715
|
-
if (!query.code_challenge || !query.code_challenge_method)
|
|
3716
|
-
if (!["S256"].includes(query.code_challenge_method))
|
|
3764
|
+
if (!query.code_challenge || !query.code_challenge_method) return handleRedirect(ctx, formatErrorURL(query.redirect_uri, "invalid_request", "code_challenge and code_challenge_method must both be provided", query.state, getIssuer(ctx, opts)));
|
|
3765
|
+
if (!["S256"].includes(query.code_challenge_method)) return handleRedirect(ctx, formatErrorURL(query.redirect_uri, "invalid_request", "invalid code_challenge method, only S256 is supported", query.state, getIssuer(ctx, opts)));
|
|
3717
3766
|
}
|
|
3718
3767
|
const session = await getSessionFromCtx(ctx);
|
|
3719
3768
|
if (!session || promptSet?.has("login") || promptSet?.has("create")) {
|
|
@@ -3799,6 +3848,11 @@ async function authorizeEndpoint(ctx, opts, settings) {
|
|
|
3799
3848
|
referenceId
|
|
3800
3849
|
});
|
|
3801
3850
|
}
|
|
3851
|
+
function serializeAuthorizationQuery(query) {
|
|
3852
|
+
const params = new URLSearchParams();
|
|
3853
|
+
for (const [key, value] of Object.entries(query)) if (value != null) params.set(key, String(value));
|
|
3854
|
+
return params;
|
|
3855
|
+
}
|
|
3802
3856
|
async function redirectWithAuthorizationCode(ctx, opts, verificationValue) {
|
|
3803
3857
|
const code = generateRandomString(32, "a-z", "A-Z", "0-9");
|
|
3804
3858
|
const iat = Math.floor(Date.now() / 1e3);
|
|
@@ -3809,7 +3863,7 @@ async function redirectWithAuthorizationCode(ctx, opts, verificationValue) {
|
|
|
3809
3863
|
expiresAt: /* @__PURE__ */ new Date(exp * 1e3),
|
|
3810
3864
|
value: JSON.stringify({
|
|
3811
3865
|
type: "authorization_code",
|
|
3812
|
-
query:
|
|
3866
|
+
query: verificationValue.query,
|
|
3813
3867
|
userId: verificationValue.userId,
|
|
3814
3868
|
sessionId: verificationValue?.sessionId,
|
|
3815
3869
|
referenceId: verificationValue.referenceId,
|
|
@@ -3839,7 +3893,7 @@ async function redirectWithPromptCode(ctx, opts, type, page) {
|
|
|
3839
3893
|
}
|
|
3840
3894
|
async function signParams(ctx, opts) {
|
|
3841
3895
|
const exp = Math.floor(Date.now() / 1e3) + (opts.codeExpiresIn ?? 600);
|
|
3842
|
-
const params =
|
|
3896
|
+
const params = serializeAuthorizationQuery(ctx.query);
|
|
3843
3897
|
params.set("exp", String(exp));
|
|
3844
3898
|
const signature = await makeSignature(params.toString(), ctx.context.secret);
|
|
3845
3899
|
params.append("sig", signature);
|
|
@@ -3945,5 +3999,3 @@ const oauthProviderOpenIdConfigMetadata = (auth, opts) => {
|
|
|
3945
3999
|
};
|
|
3946
4000
|
//#endregion
|
|
3947
4001
|
export { authServerMetadata, getOAuthProviderState, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
|
|
3948
|
-
|
|
3949
|
-
//# sourceMappingURL=index.mjs.map
|