@better-auth/oauth-provider 1.7.1 → 1.7.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,10 +1,11 @@
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-6ew7sakf.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-B77ebneW.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-CbhhXT0E.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-oOcdCCVw.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-DWXDeMXU.mjs";
5
+ import { t as PACKAGE_VERSION } from "./version-dywjHxve.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
+ import { appendQueryParams } from "@better-auth/core/utils/url";
8
9
  import { APIError, NO_STORE_HEADERS, addOAuthServerContext, createAuthEndpoint, createAuthMiddleware, dispatchAuthEndpoint, getOAuthState, getSessionFromCtx, sessionMiddleware } from "better-auth/api";
9
10
  import { generateRandomString, makeSignature } from "better-auth/crypto";
10
11
  import { APIError as APIError$1 } from "better-call";
@@ -1776,7 +1777,12 @@ async function checkOAuthClient(client, opts, settings) {
1776
1777
  });
1777
1778
  for (const uri of clientWithDefaults.redirect_uris ?? []) validateClientRedirectUri(uri, applicationType ?? (isClientMetadataDocument ? "native" : "web"));
1778
1779
  const supportedGrantTypes = new Set(getSupportedGrantTypes(opts));
1779
- for (const grantType of grantTypes) if (!supportedGrantTypes.has(grantType)) throw new APIError("BAD_REQUEST", {
1780
+ if (isClientMetadataDocument) {
1781
+ if (!grantTypes.some((grantType) => supportedGrantTypes.has(grantType))) throw new APIError("BAD_REQUEST", {
1782
+ error: "invalid_client_metadata",
1783
+ error_description: `no mutually supported grant_type among ${grantTypes.join(", ")}`
1784
+ });
1785
+ } else for (const grantType of grantTypes) if (!supportedGrantTypes.has(grantType)) throw new APIError("BAD_REQUEST", {
1780
1786
  error: "invalid_client_metadata",
1781
1787
  error_description: `unsupported grant_type ${grantType}`
1782
1788
  });
@@ -5288,7 +5294,7 @@ function formatErrorURL(url, error, description, state, iss, mode = "query") {
5288
5294
  state && searchParams.append("state", state);
5289
5295
  iss && searchParams.append("iss", iss);
5290
5296
  if (mode === "fragment") return `${url}#${searchParams.toString()}`;
5291
- return `${url}${url.includes("?") ? "&" : "?"}${searchParams.toString()}`;
5297
+ return appendQueryParams(url, searchParams);
5292
5298
  }
5293
5299
  /**
5294
5300
  * Selects the response mode for an error redirect to the RP. OIDC Core 1.0 §5
@@ -5373,26 +5379,70 @@ function getErrorURL(ctx, error, description) {
5373
5379
  return formatErrorURL(ctx.context.options.onAPIError?.errorURL || `${ctx.context.baseURL}/error`, error, description);
5374
5380
  }
5375
5381
  /**
5376
- * Finds the matching entry in a client's registered redirect_uris for a
5377
- * requested redirect_uri. Honors RFC 8252 §7.3 loopback port variance for
5378
- * the full 127.0.0.0/8 range and [::1], matching on scheme+host+path+query
5379
- * and ignoring port. DNS names like "localhost" are excluded per §8.3.
5382
+ * Based on the loopback port matching approach in node-oidc-provider.
5383
+ *
5384
+ * @see https://github.com/panva/node-oidc-provider/blob/ea1456f987de7750b6af8a89a1881e70c70827fe/lib/models/client.js#L36-L76
5385
+ */
5386
+ function stripLoopbackRedirectPort(uri) {
5387
+ let parsed;
5388
+ try {
5389
+ parsed = new URL(uri);
5390
+ } catch {
5391
+ return;
5392
+ }
5393
+ const isLoopback = isLoopbackIP(parsed.hostname) || parsed.hostname === "localhost";
5394
+ if (parsed.protocol !== "http:" || !isLoopback) return;
5395
+ const schemeSeparatorIndex = uri.indexOf("://");
5396
+ if (schemeSeparatorIndex < 0) return void 0;
5397
+ const authorityStart = schemeSeparatorIndex + 3;
5398
+ const authorityEndOffset = uri.slice(authorityStart).search(/[/?#]/u);
5399
+ let authorityEnd = uri.length;
5400
+ if (authorityEndOffset >= 0) authorityEnd = authorityStart + authorityEndOffset;
5401
+ const authority = uri.slice(authorityStart, authorityEnd);
5402
+ let portStart;
5403
+ if (authority.startsWith("[")) {
5404
+ const closingBracket = authority.indexOf("]");
5405
+ if (closingBracket < 0) return void 0;
5406
+ if (authority[closingBracket + 1] !== ":") return uri;
5407
+ portStart = closingBracket + 1;
5408
+ } else {
5409
+ portStart = authority.lastIndexOf(":");
5410
+ if (portStart < 0) return uri;
5411
+ }
5412
+ const port = authority.slice(portStart + 1);
5413
+ if (!/^\d*$/u.test(port)) return;
5414
+ const portStartInUri = authorityStart + portStart;
5415
+ return `${uri.slice(0, portStartInUri)}${uri.slice(authorityEnd)}`;
5416
+ }
5417
+ /**
5418
+ * Finds the matching entry in a client's registered redirect URIs.
5419
+ *
5420
+ * Registration limits loopback redirects to native-compatible HTTP forms.
5421
+ * Within that boundary, only the port may vary; every other character must
5422
+ * match the registered URI.
5423
+ *
5424
+ * @see https://www.rfc-editor.org/rfc/rfc9700.html#section-4.1.3
5425
+ * @see https://www.rfc-editor.org/rfc/rfc8252.html#section-8.3
5380
5426
  */
5381
5427
  function findRegisteredRedirectUri(registered, requested) {
5382
5428
  if (!registered || !requested) return void 0;
5383
- let req;
5429
+ let requestedUrl;
5384
5430
  try {
5385
- req = new URL(requested);
5386
- } catch {}
5431
+ requestedUrl = new URL(requested);
5432
+ } catch {
5433
+ return;
5434
+ }
5435
+ /**
5436
+ * A trailing `#` yields an empty `URL.hash` but still defines a fragment.
5437
+ */
5438
+ const hasFragment = requested.includes("#");
5439
+ const hasUserinfo = requestedUrl.username.length > 0 || requestedUrl.password.length > 0;
5440
+ if (hasFragment || hasUserinfo) return;
5441
+ const requestedWithoutPort = stripLoopbackRedirectPort(requested);
5387
5442
  return registered.find((url) => {
5388
5443
  if (url === requested) return true;
5389
- if (!req) return false;
5390
- try {
5391
- const reg = new URL(url);
5392
- return isLoopbackIP(reg.hostname) && reg.hostname === req.hostname && reg.pathname === req.pathname && reg.protocol === req.protocol && reg.search === req.search;
5393
- } catch {
5394
- return false;
5395
- }
5444
+ if (!requestedWithoutPort) return false;
5445
+ return stripLoopbackRedirectPort(url) === requestedWithoutPort;
5396
5446
  });
5397
5447
  }
5398
5448
  /**
@@ -1,5 +1,5 @@
1
- import { o as getJwtPlugin, s as getOAuthProviderPlugin } from "./utils-B77ebneW.mjs";
2
- import { t as PACKAGE_VERSION } from "./version-DWXDeMXU.mjs";
1
+ import { o as getJwtPlugin, s as getOAuthProviderPlugin } from "./utils-oOcdCCVw.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-dywjHxve.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.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-DWXDeMXU.mjs";
2
+ import { t as PACKAGE_VERSION } from "./version-dywjHxve.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.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-6ew7sakf.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-B77ebneW.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-Crqw4_bR.mjs";
1
+ import { C as resolveResourcePolicy, c as ResourceUriSchema, i as getOAuthProviderApi, p as oauthClientMetadataSchema, v as extractRepeatedResourceFromForm } from "./introspect-CbhhXT0E.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-oOcdCCVw.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-9whjxVLJ.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";
package/dist/internal.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { a as registerClientMetadataDocument, c as isForbiddenCimdClientMetadataField, l as validatePublicClientJwks } from "./authorize-Crqw4_bR.mjs";
1
+ import { a as registerClientMetadataDocument, c as isForbiddenCimdClientMetadataField, l as validatePublicClientJwks } from "./authorize-9whjxVLJ.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-B77ebneW.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-oOcdCCVw.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";
@@ -707,7 +707,7 @@ async function extractClientCredentials(ctx, opts, expectedAudience) {
707
707
  confirmation: result.confirmation
708
708
  };
709
709
  }
710
- const { verifyClientAssertion: verify } = await import("./authorize-Crqw4_bR.mjs").then((n) => n.o);
710
+ const { verifyClientAssertion: verify } = await import("./authorize-9whjxVLJ.mjs").then((n) => n.o);
711
711
  return {
712
712
  kind: "pre_verified",
713
713
  method: "private_key_jwt",
@@ -1,5 +1,5 @@
1
1
  //#endregion
2
2
  //#region src/version.ts
3
- const PACKAGE_VERSION = "1.7.1";
3
+ const PACKAGE_VERSION = "1.7.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.1",
3
+ "version": "1.7.3",
4
4
  "description": "An oauth provider plugin for Better Auth",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -66,21 +66,21 @@
66
66
  },
67
67
  "dependencies": {
68
68
  "jose": "^6.2.3",
69
- "zod": "^4.3.6"
69
+ "zod": "^4.5.4"
70
70
  },
71
71
  "devDependencies": {
72
72
  "listhen": "^1.9.0",
73
73
  "tsdown": "0.21.10",
74
- "@better-auth/core": "1.7.1",
75
- "@better-auth/memory-adapter": "1.7.1",
76
- "better-auth": "1.7.1"
74
+ "@better-auth/core": "1.7.3",
75
+ "@better-auth/memory-adapter": "1.7.3",
76
+ "better-auth": "1.7.3"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "@better-auth/utils": "0.4.2",
80
80
  "@better-fetch/fetch": "1.3.1",
81
81
  "better-call": "1.4.0",
82
- "better-auth": "^1.7.1",
83
- "@better-auth/core": "^1.7.1"
82
+ "@better-auth/core": "^1.7.3",
83
+ "better-auth": "^1.7.3"
84
84
  },
85
85
  "scripts": {
86
86
  "build": "tsdown",