@better-auth/oauth-provider 1.7.6 → 1.7.7

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,8 +1,8 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs";
2
- import { A as filterClaimsRequestUserInfoClaims, C as resolveResourcePolicy, D as getSupportedClaims, E as STANDARD_CLAIM_NAMES, M as isValidOidcClaimsRequest, O as canSatisfyEssentialAcrRequest, S as logEnforcePerClientResourcesResolution, T as STANDARD_CLAIMS, _ as assertIdentifierValid, a as invalidateRefreshFamily, b as invalidateResourceCache, c as ResourceUriSchema, d as clientJwksSchema, f as clientRegistrationRequestSchema, g as JWS_ALGORITHMS, h as validateClientCredentialsScopes, j as getRequestedUserInfoClaims, k as claimsRequestParameterSchema, l as SafeUrlSchema, m as normalizeClientCredentialsScopes, o as tokenEndpoint, r as decodeRefreshToken, s as userInfoEndpoint, t as introspectEndpoint, u as authorizationQuerySchema, v as extractRepeatedResourceFromForm, w as seedResources, x as isAudienceClaimAllowed, y as getResource } from "./introspect-CbYi2MJT.mjs";
3
- import { B as validateOAuthProviderExtensions, C as storeToken, E as validateClientCredentials, I as getSupportedAuthMethods, L as getSupportedGrantTypes, O as verifyOAuthQueryParams, P as getClientDiscoveries, S as storeClientSecret, T as toResourceList, _ as removeMaxAgeFromQuery, a as getClient, b as resolveSubjectIdentifier, c as getStoredToken, d as mergeDiscoveryMetadata, g as parsePrompt, h as parseClientMetadata, i as extractClientCredentials, k as applyOAuthProviderMetadataExtensions, l as isPKCERequired, m as parseBearerToken, n as decryptStoredClientSecret, o as getJwtPlugin, r as destructureCredentials, t as clientAllowsGrant, u as isSessionFreshForSignedQuery, v as removePromptFromQuery, x as searchParamsToQuery, z as isExtensionTokenEndpointAuthMethod } from "./utils-CoqjzHuU.mjs";
2
+ import { A as filterClaimsRequestUserInfoClaims, C as resolveResourcePolicy, D as getSupportedClaims, E as STANDARD_CLAIM_NAMES, M as isValidOidcClaimsRequest, O as canSatisfyEssentialAcrRequest, S as logEnforcePerClientResourcesResolution, T as STANDARD_CLAIMS, _ as assertIdentifierValid, a as invalidateRefreshFamily, b as invalidateResourceCache, c as ResourceUriSchema, d as clientJwksSchema, f as clientRegistrationRequestSchema, g as JWS_ALGORITHMS, h as validateClientCredentialsScopes, j as getRequestedUserInfoClaims, k as claimsRequestParameterSchema, l as SafeUrlSchema, m as normalizeClientCredentialsScopes, o as tokenEndpoint, r as decodeRefreshToken, s as userInfoEndpoint, t as introspectEndpoint, u as authorizationQuerySchema, v as extractRepeatedResourceFromForm, w as seedResources, x as isAudienceClaimAllowed, y as getResource } from "./introspect-CNR06Oy3.mjs";
3
+ import { B as validateOAuthProviderExtensions, C as storeToken, E as validateClientCredentials, I as getSupportedAuthMethods, L as getSupportedGrantTypes, O as verifyOAuthQueryParams, P as getClientDiscoveries, S as storeClientSecret, T as toResourceList, _ as removeMaxAgeFromQuery, a as getClient, b as resolveSubjectIdentifier, c as getStoredToken, d as mergeDiscoveryMetadata, g as parsePrompt, h as parseClientMetadata, i as extractClientCredentials, k as applyOAuthProviderMetadataExtensions, l as isPKCERequired, m as parseBearerToken, n as decryptStoredClientSecret, o as getJwtPlugin, r as destructureCredentials, t as clientAllowsGrant, u as isSessionFreshForSignedQuery, v as removePromptFromQuery, x as searchParamsToQuery, z as isExtensionTokenEndpointAuthMethod } from "./utils-D6Hp4Qd_.mjs";
4
4
  import { a as setSignedOAuthQueryParameterNames, i as postLoginClearedParam, n as canonicalizeOAuthQueryParams, o as signedQueryIssuedAtParam, r as getSignedQueryIssuedAt } from "./signed-query-Df1MNiSH.mjs";
