@better-auth/oauth-provider 1.7.0-beta.2 → 1.7.0-beta.3

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,4 +1,4 @@
1
- import { a as getClient } from "./utils-Cx_XnD9i.mjs";
1
+ import { i as getClient } from "./utils-_Jr_enAe.mjs";
2
2
  import { APIError } from "better-call";
3
3
  import { ASSERTION_SIGNING_ALGORITHMS, CLIENT_ASSERTION_TYPE } from "@better-auth/core/oauth2";
4
4
  import { createLocalJWKSet, decodeJwt, decodeProtectedHeader, jwtVerify } from "jose";
@@ -1,4 +1,4 @@
1
- import { o as ResourceServerMetadata } from "./oauth-CU79t-eG.mjs";
1
+ import { s as ResourceServerMetadata } from "./oauth-Ds-ejTJY.mjs";
2
2
  import { JWTPayload, JWTVerifyOptions } from "jose";
3
3
  import { Auth } from "better-auth/types";
4
4
 
@@ -1,6 +1,6 @@
1
1
  import { t as handleMcpErrors } from "./mcp-CYnz-MXn.mjs";
2
- import { o as getJwtPlugin, s as getOAuthProviderPlugin } from "./utils-Cx_XnD9i.mjs";
3
- import { t as PACKAGE_VERSION } from "./version-CZxZ64qJ.mjs";
2
+ import { a as getJwtPlugin, o as getOAuthProviderPlugin } from "./utils-_Jr_enAe.mjs";
3
+ import { t as PACKAGE_VERSION } from "./version-CG1YnCiF.mjs";
4
4
  import { verifyAccessToken } from "better-auth/oauth2";
5
5
  import { APIError } from "better-call";
6
6
  import { logger } from "@better-auth/core/env";
package/dist/client.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as oauthProvider } from "./oauth-DJcZ8MMZ.mjs";
1
+ import { n as oauthProvider } from "./oauth-BxP4Iupj.mjs";
2
2
  import * as _better_fetch_fetch0 from "@better-fetch/fetch";
3
3
 
4
4
  //#region src/client.d.ts
package/dist/client.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { t as PACKAGE_VERSION } from "./version-CZxZ64qJ.mjs";
1
+ import { t as PACKAGE_VERSION } from "./version-CG1YnCiF.mjs";
2
2
  import { safeJSONParse } from "@better-auth/core/utils/json";
3
3
  //#region src/client.ts
