@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.
@@ -1,10 +1,11 @@
1
- import { a as ResourceServerMetadata } from "./oauth-DrFFxaBJ.mjs";
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 };
@@ -1,4 +1,5 @@
1
- import { a as getJwtPlugin, g as handleMcpErrors, o as getOAuthProviderPlugin } from "./utils-BpUSdl43.mjs";
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-CiaEIjBG.mjs";
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-DrFFxaBJ.mjs";
2
- import { n as oauthProvider, t as getOAuthProviderState } from "./oauth-CiaEIjBG.mjs";
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 mcpHandler, a as getJwtPlugin, c as isPKCERequired, d as resolveSubjectIdentifier, f as storeClientSecret, h as verifyOAuthQueryParams, i as getClient, l as parseClientMetadata, m as validateClientCredentials, n as decryptStoredClientSecret, p as storeToken, r as deleteFromPrompt, s as getStoredToken, t as basicToClientCredentials, u as parsePrompt } from "./utils-BpUSdl43.mjs";
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
- ctx.query = deleteFromPrompt(new URLSearchParams(_query), "create");
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: "missing verification redirect_uri",
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 ? new Date(verificationValue.authTime) : new Date(session.createdAt);
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 ? new Date(refreshToken.authTime) : void 0;
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.session && !ctx.options.session.storeSessionInDatabase) throw new BetterAuthError("OAuth Provider requires `session.storeSessionInDatabase: true` when using secondaryStorage");
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 issuer = (getJwtPlugin(ctx)?.options)?.jwt?.issuer ?? ctx.baseURL;
2728
- const issuerPath = new URL(issuer).pathname;
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: true,
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
- const query = ctx.query;
3687
- await oAuthState.set({ query: query.toString() });
3688
- if (!query.client_id) throw ctx.redirect(getErrorURL(ctx, "invalid_client", "client_id is required"));
3689
- if (!query.response_type) throw ctx.redirect(getErrorURL(ctx, "invalid_request", "response_type is required"));
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) throw ctx.redirect(getErrorURL(ctx, `unsupported_prompt_select_account`, "unsupported prompt type"));
3693
- if (!(query.response_type === "code")) throw ctx.redirect(getErrorURL(ctx, "unsupported_response_type", "unsupported response type"));
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) throw ctx.redirect(getErrorURL(ctx, "invalid_client", "client_id is required"));
3696
- if (client.disabled) throw ctx.redirect(getErrorURL(ctx, "client_disabled", "client is disabled"));
3697
- if (!client.redirectUris?.find((url) => url === query.redirect_uri) || !query.redirect_uri) throw ctx.redirect(getErrorURL(ctx, "invalid_redirect", "invalid redirect uri"));
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) throw ctx.redirect(formatErrorURL(query.redirect_uri, "invalid_scope", `The following scopes are invalid: ${invalidScopes.join(", ")}`, query.state, getIssuer(ctx, opts)));
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) throw ctx.redirect(formatErrorURL(query.redirect_uri, "invalid_request", pkceRequired.valueOf(), query.state, getIssuer(ctx, opts)));
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) throw ctx.redirect(formatErrorURL(query.redirect_uri, "invalid_request", "code_challenge and code_challenge_method must both be provided", query.state, getIssuer(ctx, opts)));
3716
- if (!["S256"].includes(query.code_challenge_method)) throw ctx.redirect(formatErrorURL(query.redirect_uri, "invalid_request", "invalid code_challenge method, only S256 is supported", query.state, getIssuer(ctx, opts)));
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: ctx.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 = new URLSearchParams(ctx.query);
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