5
- import { t as PACKAGE_VERSION } from "./version-9KCSx144.mjs";
5
+ import { t as PACKAGE_VERSION } from "./version-C2j2jEFL.mjs";
6
6
  import { isBrowserFetchRequest } from "@better-auth/core/utils/fetch-metadata";
7
7
  import { isLoopbackHost, isLoopbackIP, isPublicRoutableHost } from "@better-auth/core/utils/host";
8
8
  import { appendQueryParams } from "@better-auth/core/utils/url";
@@ -5445,11 +5445,19 @@ function findRegisteredRedirectUri(registered, requested) {
5445
5445
  return stripLoopbackRedirectPort(url) === requestedWithoutPort;
5446
5446
  });
5447
5447
  }
5448
+ /** Keep URI syntax and credential checks outside the custom trust decision. */
5449
+ function isSafeCustomRedirectUri(uri) {
5450
+ if (!SafeUrlSchema.safeParse(uri).success) return false;
5451
+ const parsed = new URL(uri);
5452
+ return parsed.username.length === 0 && parsed.password.length === 0;
5453
+ }
5448
5454
  /**
5449
5455
  * Loads the client, verifies it's enabled, and returns the requested
5450
- * redirect_uri when it matches a registered entry. Returns null whenever the
5451
- * RP cannot be safely reached, so callers can fall back to the server error
5452
- * page (avoiding open-redirect risk on validation failures).
5456
+ * redirect_uri when it matches a registered entry (or is accepted by the
5457
+ * custom `validateRedirectUri` option, mirroring the authorize endpoint's
5458
+ * validation). Returns null whenever the RP cannot be safely reached, so
5459
+ * callers can fall back to the server error page (avoiding open-redirect
5460
+ * risk on validation failures).
5453
5461
  */
5454
5462
  async function resolveTrustedRedirectUri(ctx, opts, clientId, redirectUri) {
5455
5463
  if (!clientId || !redirectUri) return null;
@@ -5460,7 +5468,17 @@ async function resolveTrustedRedirectUri(ctx, opts, clientId, redirectUri) {
5460
5468
  return null;
5461
5469
  }
5462
5470
  if (!client || client.disabled) return null;
5463
- return findRegisteredRedirectUri(client.redirectUris, redirectUri) ? redirectUri : null;
5471
+ const registeredUris = client.redirectUris ?? [];
5472
+ const matched = findRegisteredRedirectUri(registeredUris, redirectUri);
5473
+ if (opts.validateRedirectUri) {
5474
+ if (!isSafeCustomRedirectUri(redirectUri)) return null;
5475
+ try {
5476
+ return await opts.validateRedirectUri(redirectUri, registeredUris, Boolean(matched)) ? redirectUri : null;
5477
+ } catch {
5478
+ return null;
5479
+ }
5480
+ }
5481
+ return matched ? redirectUri : null;
5464
5482
  }
