@better-auth/oauth-provider 1.6.11 → 1.6.13

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,9 +1,16 @@
1
- import { s as ResourceServerMetadata } from "./oauth-BqWgUea8.mjs";
1
+ import { s as ResourceServerMetadata } from "./oauth-D74mBkw6.mjs";
2
2
  import { JWTPayload, JWTVerifyOptions } from "jose";
3
- import { Auth } from "better-auth/types";
3
+ import { BetterAuthOptions } from "better-auth/types";
4
4
 
5
5
  //#region src/client-resource.d.ts
6
- declare const oauthProviderResourceClient: <T extends Auth | undefined>(auth?: T) => {
6
+ type ResourceClientAuth = {
7
+ options: {
8
+ baseURL?: BetterAuthOptions["baseURL"];
9
+ basePath?: BetterAuthOptions["basePath"];
10
+ };
11
+ $context: Promise<unknown>;
12
+ };
13
+ declare const oauthProviderResourceClient: <T extends ResourceClientAuth | undefined = undefined>(auth?: T) => {
7
14
  id: "oauth-provider-resource-client";
8
15
  version: string;
9
16
  getActions(): {
@@ -43,7 +50,7 @@ interface VerifyAccessTokenRemote {
43
50
  */
44
51
  force?: boolean;
45
52
  }
46
- type VerifyAccessTokenOutput<T> = T extends Auth ? (token: string | undefined, opts?: VerifyAccessTokenAuthOpts) => Promise<JWTPayload> : (token: string | undefined, opts: VerifyAccessTokenNoAuthOpts) => Promise<JWTPayload>;
53
+ type VerifyAccessTokenOutput<T> = T extends undefined ? (token: string | undefined, opts: VerifyAccessTokenNoAuthOpts) => Promise<JWTPayload> : (token: string | undefined, opts?: VerifyAccessTokenAuthOpts) => Promise<JWTPayload>;
47
54
  type VerifyAccessTokenAuthOpts = {
48
55
  verifyOptions?: JWTVerifyOptions & Required<Pick<JWTVerifyOptions, "audience">>;
49
56
  scopes?: string[];
@@ -64,12 +71,12 @@ type VerifyAccessTokenNoAuthOpts = {
64
71
  remoteVerify: VerifyAccessTokenRemote; /** Maps non-url (ie urn, client) resources to resource_metadata */
65
72
  resourceMetadataMappings?: Record<string, string>;
66
73
  };
67
- type ProtectedResourceMetadataOutput<T> = T extends Auth ? (overrides?: Partial<ResourceServerMetadata>, opts?: {
74
+ type ProtectedResourceMetadataOutput<T> = T extends undefined ? (overrides: ResourceServerMetadata, opts?: {
68
75
  silenceWarnings?: {
69
76
  oidcScopes?: boolean;
70
77
  };
71
78
  externalScopes?: string[];
72
- }) => Promise<ResourceServerMetadata> : (overrides: ResourceServerMetadata, opts?: {
79
+ }) => Promise<ResourceServerMetadata> : (overrides?: Partial<ResourceServerMetadata>, opts?: {
73
80
  silenceWarnings?: {
74
81
  oidcScopes?: boolean;
75
82
  };
@@ -1,5 +1,5 @@
1
- import { S as handleMcpErrors, a as getOAuthProviderPlugin, i as getJwtPlugin } from "./utils-LAthGy-x.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-CRjaDWWg.mjs";
1
+ import { S as handleMcpErrors, a as getOAuthProviderPlugin, i as getJwtPlugin } from "./utils-DoYEeMrg.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-MLrabwrK.mjs";
3
3
  import { verifyAccessToken } from "better-auth/oauth2";
4
4
  import { APIError } from "better-call";
5
5
  import { logger } from "@better-auth/core/env";
package/dist/client.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as oauthProvider } from "./oauth-C4GaGx2I.mjs";
1
+ import { n as oauthProvider } from "./oauth-CUqnBdrR.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-CRjaDWWg.mjs";
1
+ import { t as PACKAGE_VERSION } from "./version-MLrabwrK.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 OAuthClient, b as Awaitable, c as TokenEndpointAuthMethod, d as OAuthConsent, f as OAuthOpaqueAccessToken, g as SchemaClient, h as Prompt, i as GrantType, l as AuthorizePrompt, m as OAuthRefreshToken, n as AuthServerMetadata, o as OIDCMetadata, p as OAuthOptions, r as BearerMethodsSupported, s as ResourceServerMetadata, t as AuthMethod, u as OAuthAuthorizationQuery, v as StoreTokenType, y as VerificationValue } from "./oauth-BqWgUea8.mjs";
2
- import { n as oauthProvider, t as getOAuthProviderState } from "./oauth-C4GaGx2I.mjs";
1
+ import { _ as Scope, a as OAuthClient, b as Awaitable, c as TokenEndpointAuthMethod, d as OAuthConsent, f as OAuthOpaqueAccessToken, g as SchemaClient, h as Prompt, i as GrantType, l as AuthorizePrompt, m as OAuthRefreshToken, n as AuthServerMetadata, o as OIDCMetadata, p as OAuthOptions, r as BearerMethodsSupported, s as ResourceServerMetadata, t as AuthMethod, u as OAuthAuthorizationQuery, v as StoreTokenType, y as VerificationValue } from "./oauth-D74mBkw6.mjs";
2
+ import { n as oauthProvider, t as getOAuthProviderState } from "./oauth-CUqnBdrR.mjs";
3
3
  import { verifyAccessToken } from "better-auth/oauth2";
4
4
  import { JWSAlgorithms, JwtOptions } from "better-auth/plugins";
5
5
  import { JWTPayload } from "jose";
@@ -21,6 +21,7 @@ verifyOptions: Parameters<typeof verifyAccessToken>[1], handler: (req: Request,
21
21
  //#region src/metadata.d.ts
22
22
  declare function authServerMetadata(ctx: GenericEndpointContext, opts?: JwtOptions, overrides?: {
23
23
  scopes_supported?: AuthServerMetadata["scopes_supported"];
24
+ dynamic_client_registration_supported?: boolean;
24
25
  public_client_supported?: boolean;
25
26
  grant_types_supported?: GrantType[];
26
27
  jwt_disabled?: boolean;
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
- import { C as mcpHandler, _ as signedQueryIssuedAtParam, b as validateClientCredentials, c as isPKCERequired, d as parsePrompt, f as postLoginClearedParam, g as searchParamsToQuery, h as resolveSubjectIdentifier, i as getJwtPlugin, l as normalizeTimestampValue, m as resolveSessionAuthTime, n as decryptStoredClientSecret, o as getSignedQueryIssuedAt, p as removePromptFromQuery, r as getClient, s as getStoredToken, t as basicToClientCredentials, u as parseClientMetadata, v as storeClientSecret, x as verifyOAuthQueryParams, y as storeToken } from "./utils-LAthGy-x.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-CRjaDWWg.mjs";
1
+ import { C as mcpHandler, _ as signedQueryIssuedAtParam, b as validateClientCredentials, c as isPKCERequired, d as parsePrompt, f as postLoginClearedParam, g as searchParamsToQuery, h as resolveSubjectIdentifier, i as getJwtPlugin, l as normalizeTimestampValue, m as resolveSessionAuthTime, n as decryptStoredClientSecret, o as getSignedQueryIssuedAt, p as removePromptFromQuery, r as getClient, s as getStoredToken, t as basicToClientCredentials, u as parseClientMetadata, v as storeClientSecret, x as verifyOAuthQueryParams, y as storeToken } from "./utils-DoYEeMrg.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-MLrabwrK.mjs";
3
3
  import { APIError, createAuthEndpoint, createAuthMiddleware, getOAuthState, getSessionFromCtx, sessionMiddleware } from "better-auth/api";
4
4
  import { generateCodeChallenge, getJwks, verifyJwsAccessToken } from "better-auth/oauth2";
5
5
  import { APIError as APIError$1 } from "better-call";
@@ -14,6 +14,7 @@ import { mergeSchema } from "better-auth/db";
14
14
  import * as z from "zod";
15
15
  import { signJWT, toExpJWT } from "better-auth/plugins";
16
16
  import { SignJWT, compactVerify, createLocalJWKSet, decodeJwt } from "jose";
17
+ import { SafeUrlSchema } from "@better-auth/core/utils/redirect-uri";
17
18
  //#region src/consent.ts
18
19
  async function consentEndpoint(ctx, opts) {
19
20
  const oauthRequest = await oAuthState.get();
@@ -174,11 +175,6 @@ async function postLogin(ctx, opts) {
174
175
  }
175
176
  //#endregion
176
177
  //#region src/types/zod.ts
177
- const DANGEROUS_SCHEMES = [
178
- "javascript:",
179
- "data:",
180
- "vbscript:"
181
- ];
182
178
  /**
183
179
  * Runtime schema for OAuthAuthorizationQuery.
184
180
  * Uses passthrough to tolerate fields added by future extensions (PAR, FPA, etc.)
@@ -214,34 +210,6 @@ const verificationValueSchema = z.object({
214
210
  referenceId: z.string().optional(),
215
211
  authTime: z.number().optional()
216
212
  }).passthrough();
217
- /**
218
- * Reusable URL validation for OAuth redirect URIs.
219
- * - Blocks dangerous schemes (javascript:, data:, vbscript:)
220
- * - For http/https: requires HTTPS (HTTP allowed only for loopback hosts: 127.0.0.0/8, [::1], *.localhost per RFC 6761)
221
- * - Allows custom schemes for mobile apps (e.g., myapp://callback)
222
- */
223
- const SafeUrlSchema = z.url().superRefine((val, ctx) => {
224
- if (!URL.canParse(val)) {
225
- ctx.addIssue({
226
- code: "custom",
227
- message: "URL must be parseable",
228
- fatal: true
229
- });
230
- return z.NEVER;
231
- }
232
- const u = new URL(val);
233
- if (DANGEROUS_SCHEMES.includes(u.protocol)) {
234
- ctx.addIssue({
235
- code: "custom",
236
- message: "URL cannot use javascript:, data:, or vbscript: scheme"
237
- });
238
- return;
239
- }
240
- if (u.protocol === "http:" && !isLoopbackHost(u.host)) ctx.addIssue({
241
- code: "custom",
242
- message: "Redirect URI must use HTTPS (HTTP allowed only for loopback hosts)"
243
- });
244
- });
245
213
  //#endregion
246
214
  //#region src/userinfo.ts
247
215
  /**
@@ -605,11 +573,7 @@ async function createUserTokens(ctx, opts, params) {
605
573
  async function checkVerificationValue(ctx, opts, code, client_id, redirect_uri) {
606
574
  const verification = await ctx.context.internalAdapter.consumeVerificationValue(await storeToken(opts.storeTokens, code, "authorization_code"));
607
575
  if (!verification) throw new APIError("UNAUTHORIZED", {
608
- error_description: "Invalid code",
609
- error: "invalid_grant"
610
- });
611
- if (!verification.expiresAt || verification.expiresAt < /* @__PURE__ */ new Date()) throw new APIError("UNAUTHORIZED", {
612
- error_description: "code expired",
576
+ error_description: "invalid code",
613
577
  error: "invalid_grant"
614
578
  });
615
579
  let rawValue;
@@ -1237,6 +1201,28 @@ const publicSessionMiddleware = (opts) => createAuthMiddleware(async (ctx) => {
1237
1201
  if (!await verifyOAuthQueryParams(query, ctx.context.secret)) throw new APIError("UNAUTHORIZED", { error: "invalid_signature" });
1238
1202
  });
1239
1203
  //#endregion
1204
+ //#region src/oauthClient/privileges.ts
1205
+ /**
1206
+ * Authorizes a client action against the configured `clientPrivileges` hook.
1207
+ *
1208
+ * This is the single authorization helper for every OAuth client mutation. The
1209
+ * create path enforces it at the shared creation chokepoint so that no
1210
+ * registration route can reach client persistence without it.
1211
+ *
1212
+ * @throws APIError UNAUTHORIZED when there is no session or the hook denies the action.
1213
+ * @throws APIError BAD_REQUEST when the request carries no headers.
1214
+ */
1215
+ async function assertClientPrivileges(ctx, session, opts, action) {
1216
+ if (!session) throw new APIError("UNAUTHORIZED");
1217
+ if (!ctx.headers) throw new APIError("BAD_REQUEST");
1218
+ if (opts.clientPrivileges && !await opts.clientPrivileges({
1219
+ headers: ctx.headers,
1220
+ action,
1221
+ session: session.session,
1222
+ user: session.user
1223
+ })) throw new APIError("UNAUTHORIZED");
1224
+ }
1225
+ //#endregion
1240
1226
  //#region src/register.ts
1241
1227
  /**
1242
1228
  * Resolves the auth method and type for unauthenticated DCR.
@@ -1331,6 +1317,9 @@ async function checkOAuthClient(client, opts, settings) {
1331
1317
  async function createOAuthClientEndpoint(ctx, opts, settings) {
1332
1318
  const body = ctx.body;
1333
1319
  const session = await getSessionFromCtx(ctx);
1320
+ if (settings.isRegister) {
1321
+ if (session) await assertClientPrivileges(ctx, session, opts, "create");
1322
+ } else await assertClientPrivileges(ctx, session, opts, "create");
1334
1323
  const isPublic = body.token_endpoint_auth_method === "none";
1335
1324
  await checkOAuthClient(ctx.body, opts, settings);
1336
1325
  const clientId = opts.generateClientId?.() || generateRandomString(32, "a-z", "A-Z");
@@ -1662,16 +1651,6 @@ async function rotateClientSecretEndpoint(ctx, opts) {
1662
1651
  clientSecret: (opts.prefix?.clientSecret ?? "") + clientSecret
1663
1652
  });
1664
1653
  }
1665
- async function assertClientPrivileges(ctx, session, opts, action) {
1666
- if (!session) throw new APIError("UNAUTHORIZED");
1667
- if (!ctx.headers) throw new APIError("BAD_REQUEST");
1668
- if (opts.clientPrivileges && !await opts.clientPrivileges({
1669
- headers: ctx.headers,
1670
- action,
1671
- session: session.session,
1672
- user: session.user
1673
- })) throw new APIError("UNAUTHORIZED");
1674
- }
1675
1654
  //#endregion
1676
1655
  //#region src/oauthClient/index.ts
1677
1656
  const adminCreateOAuthClient = (opts) => createAuthEndpoint("/admin/oauth2/create-client", {
@@ -1854,7 +1833,6 @@ const adminCreateOAuthClient = (opts) => createAuthEndpoint("/admin/oauth2/creat
1854
1833
  }
1855
1834
  }
1856
1835
  }, async (ctx) => {
1857
- await assertClientPrivileges(ctx, await getSessionFromCtx(ctx), opts, "create");
1858
1836
  return createOAuthClientEndpoint(ctx, opts, { isRegister: false });
1859
1837
  });
1860
1838
  const createOAuthClient = (opts) => createAuthEndpoint("/oauth2/create-client", {
@@ -2024,7 +2002,6 @@ const createOAuthClient = (opts) => createAuthEndpoint("/oauth2/create-client",
2024
2002
  } }
2025
2003
  } }
2026
2004
  }, async (ctx) => {
2027
- await assertClientPrivileges(ctx, await getSessionFromCtx(ctx), opts, "create");
2028
2005
  return createOAuthClientEndpoint(ctx, opts, { isRegister: false });
2029
2006
  });
2030
2007
  const getOAuthClient = (opts) => createAuthEndpoint("/oauth2/get-client", {
@@ -2228,12 +2205,12 @@ async function updateConsentEndpoint(ctx, opts) {
2228
2205
  error_description: "no consent",
2229
2206
  error: "not_found"
2230
2207
  });
2208
+ if (consent.userId !== session.user.id) throw new APIError("UNAUTHORIZED");
2231
2209
  const client = await getClient(ctx, opts, consent.clientId);
2232
- if (!consent) throw new APIError("NOT_FOUND", {
2233
- error_description: "no consent",
2210
+ if (!client) throw new APIError("NOT_FOUND", {
2211
+ error_description: "client not found",
2234
2212
  error: "not_found"
2235
2213
  });
2236
- if (consent.userId !== session.user.id) throw new APIError("UNAUTHORIZED");
2237
2214
  const allowedScopes = client?.scopes ?? opts.scopes ?? [];
2238
2215
  const updates = ctx.body.update;
2239
2216
  const scopes = updates.scopes;
@@ -2831,6 +2808,47 @@ const oauthProvider = (options) => {
2831
2808
  if (opts.grantTypes && opts.grantTypes.includes("refresh_token") && !opts.grantTypes.includes("authorization_code")) throw new BetterAuthError("refresh_token grant requires authorization_code grant");
2832
2809
  if (opts.disableJwtPlugin && (opts.storeClientSecret === "hashed" || typeof opts.storeClientSecret === "object" && "hash" in opts.storeClientSecret)) throw new BetterAuthError("unable to store hashed secrets because id tokens will be signed with secret");
2833
2810
  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");
2811
+ const handleIssuerMetadataRequest = async (request, ctx) => {
2812
+ const requestPathname = new URL(request.url).pathname;
2813
+ const requestPath = ctx.options.advanced?.skipTrailingSlashes ? requestPathname.replace(/\/+$/, "") || "/" : requestPathname;
2814
+ const issuer = opts.disableJwtPlugin ? ctx.baseURL : getJwtPlugin(ctx)?.options?.jwt?.issuer ?? ctx.baseURL;
2815
+ let issuerPath = "/";
2816
+ try {
2817
+ issuerPath = new URL(issuer).pathname.replace(/\/$/, "") || "";
2818
+ } catch {
2819
+ issuerPath = new URL(ctx.baseURL).pathname.replace(/\/$/, "") || "";
2820
+ }
2821
+ const endpointCtx = { context: ctx };
2822
+ const authServerMetadataPaths = new Set([`/.well-known/oauth-authorization-server${issuerPath}`, `${issuerPath}/.well-known/oauth-authorization-server`]);
2823
+ const openIdConfigPath = `${issuerPath}/.well-known/openid-configuration`;
2824
+ const isAuthServerMetadataRequest = authServerMetadataPaths.has(requestPath);
2825
+ const isOpenIdConfigRequest = opts.scopes?.includes("openid") && requestPath === openIdConfigPath;
2826
+ const createMetadataResponse = (metadata) => {
2827
+ const response = metadataResponse(metadata);
2828
+ if (request.method === "HEAD") return new Response(null, {
2829
+ status: response.status,
2830
+ headers: response.headers
2831
+ });
2832
+ return response;
2833
+ };
2834
+ if (isAuthServerMetadataRequest || isOpenIdConfigRequest) {
2835
+ if (request.method !== "GET" && request.method !== "HEAD") return { response: new Response(null, {
2836
+ status: 405,
2837
+ headers: { Allow: "GET, HEAD" }
2838
+ }) };
2839
+ }
2840
+ if (isAuthServerMetadataRequest) {
2841
+ if (opts.scopes?.includes("openid")) return { response: createMetadataResponse(oidcServerMetadata(endpointCtx, opts)) };
2842
+ return { response: createMetadataResponse(authServerMetadata(endpointCtx, opts.disableJwtPlugin ? void 0 : getJwtPlugin(ctx)?.options, {
2843
+ scopes_supported: opts.advertisedMetadata?.scopes_supported ?? opts.scopes,
2844
+ dynamic_client_registration_supported: opts.allowDynamicClientRegistration,
2845
+ public_client_supported: opts.allowUnauthenticatedClientRegistration,
2846
+ grant_types_supported: opts.grantTypes,
2847
+ jwt_disabled: opts.disableJwtPlugin
2848
+ })) };
2849
+ }
2850
+ if (isOpenIdConfigRequest) return { response: createMetadataResponse(oidcServerMetadata(endpointCtx, opts)) };
2851
+ };
2834
2852
  return {
2835
2853
  id: "oauth-provider",
2836
2854
  version: PACKAGE_VERSION,
@@ -2852,6 +2870,7 @@ const oauthProvider = (options) => {
2852
2870
  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.`);
2853
2871
  }
2854
2872
  },
2873
+ onRequest: handleIssuerMetadataRequest,
2855
2874
  hooks: {
2856
2875
  before: [{
2857
2876
  matcher(ctx) {
@@ -2908,6 +2927,7 @@ const oauthProvider = (options) => {
2908
2927
  if (opts.scopes && opts.scopes.includes("openid")) return oidcServerMetadata(ctx, opts);
2909
2928
  else return authServerMetadata(ctx, opts.disableJwtPlugin ? void 0 : getJwtPlugin(ctx.context)?.options, {
2910
2929
  scopes_supported: opts.advertisedMetadata?.scopes_supported ?? opts.scopes,
2930
+ dynamic_client_registration_supported: opts.allowDynamicClientRegistration,
2911
2931
  public_client_supported: opts.allowUnauthenticatedClientRegistration,
2912
2932
  grant_types_supported: opts.grantTypes,
2913
2933
  jwt_disabled: opts.disableJwtPlugin
@@ -4030,7 +4050,7 @@ function authServerMetadata(ctx, opts, overrides) {
4030
4050
  authorization_endpoint: `${baseURL}/oauth2/authorize`,
4031
4051
  token_endpoint: `${baseURL}/oauth2/token`,
4032
4052
  jwks_uri: overrides?.jwt_disabled ? void 0 : opts?.jwks?.remoteUrl ?? `${baseURL}${opts?.jwks?.jwksPath ?? "/jwks"}`,
4033
- registration_endpoint: `${baseURL}/oauth2/register`,
4053
+ registration_endpoint: overrides?.dynamic_client_registration_supported ? `${baseURL}/oauth2/register` : void 0,
4034
4054
  introspection_endpoint: `${baseURL}/oauth2/introspect`,
4035
4055
  revocation_endpoint: `${baseURL}/oauth2/revoke`,
4036
4056
  response_types_supported: overrides?.grant_types_supported && !overrides.grant_types_supported.includes("authorization_code") ? [] : ["code"],
@@ -4057,6 +4077,7 @@ function oidcServerMetadata(ctx, opts) {
4057
4077
  return {
4058
4078
  ...authServerMetadata(ctx, jwtPluginOptions, {
4059
4079
  scopes_supported: opts.advertisedMetadata?.scopes_supported ?? opts.scopes,
4080
+ dynamic_client_registration_supported: opts.allowDynamicClientRegistration,
4060
4081
  public_client_supported: opts.allowUnauthenticatedClientRegistration,
4061
4082
  grant_types_supported: opts.grantTypes,
4062
4083
  jwt_disabled: opts.disableJwtPlugin
@@ -1,4 +1,4 @@
1
- import { _ as Scope, a as OAuthClient, d as OAuthConsent, n as AuthServerMetadata, o as OIDCMetadata, p as OAuthOptions } from "./oauth-BqWgUea8.mjs";
1
+ import { _ as Scope, a as OAuthClient, d as OAuthConsent, n as AuthServerMetadata, o as OIDCMetadata, p as OAuthOptions } from "./oauth-D74mBkw6.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";
@@ -30,6 +30,11 @@ declare const oauthProvider: <O extends OAuthOptions<Scope[]>>(options: O) => {
30
30
  version: string;
31
31
  options: NoInfer<O>;
32
32
  init: (ctx: better_auth0.AuthContext) => void;
33
+ onRequest: (request: Request, ctx: better_auth0.AuthContext) => Promise<{
34
+ response: Response;
35
+ } | {
36
+ request: Request;
37
+ } | void>;
33
38
  hooks: {
34
39
  before: {
35
40
  matcher(ctx: better_auth0.HookEndpointContext): any;
@@ -1380,9 +1380,11 @@ interface AuthServerMetadata {
1380
1380
  /**
1381
1381
  * The URL of the dynamic client registration endpoint.
1382
1382
  *
1383
+ * This field is only present when `allowDynamicClientRegistration` is enabled.
1384
+ *
1383
1385
  * @default `/oauth2/register`
1384
1386
  */
1385
- registration_endpoint: string;
1387
+ registration_endpoint?: string;
1386
1388
  /**
1387
1389
  * Supported scopes.
1388
1390
  */
@@ -254,11 +254,13 @@ function basicToClientCredentials(authorization) {
254
254
  if (authorization.startsWith("Basic ")) {
255
255
  const encoded = authorization.replace("Basic ", "");
256
256
  const decoded = new TextDecoder().decode(base64.decode(encoded));
257
- if (!decoded.includes(":")) throw new APIError$1("BAD_REQUEST", {
257
+ const separatorIndex = decoded.indexOf(":");
258
+ if (separatorIndex === -1) throw new APIError$1("BAD_REQUEST", {
258
259
  error_description: "invalid authorization header format",
259
260
  error: "invalid_client"
260
261
  });
261
- const [id, secret] = decoded.split(":", 2);
262
+ const id = decoded.slice(0, separatorIndex);
263
+ const secret = decoded.slice(separatorIndex + 1);
262
264
  if (!id || !secret) throw new APIError$1("BAD_REQUEST", {
263
265
  error_description: "invalid authorization header format",
264
266
  error: "invalid_client"
@@ -1,5 +1,5 @@
1
1
  //#endregion
2
2
  //#region src/version.ts
3
- const PACKAGE_VERSION = "1.6.11";
3
+ const PACKAGE_VERSION = "1.6.13";
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.6.11",
3
+ "version": "1.6.13",
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.6.11",
68
- "better-auth": "1.6.11"
67
+ "@better-auth/core": "1.6.13",
68
+ "better-auth": "1.6.13"
69
69
  },
70
70
  "peerDependencies": {
71
- "@better-auth/utils": "0.4.0",
71
+ "@better-auth/utils": "0.4.1",
72
72
  "@better-fetch/fetch": "1.1.21",
73
73
  "better-call": "1.3.5",
74
- "@better-auth/core": "^1.6.11",
75
- "better-auth": "^1.6.11"
74
+ "@better-auth/core": "^1.6.13",
75
+ "better-auth": "^1.6.13"
76
76
  },
77
77
  "scripts": {
78
78
  "build": "tsdown",