4
4
  function parseSignedQuery(search) {
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { _ as Scope, a as OIDCMetadata, b as Awaitable, c as AuthorizePrompt, d as OAuthConsent, f as OAuthOpaqueAccessToken, g as SchemaClient, h as Prompt, i as OAuthClient, l as ClientDiscovery, m as OAuthRefreshToken, n as AuthServerMetadata, o as ResourceServerMetadata, p as OAuthOptions, r as GrantType, s as TokenEndpointAuthMethod, t as AuthMethod, u as OAuthAuthorizationQuery, v as StoreTokenType, y as VerificationValue } from "./oauth-CU79t-eG.mjs";
2
- import { a as OAuthErrorCode, c as OAuthRedirectOnError, i as OAuthEndpointRedirectContext, n as oauthProvider, o as OAuthFieldErrorCode, r as OAuthEndpointErrorResult, s as OAuthFieldErrorCodeMap, t as getOAuthProviderState } from "./oauth-DJcZ8MMZ.mjs";
1
+ import { _ as SchemaClient, a as OAuthClient, b as VerificationValue, c as TokenEndpointAuthMethod, d as OAuthAuthorizationQuery, f as OAuthConsent, g as Prompt, h as OAuthRefreshToken, i as GrantType, l as AuthorizePrompt, m as OAuthOptions, n as AuthServerMetadata, o as OIDCMetadata, p as OAuthOpaqueAccessToken, r as BearerMethodsSupported, s as ResourceServerMetadata, t as AuthMethod, u as ClientDiscovery, v as Scope, x as Awaitable, y as StoreTokenType } from "./oauth-Ds-ejTJY.mjs";
2
+ import { a as OAuthErrorCode, c as OAuthRedirectOnError, i as OAuthEndpointRedirectContext, n as oauthProvider, o as OAuthFieldErrorCode, r as OAuthEndpointErrorResult, s as OAuthFieldErrorCodeMap, t as getOAuthProviderState } from "./oauth-BxP4Iupj.mjs";
3
3
  import { verifyAccessToken } from "better-auth/oauth2";
4
4
  import { JWSAlgorithms, JwtOptions } from "better-auth/plugins";
5
5
  import { JWTPayload } from "jose";
@@ -105,4 +105,4 @@ declare function checkOAuthClient(client: OAuthClient, opts: OAuthOptions<Scope[
105
105
  */
106
106
  declare function oauthToSchema(input: OAuthClient): SchemaClient<Scope[]>;
107
107
  //#endregion
108
- export { AuthServerMetadata, AuthorizePrompt, ClientDiscovery, OAuthAuthorizationQuery, OAuthClient, OAuthConsent, type OAuthEndpointErrorResult, type OAuthEndpointRedirectContext, type OAuthErrorCode, type OAuthFieldErrorCode, type OAuthFieldErrorCodeMap, OAuthOpaqueAccessToken, OAuthOptions, type OAuthRedirectOnError, OAuthRefreshToken, OIDCMetadata, Prompt, ResourceServerMetadata, SchemaClient, Scope, StoreTokenType, VerificationValue, authServerMetadata, checkOAuthClient, getOAuthProviderState, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oauthToSchema, oidcServerMetadata };
108
+ export { AuthMethod, AuthServerMetadata, AuthorizePrompt, BearerMethodsSupported, ClientDiscovery, GrantType, OAuthAuthorizationQuery, OAuthClient, OAuthConsent, type OAuthEndpointErrorResult, type OAuthEndpointRedirectContext, type OAuthErrorCode, type OAuthFieldErrorCode, type OAuthFieldErrorCodeMap, OAuthOpaqueAccessToken, OAuthOptions, type OAuthRedirectOnError, OAuthRefreshToken, OIDCMetadata, Prompt, ResourceServerMetadata, SchemaClient, Scope, StoreTokenType, TokenEndpointAuthMethod, VerificationValue, authServerMetadata, checkOAuthClient, getOAuthProviderState, mcpHandler, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oauthToSchema, oidcServerMetadata };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { n as isPrivateHostname } from "./client-assertion-CderPEmR.mjs";
1
+ import { n as isPrivateHostname } from "./client-assertion-BYtMWGCE.mjs";
2
2
  import { n as mcpHandler } from "./mcp-CYnz-MXn.mjs";
3
- import { _ as storeClientSecret, a as getClient, b as validateClientCredentials, c as getStoredToken, d as normalizeTimestampValue, f as parseClientMetadata, g as searchParamsToQuery, h as resolveSubjectIdentifier, i as extractClientCredentials, l as isPKCERequired, m as resolveSessionAuthTime, n as deleteFromPrompt, o as getJwtPlugin, p as parsePrompt, r as destructureCredentials, t as decryptStoredClientSecret, u as mergeDiscoveryMetadata, v as storeToken, x as verifyOAuthQueryParams, y as toClientDiscoveryArray } from "./utils-Cx_XnD9i.mjs";
4
- import { t as PACKAGE_VERSION } from "./version-CZxZ64qJ.mjs";
3
+ import { C as validateClientCredentials, S as toClientDiscoveryArray, _ as resolveSubjectIdentifier, a as getJwtPlugin, b as storeClientSecret, c as getStoredToken, d as normalizeTimestampValue, f as parseClientMetadata, g as resolveSessionAuthTime, h as removePromptFromQuery, i as getClient, l as isPKCERequired, m as postLoginClearedParam, n as destructureCredentials, p as parsePrompt, r as extractClientCredentials, s as getSignedQueryIssuedAt, t as decryptStoredClientSecret, u as mergeDiscoveryMetadata, v as searchParamsToQuery, w as verifyOAuthQueryParams, x as storeToken, y as signedQueryIssuedAtParam } from "./utils-_Jr_enAe.mjs";
4
+ import { t as PACKAGE_VERSION } from "./version-CG1YnCiF.mjs";
5
5
  import { APIError, createAuthEndpoint, createAuthMiddleware, getOAuthState, getSessionFromCtx, sessionMiddleware } from "better-auth/api";
6
6
  import { generateCodeChallenge, getJwks, verifyJwsAccessToken } from "better-auth/oauth2";
7
7
  import { APIError as APIError$1 } from "better-call";
@@ -19,7 +19,8 @@ import { resolveSigningKey, signJWT, toExpJWT } from "better-auth/plugins";
19
19
  import { SignJWT, base64url, compactVerify, createLocalJWKSet, decodeJwt, decodeProtectedHeader } from "jose";
20
20
  //#region src/consent.ts
21
21
  async function consentEndpoint(ctx, opts) {
22
- const _query = (await oAuthState.get())?.query;
22
+ const oauthRequest = await oAuthState.get();
23
+ const _query = oauthRequest?.query;
23
24
  if (!_query) throw new APIError("BAD_REQUEST", {
24
25
  error_description: "missing oauth query",
25
26
  error: "invalid_request"
@@ -43,6 +44,17 @@ async function consentEndpoint(ctx, opts) {
43
44
  url: formatErrorURL(query.get("redirect_uri") ?? "", "access_denied", "User denied access", query.get("state") ?? void 0, getIssuer(ctx, opts))
44
45
  };
45
46
  const session = await getSessionFromCtx(ctx);
47
+ const hasLoginPrompt = parsePrompt(query.get("prompt") ?? "").has("login");
48
+ const hasSatisfiedLoginPrompt = hasLoginPrompt && sessionSatisfiesLoginPrompt(session?.session.createdAt, oauthRequest?.signedQueryIssuedAt);
49
+ if (hasLoginPrompt && !hasSatisfiedLoginPrompt) {
50
+ ctx?.headers?.set("accept", "application/json");
51
+ ctx.query = searchParamsToQuery(query);
52
+ const { url } = await authorizeEndpoint(ctx, opts);
53
+ return {
54
+ redirect: true,
55
+ url
56
+ };
57
+ }
46
58
  const referenceId = await opts.postLogin?.consentReferenceId?.({
47
59
  user: session?.user,
48
60
  session: session?.session,
@@ -93,14 +105,21 @@ async function consentEndpoint(ctx, opts) {
93
105
  });
94
106
  if (requestedScopes) query.set("scope", consent.scopes.join(" "));
95
107
  ctx?.headers?.set("accept", "application/json");
96
- ctx.query = deleteFromPrompt(query, "consent");
97
- ctx.context.postLogin = true;
98
- const { url } = await authorizeEndpoint(ctx, opts);
108
+ let authorizationQuery = removePromptFromQuery(query, "consent");
109
+ if (hasSatisfiedLoginPrompt) authorizationQuery = removePromptFromQuery(authorizationQuery, "login");
110
+ ctx.query = searchParamsToQuery(authorizationQuery);
111
+ const { url } = await authorizeEndpoint(ctx, opts, { postLogin: oauthRequest?.postLoginClearedForSession !== void 0 && oauthRequest.postLoginClearedForSession === session?.session.id });
99
112
  return {
100
113
  redirect: true,
101
114
  url
102
115
  };
103
116
  }
117
+ function sessionSatisfiesLoginPrompt(sessionCreatedAt, signedQueryIssuedAt) {
118
+ if (!signedQueryIssuedAt) return false;
119
+ const normalized = normalizeTimestampValue(sessionCreatedAt);
120
+ if (!normalized) return false;
121
+ return normalized.getTime() >= signedQueryIssuedAt.getTime();
122
+ }
104
123
  //#endregion
105
124
  //#region src/continue.ts
106
125
  async function continueEndpoint(ctx, opts) {
@@ -119,7 +138,7 @@ async function selected(ctx, opts) {
119
138
  error: "invalid_request"
120
139
  });
121
140
  ctx.headers?.set("accept", "application/json");
122
- ctx.query = deleteFromPrompt(new URLSearchParams(_query), "select_account");
141
+ ctx.query = searchParamsToQuery(removePromptFromQuery(new URLSearchParams(_query), "select_account"));
123
142
  const { url } = await authorizeEndpoint(ctx, opts);
124
143
  return {
125
144
  redirect: true,
@@ -134,7 +153,7 @@ async function created(ctx, opts) {
134
153
  });
135
154
  const query = new URLSearchParams(_query);
136
155
  ctx.headers?.set("accept", "application/json");
137
- ctx.query = deleteFromPrompt(query, "create");
156
+ ctx.query = searchParamsToQuery(removePromptFromQuery(query, "create"));
138
157
  const { url } = await authorizeEndpoint(ctx, opts);
139
158
  return {
140
159
  redirect: true,
@@ -939,7 +958,7 @@ async function validateRefreshToken(ctx, opts, token, clientId) {
939
958
  model: "session",
940
959
  where: [{
941
960
  field: "id",
942
- value: refreshToken.sessionId
961
+ value: sessionId
943
962
  }]
944
963
  });
945
964
  if (!session || session.expiresAt < /* @__PURE__ */ new Date()) sessionId = void 0;
@@ -2617,7 +2636,8 @@ const schema = {
2617
2636
  references: {
2618
2637
  model: "user",
2619
2638
  field: "id"
2620
- }
2639
+ },
2640
+ index: true
2621
2641
  },
2622
2642
  createdAt: {
2623
2643
  type: "date",
@@ -2724,7 +2744,8 @@ const schema = {
2724
2744
  references: {
2725
2745
  model: "oauthClient",
2726
2746
  field: "clientId"
2727
- }
2747
+ },
2748
+ index: true
2728
2749
  },
2729
2750
  sessionId: {
2730
2751
  type: "string",
@@ -2733,7 +2754,8 @@ const schema = {
2733
2754
  model: "session",
2734
2755
  field: "id",
2735
2756
  onDelete: "set null"
2736
- }
2757
+ },
2758
+ index: true
2737
2759
  },
2738
2760
  userId: {
2739
2761
  type: "string",
@@ -2741,7 +2763,8 @@ const schema = {
2741
2763
  references: {
2742
2764
  model: "user",
2743
2765
  field: "id"
2744
- }
2766
+ },
2767
+ index: true
2745
2768
  },
2746
2769
  referenceId: {
2747
2770
  type: "string",
@@ -2775,7 +2798,8 @@ const schema = {
2775
2798
  references: {
2776
2799
  model: "oauthClient",
2777
2800
  field: "clientId"
2778
- }
2801
+ },
2802
+ index: true
2779
2803
  },
2780
2804
  sessionId: {
2781
2805
  type: "string",
@@ -2784,7 +2808,8 @@ const schema = {
2784
2808
  model: "session",
2785
2809
  field: "id",
2786
2810
  onDelete: "set null"
2787
- }
2811
+ },
2812
+ index: true
2788
2813
  },
2789
2814
  userId: {
2790
2815
  type: "string",
@@ -2792,7 +2817,8 @@ const schema = {
2792
2817
  references: {
2793
2818
  model: "user",
2794
2819
  field: "id"
2795
- }
2820
+ },
2821
+ index: true
2796
2822
  },
2797
2823
  referenceId: {
2798
2824
  type: "string",
@@ -2804,7 +2830,8 @@ const schema = {
2804
2830
  references: {
2805
2831
  model: "oauthRefreshToken",
2806
2832
  field: "id"
2807
- }
2833
+ },
2834
+ index: true
2808
2835
  },
2809
2836
  expiresAt: { type: "date" },
2810
2837
  createdAt: { type: "date" },
@@ -2823,7 +2850,8 @@ const schema = {
2823
2850
  references: {
2824
2851
  model: "oauthClient",
2825
2852
  field: "clientId"
2826
- }
2853
+ },
2854
+ index: true
2827
2855
  },
2828
2856
  userId: {
2829
2857
  type: "string",
@@ -2831,7 +2859,8 @@ const schema = {
2831
2859
  references: {
2832
2860
  model: "user",
2833
2861
  field: "id"
2834
- }
2862
+ },
2863
+ index: true
2835
2864
  },
2836
2865
  referenceId: {
2837
2866
  type: "string",
@@ -2943,10 +2972,18 @@ const oauthProvider = (options) => {
2943
2972
  handler: createAuthMiddleware(async (ctx) => {
2944
2973
  const query = ctx.body.oauth_query;
2945
2974
  if (!await verifyOAuthQueryParams(query, ctx.context.secret)) throw new APIError("BAD_REQUEST", { error: "invalid_signature" });
2975
+ const signedQueryIssuedAt = getSignedQueryIssuedAt(query);
2946
2976
  const queryParams = new URLSearchParams(query);
2977
+ const postLoginClearedForSession = queryParams.get("ba_pl") ?? void 0;
2947
2978
  queryParams.delete("sig");
2948
2979
  queryParams.delete("exp");
2949
- await oAuthState.set({ query: queryParams.toString() });
2980
+ queryParams.delete(signedQueryIssuedAtParam);
2981
+ queryParams.delete(postLoginClearedParam);
2982
+ await oAuthState.set({
2983
+ query: queryParams.toString(),
2984
+ signedQueryIssuedAt: signedQueryIssuedAt ?? void 0,
2985
+ postLoginClearedForSession
2986
+ });
2950
2987
  if (ctx.path === "/sign-in/social") {
2951
2988
  if (ctx.body.additionalData?.query) return;
2952
2989
  if (!ctx.body.additionalData) ctx.body.additionalData = {};
@@ -2970,7 +3007,7 @@ const oauthProvider = (options) => {
2970
3007
  const secFetchMode = ctx.request?.headers?.get("sec-fetch-mode")?.toLowerCase();
2971
3008
  const acceptHeader = ctx.request?.headers?.get("accept")?.toLowerCase() ?? "";
2972
3009
  if (!(secFetchMode === "navigate" || !secFetchMode && (acceptHeader.includes("text/html") || acceptHeader.includes("application/xhtml+xml")))) ctx.headers?.set("accept", "application/json");
2973
- ctx.query = deleteFromPrompt(query, "login");
3010
+ ctx.query = searchParamsToQuery(removePromptFromQuery(query, "login"));
2974
3011
  return await authorizeEndpoint(ctx, opts);
2975
3012
  })
2976
3013
  }]
@@ -4071,7 +4108,7 @@ async function authorizeEndpoint(ctx, opts, settings) {
4071
4108
  });
4072
4109
  if (signupRedirect) {
4073
4110
  if (promptNone) return redirectWithPromptNoneError(ctx, opts, query, "interaction_required", "End-User interaction is required");
4074
- return redirectWithPromptCode(ctx, opts, "create", typeof signupRedirect === "string" ? signupRedirect : void 0);
4111
+ return redirectWithPromptCode(ctx, opts, "create", { page: typeof signupRedirect === "string" ? signupRedirect : void 0 });
4075
4112
  }
4076
4113
  }
4077
4114
  if (!settings?.postLogin && opts.postLogin) {
@@ -4085,7 +4122,7 @@ async function authorizeEndpoint(ctx, opts, settings) {
4085
4122
  return redirectWithPromptCode(ctx, opts, "post_login");
4086
4123
  }
4087
4124
  }
4088
- if (promptSet?.has("consent")) return redirectWithPromptCode(ctx, opts, "consent");
4125
+ if (promptSet?.has("consent")) return redirectWithPromptCode(ctx, opts, "consent", { sessionId: session.session.id });
4089
4126
  const referenceId = await opts.postLogin?.consentReferenceId?.({
4090
4127
  user: session.user,
4091
4128
  session: session.session,
@@ -4118,7 +4155,7 @@ async function authorizeEndpoint(ctx, opts, settings) {
4118
4155
  });
4119
4156
  if (!consent || !requestedScopes.every((val) => consent.scopes.includes(val))) {
4120
4157
  if (promptNone) return redirectWithPromptNoneError(ctx, opts, query, "consent_required", "End-User consent is required");
4121
- return redirectWithPromptCode(ctx, opts, "consent");
4158
+ return redirectWithPromptCode(ctx, opts, "consent", { sessionId: session.session.id });
4122
4159
  }
4123
4160
  return redirectWithAuthorizationCode(ctx, opts, {
4124
4161
  query,
@@ -4165,8 +4202,8 @@ async function redirectWithAuthorizationCode(ctx, opts, verificationValue) {
4165
4202
  redirectUriWithCode.searchParams.set("iss", getIssuer(ctx, opts));
4166
4203
  return handleRedirect(ctx, redirectUriWithCode.toString());
4167
4204
  }
4168
- async function redirectWithPromptCode(ctx, opts, type, page) {
4169
- const queryParams = await signParams(ctx, opts);
4205
+ async function redirectWithPromptCode(ctx, opts, type, options) {
4206
+ const queryParams = await signParams(ctx, opts, { postLoginClearedForSession: type === "consent" && opts.postLogin ? options?.sessionId : void 0 });
4170
4207
  let path = opts.loginPage;
4171
4208
  if (type === "select_account") path = opts.selectAccount?.page ?? opts.loginPage;
4172
4209
  else if (type === "post_login") {
@@ -4174,12 +4211,16 @@ async function redirectWithPromptCode(ctx, opts, type, page) {
4174
4211
  path = opts.postLogin?.page;
4175
4212
  } else if (type === "consent") path = opts.consentPage;
4176
4213
  else if (type === "create") path = opts.signup?.page ?? opts.loginPage;
4177
- return handleRedirect(ctx, `${page ?? path}?${queryParams}`);
4214
+ return handleRedirect(ctx, `${options?.page ?? path}?${queryParams}`);
4178
4215
  }
4179
- async function signParams(ctx, opts) {
4180
- const exp = Math.floor(Date.now() / 1e3) + (opts.codeExpiresIn ?? 600);
4216
+ async function signParams(ctx, opts, flags) {
4217
+ const issuedAt = Date.now();
4218
+ const exp = Math.floor(issuedAt / 1e3) + (opts.codeExpiresIn ?? 600);
4181
4219
  const params = serializeAuthorizationQuery(ctx.query);
4182
4220
  params.set("exp", String(exp));
4221
+ params.set(signedQueryIssuedAtParam, String(issuedAt));
4222
+ params.delete(postLoginClearedParam);
4223
+ if (flags?.postLoginClearedForSession) params.set(postLoginClearedParam, flags.postLoginClearedForSession);
4183
4224
  const signature = await makeSignature(params.toString(), ctx.context.secret);
4184
4225
  params.append("sig", signature);
4185
4226
  return params.toString();
@@ -1,4 +1,4 @@
1
- import { _ as Scope, d as OAuthConsent, h as Prompt, i as OAuthClient, p as OAuthOptions, r as GrantType, s as TokenEndpointAuthMethod, t as AuthMethod } from "./oauth-CU79t-eG.mjs";
1
+ import { a as OAuthClient, c as TokenEndpointAuthMethod, f as OAuthConsent, g as Prompt, i as GrantType, m as OAuthOptions, t as AuthMethod, v as Scope } from "./oauth-Ds-ejTJY.mjs";
2
2
  import * as better_call0 from "better-call";
3
3
  import * as z from "zod";
4
4
  import * as better_auth_plugins0 from "better-auth/plugins";
@@ -45,6 +45,8 @@ declare module "@better-auth/core" {
45
45
  }
46
46
  declare const getOAuthProviderState: () => Promise<{
47
47
  query?: string;
48
+ signedQueryIssuedAt?: Date;
49
+ postLoginClearedForSession?: string;
48
50
  } | null>;
49
51
  /**
50
52
  * oAuth 2.1 provider plugin for Better Auth.
@@ -1967,6 +1969,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
1967
1969
  model: string;
1968
1970
  field: string;
1969
1971
  };
1972
+ index: true;
1970
1973
  };
1971
1974
  createdAt: {
1972
1975
  type: "date";
@@ -2075,6 +2078,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2075
2078
  model: string;
2076
2079
  field: string;
2077
2080
  };
2081
+ index: true;
2078
2082
  };
2079
2083
  sessionId: {
2080
2084
  type: "string";
@@ -2084,6 +2088,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2084
2088
  field: string;
2085
2089
  onDelete: "set null";
2086
2090
  };
2091
+ index: true;
2087
2092
  };
2088
2093
  userId: {
2089
2094
  type: "string";
@@ -2092,6 +2097,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2092
2097
  model: string;
2093
2098
  field: string;
2094
2099
  };
2100
+ index: true;
2095
2101
  };
2096
2102
  referenceId: {
2097
2103
  type: "string";
@@ -2131,6 +2137,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2131
2137
  model: string;
2132
2138
  field: string;
2133
2139
  };
2140
+ index: true;
2134
2141
  };
2135
2142
  sessionId: {
2136
2143
  type: "string";
@@ -2140,6 +2147,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2140
2147
  field: string;
2141
2148
  onDelete: "set null";
2142
2149
  };
2150
+ index: true;
2143
2151
  };
2144
2152
  userId: {
2145
2153
  type: "string";
@@ -2148,6 +2156,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2148
2156
  model: string;
2149
2157
  field: string;
2150
2158
  };
2159
+ index: true;
2151
2160
  };
2152
2161
  referenceId: {
2153
2162
  type: "string";
@@ -2160,6 +2169,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2160
2169
  model: string;
2161
2170
  field: string;
2162
2171
  };
2172
+ index: true;
2163
2173
  };
2164
2174
  expiresAt: {
2165
2175
  type: "date";
@@ -2183,6 +2193,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2183
2193
  model: string;
2184
2194
  field: string;
2185
2195
  };
2196
+ index: true;
2186
2197
  };
2187
2198
  userId: {
2188
2199
  type: "string";
@@ -2191,6 +2202,7 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
2191
2202
  model: string;
2192
2203
  field: string;
2193
2204
  };
2205
+ index: true;
2194
2206
  };
2195
2207
  referenceId: {
2196
2208
  type: "string";
@@ -46,6 +46,7 @@ declare const schema: {
46
46
  model: string;
47
47
  field: string;
48
48
  };
49
+ index: true;
49
50
  };
50
51
  createdAt: {
51
52
  type: "date";
@@ -159,6 +160,7 @@ declare const schema: {
159
160
  model: string;
160
161
  field: string;
161
162
  };
163
+ index: true;
162
164
  };
163
165
  sessionId: {
164
166
  type: "string";
@@ -168,6 +170,7 @@ declare const schema: {
168
170
  field: string;
169
171
  onDelete: "set null";
170
172
  };
173
+ index: true;
171
174
  };
172
175
  userId: {
173
176
  type: "string";
@@ -176,6 +179,7 @@ declare const schema: {
176
179
  model: string;
177
180
  field: string;
178
181
  };
182
+ index: true;
179
183
  };
180
184
  referenceId: {
181
185
  type: "string";
@@ -227,6 +231,7 @@ declare const schema: {
227
231
  model: string;
228
232
  field: string;
229
233
  };
234
+ index: true;
230
235
  };
231
236
  sessionId: {
232
237
  type: "string";
@@ -236,6 +241,7 @@ declare const schema: {
236
241
  field: string;
237
242
  onDelete: "set null";
238
243
  };
244
+ index: true;
239
245
  };
240
246
  userId: {
241
247
  type: "string";
@@ -244,6 +250,7 @@ declare const schema: {
244
250
  model: string;
245
251
  field: string;
246
252
  };
253
+ index: true;
247
254
  };
248
255
  referenceId: {
249
256
  type: "string";
@@ -256,6 +263,7 @@ declare const schema: {
256
263
  model: string;
257
264
  field: string;
258
265
  };
266
+ index: true;
259
267
  };
260
268
  expiresAt: {
261
269
  type: "date";
@@ -279,6 +287,7 @@ declare const schema: {
279
287
  model: string;
280
288
  field: string;
281
289
  };
290
+ index: true;
282
291
  };
283
292
  userId: {
284
293
  type: "string";
@@ -287,6 +296,7 @@ declare const schema: {
287
296
  model: string;
288
297
  field: string;
289
298
  };
299
+ index: true;
290
300
  };
291
301
  referenceId: {
292
302
  type: "string";
@@ -1096,10 +1106,12 @@ interface OAuthAuthorizationQuery {
1096
1106
  * Cross-Site Request Forgery (CSRF, XSRF) mitigation is done by cryptographically binding the
1097
1107
  * value of this parameter with a browser cookie.
1098
1108
  *
1109
+ * Recommended for clients, but optional for the authorization server.
1110
+ *
1099
1111
  * Note: Better Auth stores the state in a database instead of a cookie. - This is to minimize
1100
1112
  * the complication with native apps and other clients that may not have access to cookies.
1101
1113
  */
1102
- state: string;
1114
+ state?: string;
1103
1115
  /**
1104
1116
  * The client ID. Must be the ID of a registered client.
1105
1117
  */
@@ -1363,7 +1375,7 @@ interface OAuthOpaqueAccessToken<Scopes extends readonly Scope[] = InternallySup
1363
1375
  */
1364
1376
  interface OAuthRefreshToken<Scopes extends readonly Scope[] = InternallySupportedScopes[]> {
1365
1377
  token: string;
1366
- sessionId: string;
1378
+ sessionId?: string;
1367
1379
  userId: string;
1368
1380
  referenceId?: string;
1369
1381
  clientId?: string;
@@ -1739,4 +1751,4 @@ interface ResourceServerMetadata {
1739
1751
  dpop_bound_access_tokens_required?: boolean;
1740
1752
  }
1741
1753
  //#endregion
1742
- export { Scope as _, OIDCMetadata as a, Awaitable as b, AuthorizePrompt as c, OAuthConsent as d, OAuthOpaqueAccessToken as f, SchemaClient as g, Prompt as h, OAuthClient as i, ClientDiscovery as l, OAuthRefreshToken as m, AuthServerMetadata as n, ResourceServerMetadata as o, OAuthOptions as p, GrantType as r, TokenEndpointAuthMethod as s, AuthMethod as t, OAuthAuthorizationQuery as u, StoreTokenType as v, VerificationValue as y };
1754
+ export { SchemaClient as _, OAuthClient as a, VerificationValue as b, TokenEndpointAuthMethod as c, OAuthAuthorizationQuery as d, OAuthConsent as f, Prompt as g, OAuthRefreshToken as h, GrantType as i, AuthorizePrompt as l, OAuthOptions as m, AuthServerMetadata as n, OIDCMetadata as o, OAuthOpaqueAccessToken as p, BearerMethodsSupported as r, ResourceServerMetadata as s, AuthMethod as t, ClientDiscovery as u, Scope as v, Awaitable as x, StoreTokenType as y };
@@ -324,7 +324,7 @@ async function extractClientCredentials(ctx, opts, expectedAudience) {
324
324
  error_description: "client_assertion cannot be combined with client_secret or Basic auth",
325
325
  error: "invalid_client"
326
326
  });
327
- const { verifyClientAssertion: verify } = await import("./client-assertion-CderPEmR.mjs").then((n) => n.t);
327
+ const { verifyClientAssertion: verify } = await import("./client-assertion-BYtMWGCE.mjs").then((n) => n.t);
328
328
  const result = await verify(ctx, opts, body.client_assertion, body.client_assertion_type, body.client_id, expectedAudience);
329
329
  return {
330
330
  method: "private_key_jwt",
@@ -404,20 +404,24 @@ function searchParamsToQuery(params) {
404
404
  }
405
405
  return result;
406
406
  }
407
- /**
408
- * Deletes a prompt value
409
- *
410
- * @param ctx
411
- * @param prompt - the prompt value to delete
412
- */
413
- function deleteFromPrompt(query, prompt) {
414
- const prompts = query.get("prompt")?.split(" ");
407
+ const signedQueryIssuedAtParam = "ba_iat";
408
+ const postLoginClearedParam = "ba_pl";
409
+ function getSignedQueryIssuedAt(oauthQuery) {
410
+ const raw = new URLSearchParams(oauthQuery).get(signedQueryIssuedAtParam);
411
+ if (!raw) return null;
412
+ const issuedAt = Number(raw);
413
+ if (!Number.isFinite(issuedAt) || issuedAt <= 0) return null;
414
+ return new Date(issuedAt);
415
+ }
416
+ function removePromptFromQuery(query, prompt) {
417
+ const nextQuery = new URLSearchParams(query);
418
+ const prompts = nextQuery.get("prompt")?.split(" ");
415
419
  const foundPrompt = prompts?.findIndex((v) => v === prompt) ?? -1;
416
420
  if (foundPrompt >= 0) {
417
421
  prompts?.splice(foundPrompt, 1);
418
- prompts?.length ? query.set("prompt", prompts.join(" ")) : query.delete("prompt");
422
+ prompts?.length ? nextQuery.set("prompt", prompts.join(" ")) : nextQuery.delete("prompt");
419
423
  }
420
- return searchParamsToQuery(query);
424
+ return nextQuery;
421
425
  }
422
426
  var PKCERequirementErrors = /* @__PURE__ */ function(PKCERequirementErrors) {
423
427
  PKCERequirementErrors["PUBLIC_CLIENT"] = "pkce is required for public clients";
@@ -446,4 +450,4 @@ function isPKCERequired(client, requestedScopes) {
446
450
  return false;
447
451
  }
448
452
  //#endregion
449
- export { storeClientSecret as _, getClient as a, validateClientCredentials as b, getStoredToken as c, normalizeTimestampValue as d, parseClientMetadata as f, searchParamsToQuery as g, resolveSubjectIdentifier as h, extractClientCredentials as i, isPKCERequired as l, resolveSessionAuthTime as m, deleteFromPrompt as n, getJwtPlugin as o, parsePrompt as p, destructureCredentials as r, getOAuthProviderPlugin as s, decryptStoredClientSecret as t, mergeDiscoveryMetadata as u, storeToken as v, verifyOAuthQueryParams as x, toClientDiscoveryArray as y };
453
+ export { validateClientCredentials as C, toClientDiscoveryArray as S, resolveSubjectIdentifier as _, getJwtPlugin as a, storeClientSecret as b, getStoredToken as c, normalizeTimestampValue as d, parseClientMetadata as f, resolveSessionAuthTime as g, removePromptFromQuery as h, getClient as i, isPKCERequired as l, postLoginClearedParam as m, destructureCredentials as n, getOAuthProviderPlugin as o, parsePrompt as p, extractClientCredentials as r, getSignedQueryIssuedAt as s, decryptStoredClientSecret as t, mergeDiscoveryMetadata as u, searchParamsToQuery as v, verifyOAuthQueryParams as w, storeToken as x, signedQueryIssuedAtParam as y };
@@ -1,5 +1,5 @@
1
1
  //#endregion
2
2
  //#region src/version.ts
3
- const PACKAGE_VERSION = "1.7.0-beta.2";
3
+ const PACKAGE_VERSION = "1.7.0-beta.3";
4
4
  //#endregion
5
5
  export { PACKAGE_VERSION as t };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@better-auth/oauth-provider",
3
- "version": "1.7.0-beta.2",
3
+ "version": "1.7.0-beta.3",
4
4
  "description": "An oauth provider plugin for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -64,15 +64,15 @@
64
64
  "@modelcontextprotocol/sdk": "^1.27.1",
65
65
  "listhen": "^1.9.0",
66
66
  "tsdown": "0.21.1",
67
- "@better-auth/core": "1.7.0-beta.2",
68
- "better-auth": "1.7.0-beta.2"
67
+ "@better-auth/core": "1.7.0-beta.3",
68
+ "better-auth": "1.7.0-beta.3"
69
69
  },
70
70
  "peerDependencies": {
71
71
  "@better-auth/utils": "0.4.0",
72
72
  "@better-fetch/fetch": "1.1.21",
73
73
  "better-call": "1.3.5",
74
- "@better-auth/core": "^1.7.0-beta.2",
75
- "better-auth": "^1.7.0-beta.2"
74
+ "@better-auth/core": "^1.7.0-beta.3",
75
+ "better-auth": "^1.7.0-beta.3"
76
76
  },
77
77
  "scripts": {
78
78
  "build": "tsdown",