5465
5483
  /**
5466
5484
  * `redirectOnError` callback for `/oauth2/authorize`. Per RFC 6749 §4.1.2.1,
@@ -5552,7 +5570,18 @@ async function authorizeEndpoint(ctx, opts, settings) {
5552
5570
  if (!client) return handleRedirect(ctx, getErrorURL(ctx, "invalid_client", "client_id is required"));
5553
5571
  if (client.disabled) return handleRedirect(ctx, getErrorURL(ctx, "client_disabled", "client is disabled"));
5554
5572
  if (!clientAllowsGrant(client, "authorization_code")) return handleRedirect(ctx, getErrorURL(ctx, "unauthorized_client", "client is not authorized to use the authorization_code grant"));
5555
- if (!findRegisteredRedirectUri(client.redirectUris, query.redirect_uri) || !query.redirect_uri) return handleRedirect(ctx, getErrorURL(ctx, "invalid_redirect", "invalid redirect uri"));
5573
+ const registeredUris = client.redirectUris ?? [];
5574
+ let isValidRedirectUri = false;
5575
+ if (query.redirect_uri) {
5576
+ const defaultResult = Boolean(findRegisteredRedirectUri(registeredUris, query.redirect_uri));
5577
+ if (opts.validateRedirectUri && isSafeCustomRedirectUri(query.redirect_uri)) try {
5578
+ isValidRedirectUri = await opts.validateRedirectUri(query.redirect_uri, registeredUris, defaultResult);
5579
+ } catch {
5580
+ isValidRedirectUri = false;
5581
+ }
5582
+ else if (!opts.validateRedirectUri) isValidRedirectUri = defaultResult;
5583
+ }
5584
+ if (!isValidRedirectUri) return handleRedirect(ctx, getErrorURL(ctx, "invalid_redirect", "invalid redirect uri"));
5556
5585
  let requestedScopes = query.scope?.split(" ").filter((s) => s);
5557
5586
  if (requestedScopes) {
5558
5587
  const validScopes = new Set(client.scopes ?? opts.scopes);
@@ -1,4 +1,4 @@
1
- import { c as ResourceServerMetadata } from "./oauth-1Ud-hvZY.mjs";
1
+ import { c as ResourceServerMetadata } from "./oauth-C_7TvkRL.mjs";
2
2
  import { ResourceRequestInput, VerifyAccessTokenRequestOptions } from "better-auth/oauth2";
3
3
  import { JWTPayload, JWTVerifyOptions } from "jose";
4
4
  import { BetterAuthOptions } from "better-auth/types";
@@ -1,5 +1,5 @@
1
- import { o as getJwtPlugin, s as getOAuthProviderPlugin } from "./utils-CoqjzHuU.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-9KCSx144.mjs";
1
+ import { o as getJwtPlugin, s as getOAuthProviderPlugin } from "./utils-D6Hp4Qd_.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-C2j2jEFL.mjs";
3
3
  import { t as createResourceServerChallenge } from "./resource-challenge-Damwi0Or.mjs";
4
4
  import { APIError } from "better-call";
5
5
  import { BetterAuthError } from "@better-auth/core/error";
package/dist/client.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { p as oauthDeviceAuthorization, r as oauthProvider } from "./oauth-CJ85_W0W.mjs";
1
+ import { p as oauthDeviceAuthorization, r as oauthProvider } from "./oauth-Dtt-caL2.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,5 +1,5 @@
1
1
  import { t as buildSignedOAuthQuery } from "./signed-query-Df1MNiSH.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-9KCSx144.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-C2j2jEFL.mjs";
3
3
  import { safeJSONParse } from "@better-auth/core/utils/json";
4
4
  import { deviceAuthorizationClient } from "better-auth/client/plugins";
5
5
  //#region src/client.ts
package/dist/index.d.mts CHANGED
@@ -1,10 +1,9 @@
1
- import { A as OAuthOpaqueAccessToken, B as Prompt, C as OAuthClientAuthenticationStrategy, D as OAuthExtensionGrantHandler, E as OAuthConsent, F as OAuthResource, G as VerificationValue, H as Scope, I as OAuthResourceInput, J as ResourceUriSchema, K as ClientRegistrationRequest, L as OAuthTokenIssueParams, M as OAuthProviderApi, N as OAuthProviderExtension, O as OAuthExtensionGrantHandlerInput, P as OAuthRefreshToken, R as OAuthTokenResponse, S as OAuthClientAuthenticationResult, T as OAuthClientResource, U as StoreTokenType, V as SchemaClient, W as StoredAuthorizationQuery, Y as oauthClientMetadataSchema, _ as OAuthAuthorizationQuery, a as GrantType, b as OAuthClientAuthenticationInput, c as ResourceServerMetadata, d as ActiveAccessTokenPayload, f as AuthorizePrompt, g as OAuthAuthenticatedClient, h as InitialAccessTokenAuthorization, i as Confirmation, j as OAuthOptions, k as OAuthMetadataExtensionInput, l as TokenEndpointAuthMethod, m as ClientMetadataResourceFetch, n as AuthServerMetadata, o as OAuthClient, p as ClientDiscovery, q as OAuthClientMetadata, r as BearerMethodsSupported, s as OIDCMetadata, t as AuthMethod, u as TokenType, v as OAuthClaimExtensionInput, w as OAuthClientRegistrationResponse, x as OAuthClientAuthenticationRequest, y as OAuthClientAdministrativeResponse, z as OAuthUserInfoExtensionInput } from "./oauth-1Ud-hvZY.mjs";
2
- import { a as OAuthEndpointErrorResult, c as OAuthFieldErrorCode, d as DEVICE_CODE_GRANT_TYPE, f as OAuthDeviceAuthorizationOptions, i as getIssuer, l as OAuthFieldErrorCodeMap, n as getOAuthProviderState, o as OAuthEndpointRedirectContext, p as oauthDeviceAuthorization, r as oauthProvider, s as OAuthErrorCode, t as DEFAULT_OAUTH_SCOPES, u as OAuthRedirectOnError } from "./oauth-CJ85_W0W.mjs";
1
+ import { A as OAuthOpaqueAccessToken, B as Prompt, C as OAuthClientAuthenticationStrategy, D as OAuthExtensionGrantHandler, E as OAuthConsent, F as OAuthResource, G as VerificationValue, H as Scope, I as OAuthResourceInput, J as ResourceUriSchema, K as ClientRegistrationRequest, L as OAuthTokenIssueParams, M as OAuthProviderApi, N as OAuthProviderExtension, O as OAuthExtensionGrantHandlerInput, P as OAuthRefreshToken, R as OAuthTokenResponse, S as OAuthClientAuthenticationResult, T as OAuthClientResource, U as StoreTokenType, V as SchemaClient, W as StoredAuthorizationQuery, Y as oauthClientMetadataSchema, _ as OAuthAuthorizationQuery, a as GrantType, b as OAuthClientAuthenticationInput, c as ResourceServerMetadata, d as ActiveAccessTokenPayload, f as AuthorizePrompt, g as OAuthAuthenticatedClient, h as InitialAccessTokenAuthorization, i as Confirmation, j as OAuthOptions, k as OAuthMetadataExtensionInput, l as TokenEndpointAuthMethod, m as ClientMetadataResourceFetch, n as AuthServerMetadata, o as OAuthClient, p as ClientDiscovery, q as OAuthClientMetadata, r as BearerMethodsSupported, s as OIDCMetadata, t as AuthMethod, u as TokenType, v as OAuthClaimExtensionInput, w as OAuthClientRegistrationResponse, x as OAuthClientAuthenticationRequest, y as OAuthClientAdministrativeResponse, z as OAuthUserInfoExtensionInput } from "./oauth-C_7TvkRL.mjs";
2
+ import { a as OAuthEndpointErrorResult, c as OAuthFieldErrorCode, d as DEVICE_CODE_GRANT_TYPE, f as OAuthDeviceAuthorizationOptions, i as getIssuer, l as OAuthFieldErrorCodeMap, n as getOAuthProviderState, o as OAuthEndpointRedirectContext, p as oauthDeviceAuthorization, r as oauthProvider, s as OAuthErrorCode, t as DEFAULT_OAUTH_SCOPES, u as OAuthRedirectOnError } from "./oauth-Dtt-caL2.mjs";
3
3
  import { APIError } from "better-call";
4
4
  import { JWSAlgorithms, JwtOptions } from "better-auth/plugins";
5
5
  import { AuthContext, GenericEndpointContext } from "@better-auth/core";
6
6
  import * as _$better_auth0 from "better-auth";
7
-
8
7
  //#region src/extensions.d.ts
9
8
  /**
10
9
  * Registers an {@link OAuthProviderExtension} with the OAuth Provider plugin
@@ -160,6 +159,14 @@ declare function createResourceServerChallenge(error: unknown, resource: string
160
159
  */
161
160
  declare function getOAuthProviderApi(ctx: GenericEndpointContext, opts: OAuthOptions<Scope[]>, grantType?: GrantType): OAuthProviderApi;
162
161
  //#endregion
162
+ //#region src/utils/index.d.ts
163
+ /**
164
+ * Verify the signature and expiration of an OAuth query issued by this provider.
165
+ * Use the provider's current auth secret on the server before displaying a
166
+ * consent page. A valid signature does not replace client or session checks.
167
+ */
168
+ declare function verifyOAuthQueryParams(oauth_query: string, secret: string): Promise<boolean>;
169
+ //#endregion
163
170
  //#region src/utils/client-assertion.d.ts
164
171
  /**
165
172
  * Enforces the assertion-hygiene claims every client-assertion authentication
@@ -193,4 +200,4 @@ declare function consumeClientAssertion(ctx: GenericEndpointContext, opts: OAuth
193
200
  expectedAudience: string;
194
201
  }): Promise<void>;
195
202
  //#endregion
196
- export { ActiveAccessTokenPayload, AuthMethod, AuthServerMetadata, AuthorizePrompt, BearerMethodsSupported, ClientDiscovery, ClientMetadataResourceFetch, ClientRegistrationRequest, Confirmation, DEFAULT_OAUTH_SCOPES, DEVICE_CODE_GRANT_TYPE, GrantType, InitialAccessTokenAuthorization, OAuthAuthenticatedClient, OAuthAuthorizationQuery, OAuthClaimExtensionInput, type OAuthClient, OAuthClientAdministrativeResponse, OAuthClientAuthenticationInput, OAuthClientAuthenticationRequest, OAuthClientAuthenticationResult, OAuthClientAuthenticationStrategy, type OAuthClientMetadata, OAuthClientRegistrationResponse, OAuthClientResource, OAuthConsent, type OAuthDeviceAuthorizationOptions, type OAuthEndpointErrorResult, type OAuthEndpointRedirectContext, type OAuthErrorCode, OAuthExtensionGrantHandler, OAuthExtensionGrantHandlerInput, type OAuthFieldErrorCode, type OAuthFieldErrorCodeMap, OAuthMetadataExtensionInput, OAuthOpaqueAccessToken, OAuthOptions, OAuthProviderApi, OAuthProviderExtension, type OAuthRedirectOnError, OAuthRefreshToken, OAuthResource, OAuthResourceInput, OAuthTokenIssueParams, OAuthTokenResponse, OAuthUserInfoExtensionInput, OIDCMetadata, Prompt, type ResourceServerMetadata, ResourceUriSchema, SchemaClient, Scope, StoreTokenType, StoredAuthorizationQuery, TokenEndpointAuthMethod, TokenType, VerificationValue, authServerMetadata, consumeClientAssertion, createResourceServerChallenge, extendOAuthProvider, getIssuer, getOAuthProviderApi, getOAuthProviderState, metadataResponse, oauthAuthorizationServerMetadata, oauthClientMetadataSchema, oauthDeviceAuthorization, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
203
+ export { ActiveAccessTokenPayload, AuthMethod, AuthServerMetadata, AuthorizePrompt, BearerMethodsSupported, ClientDiscovery, ClientMetadataResourceFetch, ClientRegistrationRequest, Confirmation, DEFAULT_OAUTH_SCOPES, DEVICE_CODE_GRANT_TYPE, GrantType, InitialAccessTokenAuthorization, OAuthAuthenticatedClient, OAuthAuthorizationQuery, OAuthClaimExtensionInput, type OAuthClient, OAuthClientAdministrativeResponse, OAuthClientAuthenticationInput, OAuthClientAuthenticationRequest, OAuthClientAuthenticationResult, OAuthClientAuthenticationStrategy, type OAuthClientMetadata, OAuthClientRegistrationResponse, OAuthClientResource, OAuthConsent, type OAuthDeviceAuthorizationOptions, type OAuthEndpointErrorResult, type OAuthEndpointRedirectContext, type OAuthErrorCode, OAuthExtensionGrantHandler, OAuthExtensionGrantHandlerInput, type OAuthFieldErrorCode, type OAuthFieldErrorCodeMap, OAuthMetadataExtensionInput, OAuthOpaqueAccessToken, OAuthOptions, OAuthProviderApi, OAuthProviderExtension, type OAuthRedirectOnError, OAuthRefreshToken, OAuthResource, OAuthResourceInput, OAuthTokenIssueParams, OAuthTokenResponse, OAuthUserInfoExtensionInput, OIDCMetadata, Prompt, type ResourceServerMetadata, ResourceUriSchema, SchemaClient, Scope, StoreTokenType, StoredAuthorizationQuery, TokenEndpointAuthMethod, TokenType, VerificationValue, authServerMetadata, consumeClientAssertion, createResourceServerChallenge, extendOAuthProvider, getIssuer, getOAuthProviderApi, getOAuthProviderState, metadataResponse, oauthAuthorizationServerMetadata, oauthClientMetadataSchema, oauthDeviceAuthorization, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata, verifyOAuthQueryParams };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import { C as resolveResourcePolicy, c as ResourceUriSchema, i as getOAuthProviderApi, p as oauthClientMetadataSchema, v as extractRepeatedResourceFromForm } from "./introspect-CbYi2MJT.mjs";
2
- import { D as validateClientScopes, N as extendOAuthProvider, T as toResourceList, a as getClient, f as normalizeClientAuthenticationParameters, s as getOAuthProviderPlugin, w as toAudienceClaim } from "./utils-CoqjzHuU.mjs";
3
- import { d as metadataResponse, f as oauthAuthorizationServerMetadata, h as oidcServerMetadata, i as oauthProvider, m as oauthProviderOpenIdConfigMetadata, n as DEFAULT_OAUTH_SCOPES, p as oauthProviderAuthServerMetadata, r as getOAuthProviderState, s as consumeClientAssertion, t as getIssuer, u as authServerMetadata } from "./authorize-CLuqtSXQ.mjs";
1
+ import { C as resolveResourcePolicy, c as ResourceUriSchema, i as getOAuthProviderApi, p as oauthClientMetadataSchema, v as extractRepeatedResourceFromForm } from "./introspect-CNR06Oy3.mjs";
2
+ import { D as validateClientScopes, N as extendOAuthProvider, O as verifyOAuthQueryParams, T as toResourceList, a as getClient, f as normalizeClientAuthenticationParameters, s as getOAuthProviderPlugin, w as toAudienceClaim } from "./utils-D6Hp4Qd_.mjs";
3
+ import { d as metadataResponse, f as oauthAuthorizationServerMetadata, h as oidcServerMetadata, i as oauthProvider, m as oauthProviderOpenIdConfigMetadata, n as DEFAULT_OAUTH_SCOPES, p as oauthProviderAuthServerMetadata, r as getOAuthProviderState, s as consumeClientAssertion, t as getIssuer, u as authServerMetadata } from "./authorize-K1WHCNih.mjs";
4
4
  import { t as createResourceServerChallenge } from "./resource-challenge-Damwi0Or.mjs";
5
5
  import { APIError } from "better-auth/api";
6
6
  import * as z from "zod";
@@ -228,4 +228,4 @@ function oauthDeviceAuthorization(options = {}) {
228
228
  };
229
229
  }
230
230
  //#endregion
231
- export { DEFAULT_OAUTH_SCOPES, DEVICE_CODE_GRANT_TYPE, ResourceUriSchema, authServerMetadata, consumeClientAssertion, createResourceServerChallenge, extendOAuthProvider, getIssuer, getOAuthProviderApi, getOAuthProviderState, metadataResponse, oauthAuthorizationServerMetadata, oauthClientMetadataSchema, oauthDeviceAuthorization, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata };
231
+ export { DEFAULT_OAUTH_SCOPES, DEVICE_CODE_GRANT_TYPE, ResourceUriSchema, authServerMetadata, consumeClientAssertion, createResourceServerChallenge, extendOAuthProvider, getIssuer, getOAuthProviderApi, getOAuthProviderState, metadataResponse, oauthAuthorizationServerMetadata, oauthClientMetadataSchema, oauthDeviceAuthorization, oauthProvider, oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oidcServerMetadata, verifyOAuthQueryParams };
@@ -1,4 +1,4 @@
1
- import { H as Scope, V as SchemaClient, j as OAuthOptions, o as OAuthClient } from "./oauth-1Ud-hvZY.mjs";
1
+ import { H as Scope, V as SchemaClient, j as OAuthOptions, o as OAuthClient } from "./oauth-C_7TvkRL.mjs";
2
2
  import { JSONWebKeySet } from "jose";
3
3
  import { GenericEndpointContext } from "@better-auth/core";
4
4
 
package/dist/internal.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as registerClientMetadataDocument, c as isForbiddenCimdClientMetadataField, l as validatePublicClientJwks } from "./authorize-CLuqtSXQ.mjs";
1
+ import { a as registerClientMetadataDocument, c as isForbiddenCimdClientMetadataField, l as validatePublicClientJwks } from "./authorize-K1WHCNih.mjs";
2
2
  export { isForbiddenCimdClientMetadataField, registerClientMetadataDocument, validatePublicClientJwks };
@@ -1,5 +1,5 @@
1
1
  import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs";
2
- import { A as collectExtensionAccessTokenClaims, C as storeToken, E as validateClientCredentials, F as getExtensionGrantHandler, L as getSupportedGrantTypes, M as collectExtensionUserInfoClaims, R as hasUserInfoClaimExtension, T as toResourceList, a as getClient, b as resolveSubjectIdentifier, c as getStoredToken, h as parseClientMetadata, i as extractClientCredentials, j as collectExtensionIdTokenClaims, l as isPKCERequired, n as decryptStoredClientSecret, o as getJwtPlugin, p as normalizeTimestampValue, r as destructureCredentials, t as clientAllowsGrant, w as toAudienceClaim, y as resolveSessionAuthTime } from "./utils-CoqjzHuU.mjs";
2
+ import { A as collectExtensionAccessTokenClaims, C as storeToken, E as validateClientCredentials, F as getExtensionGrantHandler, L as getSupportedGrantTypes, M as collectExtensionUserInfoClaims, R as hasUserInfoClaimExtension, T as toResourceList, a as getClient, b as resolveSubjectIdentifier, c as getStoredToken, h as parseClientMetadata, i as extractClientCredentials, j as collectExtensionIdTokenClaims, l as isPKCERequired, n as decryptStoredClientSecret, o as getJwtPlugin, p as normalizeTimestampValue, r as destructureCredentials, t as clientAllowsGrant, w as toAudienceClaim, y as resolveSessionAuthTime } from "./utils-D6Hp4Qd_.mjs";
3
3
  import { APIError } from "better-auth/api";
4
4
  import { generateRandomString, symmetricDecrypt, symmetricEncrypt } from "better-auth/crypto";
5
5
  import { APIError as APIError$1 } from "better-call";
@@ -1091,6 +1091,58 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1091
1091
  * ```
1092
1092
  */
1093
1093
  scopes?: Scopes;
1094
+ /**
1095
+ * Validates an OAuth authorization request's redirect URI. Without this
1096
+ * option, the URI must match one registered for the client, except that
1097
+ * a registered native HTTP loopback URI may use a different port.
1098
+ *
1099
+ * The callback runs for every client and also controls whether early
1100
+ * authorization errors may be sent to the requested URI. Returning `true`
1101
+ * accepts the URI even when `defaultResult` is `false`; returning `false`
1102
+ * or throwing rejects it. Client registration is unchanged.
1103
+ *
1104
+ * The preview example assumes only trusted clients can register its
1105
+ * production callback URI.
1106
+ *
1107
+ * @example
1108
+ * ```ts
1109
+ * oauthProvider({
1110
+ * validateRedirectUri: (uri, registeredUris, defaultResult) => {
1111
+ * if (defaultResult) return true;
1112
+ * if (!registeredUris.includes("https://app.example.com/api/auth/callback")) {
1113
+ * return false;
1114
+ * }
1115
+ * if (uri.includes("#")) return false;
1116
+ * try {
1117
+ * const url = new URL(uri);
1118
+ * return (
1119
+ * url.protocol === "https:" &&
1120
+ * url.username === "" &&
1121
+ * url.password === "" &&
1122
+ * url.hostname.endsWith(".preview.example.com") &&
1123
+ * url.port === "" &&
1124
+ * url.pathname === "/api/auth/callback" &&
1125
+ * url.search === ""
1126
+ * );
1127
+ * } catch {
1128
+ * return false;
1129
+ * }
1130
+ * },
1131
+ * })
1132
+ * ```
1133
+ *
1134
+ * Custom acceptance relaxes the exact matching required by RFC 9700 §2.1.
1135
+ * Accept only callback hosts you control. For pairwise subject identifiers,
1136
+ * custom-validated URIs use the sector of the client's first registered URI.
1137
+ *
1138
+ * @see https://www.better-auth.com/docs/plugins/oauth-provider#custom-redirect-uri-validation
1139
+ *
1140
+ * @param redirectUri - The redirect_uri from the authorization request
1141
+ * @param registeredUris - Registered redirect URIs for the client
1142
+ * @param defaultResult - Result of built-in redirect URI matching
1143
+ * @returns `true` to accept the URI, or `false` to reject it
1144
+ */
1145
+ validateRedirectUri?: (redirectUri: string, registeredUris: readonly string[], defaultResult: boolean) => Awaitable<boolean>;
1094
1146
  /**
1095
1147
  * Protected resources the AS issues access tokens for. Promotes the
1096
1148
  * resource model into a first-class persisted entity with per-resource
@@ -1732,7 +1784,7 @@ interface OAuthOptions<Scopes extends readonly Scope[] = InternallySupportedScop
1732
1784
  }) => Awaitable<Record<string, unknown>>;
1733
1785
  /**
1734
1786
  * Overwrite specific /.well-known/openid-configuration
1735
- * values so they are not available publically.
1787
+ * values so they are not available publicly.
1736
1788
  * This may be important if not all clients need specific scopes.
1737
1789
  */
1738
1790
  advertisedMetadata?: {
@@ -1,4 +1,4 @@
1
- import { B as Prompt, E as OAuthConsent, F as OAuthResource, H as Scope, O as OAuthExtensionGrantHandlerInput, R as OAuthTokenResponse, a as GrantType, j as OAuthOptions, k as OAuthMetadataExtensionInput, l as TokenEndpointAuthMethod, n as AuthServerMetadata, o as OAuthClient, u as TokenType, w as OAuthClientRegistrationResponse, y as OAuthClientAdministrativeResponse } from "./oauth-1Ud-hvZY.mjs";
1
+ import { B as Prompt, E as OAuthConsent, F as OAuthResource, H as Scope, O as OAuthExtensionGrantHandlerInput, R as OAuthTokenResponse, a as GrantType, j as OAuthOptions, k as OAuthMetadataExtensionInput, l as TokenEndpointAuthMethod, n as AuthServerMetadata, o as OAuthClient, u as TokenType, w as OAuthClientRegistrationResponse, y as OAuthClientAdministrativeResponse } from "./oauth-C_7TvkRL.mjs";
2
2
  import * as _$better_call0 from "better-call";
3
3
  import * as z from "zod";
4
4
  import * as _$jose from "jose";
@@ -356,6 +356,11 @@ function getTrustedClientCache(options) {
356
356
  trustedClientCaches.set(options, cache);
357
357
  return cache;
358
358
  }
359
+ /**
360
+ * Verify the signature and expiration of an OAuth query issued by this provider.
361
+ * Use the provider's current auth secret on the server before displaying a
362
+ * consent page. A valid signature does not replace client or session checks.
363
+ */
359
364
  async function verifyOAuthQueryParams(oauth_query, secret) {
360
365
  const queryParams = new URLSearchParams(oauth_query);
361
366
  const sig = queryParams.get("sig");
@@ -707,7 +712,7 @@ async function extractClientCredentials(ctx, opts, expectedAudience) {
707
712
  confirmation: result.confirmation
708
713
  };
709
714
  }
710
- const { verifyClientAssertion: verify } = await import("./authorize-CLuqtSXQ.mjs").then((n) => n.o);
715
+ const { verifyClientAssertion: verify } = await import("./authorize-K1WHCNih.mjs").then((n) => n.o);
711
716
  return {
712
717
  kind: "pre_verified",
713
718
  method: "private_key_jwt",
@@ -1,5 +1,5 @@
1
1
  //#endregion
2
2
  //#region src/version.ts
3
- const PACKAGE_VERSION = "1.7.6";
3
+ const PACKAGE_VERSION = "1.7.7";
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.6",
3
+ "version": "1.7.7",
4
4
  "description": "An oauth provider plugin for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -71,16 +71,16 @@
71
71
  "devDependencies": {
72
72
  "listhen": "^1.9.0",
73
73
  "tsdown": "0.21.10",
74
- "@better-auth/core": "1.7.6",
75
- "@better-auth/memory-adapter": "1.7.6",
76
- "better-auth": "1.7.6"
74
+ "@better-auth/core": "1.7.7",
75
+ "@better-auth/memory-adapter": "1.7.7",
76
+ "better-auth": "1.7.7"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "@better-auth/utils": "0.4.2",
80
80
  "@better-fetch/fetch": "1.3.2",
81
81
  "better-call": "1.4.0",
82
- "@better-auth/core": "^1.7.6",
83
- "better-auth": "^1.7.6"
82
+ "@better-auth/core": "^1.7.7",
83
+ "better-auth": "^1.7.7"
84
84
  },
85
85
  "scripts": {
86
86
  "build": "tsdown",