[PR #9120] [MERGED] chore: release v1.7.0-beta.1 #25352

Closed
opened 2026-04-15 22:50:58 -05:00 by GiteaMirror · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/better-auth/better-auth/pull/9120
Author: @better-release[bot]
Created: 4/11/2026
Status: Merged
Merged: 4/14/2026
Merged by: @gustavovalverde

Base: nextHead: changeset-release/next


📝 Commits (1)

📊 Changes

41 files changed (+367 additions, -20 deletions)

View changed files

📝 .changeset/pre.json (+12 -0)
📝 packages/api-key/CHANGELOG.md (+8 -0)
📝 packages/api-key/package.json (+1 -1)
📝 packages/better-auth/CHANGELOG.md (+60 -0)
📝 packages/better-auth/package.json (+1 -1)
📝 packages/cli/CHANGELOG.md (+9 -0)
📝 packages/cli/package.json (+1 -1)
📝 packages/core/CHANGELOG.md (+2 -0)
📝 packages/core/package.json (+1 -1)
📝 packages/drizzle-adapter/CHANGELOG.md (+7 -0)
📝 packages/drizzle-adapter/package.json (+1 -1)
📝 packages/electron/CHANGELOG.md (+22 -0)
📝 packages/electron/package.json (+1 -1)
📝 packages/expo/CHANGELOG.md (+22 -0)
📝 packages/expo/package.json (+1 -1)
📝 packages/i18n/CHANGELOG.md (+8 -0)
📝 packages/i18n/package.json (+1 -1)
📝 packages/kysely-adapter/CHANGELOG.md (+7 -0)
📝 packages/kysely-adapter/package.json (+1 -1)
📝 packages/memory-adapter/CHANGELOG.md (+7 -0)

...and 21 more files

📄 Description

This PR was opened by the Changesets release GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated.

⚠️⚠️⚠️⚠️⚠️⚠️

next is currently in pre mode so this branch has prereleases rather than normal releases. If you want to exit prereleases, run changeset pre exit on next.

⚠️⚠️⚠️⚠️⚠️⚠️

Releases

better-auth@1.7.0-beta.1

Minor Changes

  • #9069 c7d2253 Thanks @gustavovalverde! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use signIn.social + callback/:id instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with openid scope injection, and typed provider IDs.

    Breaking changes:

    • signIn.oauth2({ providerId }) replaced by signIn.social({ provider })
    • oauth2.link() replaced by linkSocial()
    • Callback URL changed from /api/auth/oauth2/callback/:id to /api/auth/callback/:id
    • genericOAuthClient() deprecated (no longer needed)
    • pkce defaults to true (was false); set pkce: false for providers that reject PKCE
    • authorizationUrlParams and tokenUrlParams only accept Record<string, string>
    • issuer and requireIssuerValidation config fields removed; issuer validation is automatic via OIDC discovery
    • mapProfileToUser profile typed as OAuth2UserInfo & Record<string, unknown>
  • #9079 6f2948e Thanks @gustavovalverde! - feat(oauth-provider): compute at_hash in ID tokens per OIDC Core §3.1.3.6

    ID tokens issued alongside an access token now include the at_hash claim, which cryptographically binds the two tokens to prevent token substitution attacks. The hash algorithm is selected based on the actual signing key's algorithm (EdDSA/Ed25519 uses SHA-512, RS/ES/PS384 uses SHA-384, RS/ES/PS512 uses SHA-512, all others use SHA-256).

    A new resolveSigningKey() export is available from better-auth/plugins to resolve the current JWKS signing key (including its algorithm). When using a custom jwt.sign callback, the signed ID token's header is validated against the declared algorithm to prevent at_hash mismatches.

Patch Changes

  • #9131 5142e9c Thanks @gustavovalverde! - harden dynamic baseURL handling for direct auth.api.* calls and plugin metadata helpers

    Direct auth.api.* calls

    • Throw APIError with a clear message when the baseURL can't be resolved (no source and no fallback), instead of leaving ctx.context.baseURL = "" for downstream plugins to crash on.
    • Convert allowedHosts mismatches on the direct-API path to APIError.
    • Honor advanced.trustedProxyHeaders on the dynamic path (default true, unchanged). Previously x-forwarded-host / -proto were unconditionally trusted with allowedHosts; they now go through the same gate as the static path. The default flip to false ships in a follow-up PR.
    • resolveRequestContext rehydrates trustedProviders and cookies per call (in addition to trustedOrigins). User-defined trustedOrigins(req) / trustedProviders(req) callbacks receive a Request synthesized from forwarded headers when no full Request is available.
    • Infer http for loopback hosts (localhost, 127.0.0.1, [::1], 0.0.0.0) on the headers-only protocol fallback, so local-dev calls don't silently resolve to https://localhost:3000.
    • hasRequest uses isRequestLike, which now rejects objects that spoof Symbol.toStringTag without a real url / headers.get shape.

    Plugin metadata helpers

    • oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oAuthDiscoveryMetadata, and oAuthProtectedResourceMetadata forward the incoming request to their chained auth.api calls, so issuer and discovery URLs reflect the request host on dynamic configs.
    • withMcpAuth forwards the incoming request to getMcpSession, threads trustedProxyHeaders, and emits a bare Bearer challenge when baseURL can't be resolved (instead of Bearer resource_metadata="undefined/...").
    • metadataResponse in @better-auth/oauth-provider normalizes headers via new Headers() so callers can pass Headers, tuple arrays, or records without silently dropping entries.
  • #9122 484ce6a Thanks @gustavovalverde! - fix(two-factor): enforce 2FA on all sign-in paths

    The 2FA after-hook now triggers on any endpoint that creates a new session, covering magic-link, OAuth, passkey, email-OTP, SIWE, and all future sign-in methods. Authenticated requests (session refreshes, profile updates) are excluded.

  • #7231 f875897 Thanks @Byte-Biscuit! - fix(two-factor): preserve backup codes storage format after verification

    After using a backup code, remaining codes are now re-saved using the same storeBackupCodes strategy (plain, encrypted, or custom) configured by the user. Previously, codes were always re-encrypted with the built-in symmetric encryption, breaking subsequent verifications for plain or custom storage modes.

  • #9078 9a6d475 Thanks @ping-maxwell! - fix(client): prevent isMounted race condition causing many rps

  • #9113 513dabb Thanks @bytaesu! - resolve dynamic baseURL from request headers on direct auth.api calls

  • Updated dependencies []:

    • @better-auth/core@1.7.0-beta.1
    • @better-auth/drizzle-adapter@1.7.0-beta.1
    • @better-auth/kysely-adapter@1.7.0-beta.1
    • @better-auth/memory-adapter@1.7.0-beta.1
    • @better-auth/mongo-adapter@1.7.0-beta.1
    • @better-auth/prisma-adapter@1.7.0-beta.1
    • @better-auth/telemetry@1.7.0-beta.1

@better-auth/electron@1.7.0-beta.1

Minor Changes

  • #9069 c7d2253 Thanks @gustavovalverde! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use signIn.social + callback/:id instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with openid scope injection, and typed provider IDs.

    Breaking changes:

    • signIn.oauth2({ providerId }) replaced by signIn.social({ provider })
    • oauth2.link() replaced by linkSocial()
    • Callback URL changed from /api/auth/oauth2/callback/:id to /api/auth/callback/:id
    • genericOAuthClient() deprecated (no longer needed)
    • pkce defaults to true (was false); set pkce: false for providers that reject PKCE
    • authorizationUrlParams and tokenUrlParams only accept Record<string, string>
    • issuer and requireIssuerValidation config fields removed; issuer validation is automatic via OIDC discovery
    • mapProfileToUser profile typed as OAuth2UserInfo & Record<string, unknown>

Patch Changes

@better-auth/expo@1.7.0-beta.1

Minor Changes

  • #9069 c7d2253 Thanks @gustavovalverde! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use signIn.social + callback/:id instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with openid scope injection, and typed provider IDs.

    Breaking changes:

    • signIn.oauth2({ providerId }) replaced by signIn.social({ provider })
    • oauth2.link() replaced by linkSocial()
    • Callback URL changed from /api/auth/oauth2/callback/:id to /api/auth/callback/:id
    • genericOAuthClient() deprecated (no longer needed)
    • pkce defaults to true (was false); set pkce: false for providers that reject PKCE
    • authorizationUrlParams and tokenUrlParams only accept Record<string, string>
    • issuer and requireIssuerValidation config fields removed; issuer validation is automatic via OIDC discovery
    • mapProfileToUser profile typed as OAuth2UserInfo & Record<string, unknown>

Patch Changes

@better-auth/oauth-provider@1.7.0-beta.1

Minor Changes

  • #9069 c7d2253 Thanks @gustavovalverde! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use signIn.social + callback/:id instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with openid scope injection, and typed provider IDs.

    Breaking changes:

    • signIn.oauth2({ providerId }) replaced by signIn.social({ provider })
    • oauth2.link() replaced by linkSocial()
    • Callback URL changed from /api/auth/oauth2/callback/:id to /api/auth/callback/:id
    • genericOAuthClient() deprecated (no longer needed)
    • pkce defaults to true (was false); set pkce: false for providers that reject PKCE
    • authorizationUrlParams and tokenUrlParams only accept Record<string, string>
    • issuer and requireIssuerValidation config fields removed; issuer validation is automatic via OIDC discovery
    • mapProfileToUser profile typed as OAuth2UserInfo & Record<string, unknown>
  • #9079 6f2948e Thanks @gustavovalverde! - feat(oauth-provider): compute at_hash in ID tokens per OIDC Core §3.1.3.6

    ID tokens issued alongside an access token now include the at_hash claim, which cryptographically binds the two tokens to prevent token substitution attacks. The hash algorithm is selected based on the actual signing key's algorithm (EdDSA/Ed25519 uses SHA-512, RS/ES/PS384 uses SHA-384, RS/ES/PS512 uses SHA-512, all others use SHA-256).

    A new resolveSigningKey() export is available from better-auth/plugins to resolve the current JWKS signing key (including its algorithm). When using a custom jwt.sign callback, the signed ID token's header is validated against the declared algorithm to prevent at_hash mismatches.

Patch Changes

  • #9123 e2e25a4 Thanks @gustavovalverde! - fix(oauth-provider): override confidential auth methods to public in unauthenticated DCR

    When allowUnauthenticatedClientRegistration is enabled, unauthenticated DCR
    requests that specify client_secret_post, client_secret_basic, or omit
    token_endpoint_auth_method (which defaults to client_secret_basic per
    RFC 7591 §2) are
    now silently overridden to token_endpoint_auth_method: "none" (public client)
    instead of being rejected with HTTP 401.

    This follows RFC 7591 §3.2.1,
    which allows the server to "reject or replace any of the client's requested
    metadata values submitted during the registration and substitute them with
    suitable values." The registration response communicates the actual method
    back to the client, allowing compliant clients to adjust.

    This fixes interoperability with real-world MCP clients (Claude, Codex, Factory
    Droid, and others) that send token_endpoint_auth_method: "client_secret_post"
    in their DCR payload because the server metadata advertises it in
    token_endpoint_auth_methods_supported.

    Closes #8588

  • #9131 5142e9c Thanks @gustavovalverde! - harden dynamic baseURL handling for direct auth.api.* calls and plugin metadata helpers

    Direct auth.api.* calls

    • Throw APIError with a clear message when the baseURL can't be resolved (no source and no fallback), instead of leaving ctx.context.baseURL = "" for downstream plugins to crash on.
    • Convert allowedHosts mismatches on the direct-API path to APIError.
    • Honor advanced.trustedProxyHeaders on the dynamic path (default true, unchanged). Previously x-forwarded-host / -proto were unconditionally trusted with allowedHosts; they now go through the same gate as the static path. The default flip to false ships in a follow-up PR.
    • resolveRequestContext rehydrates trustedProviders and cookies per call (in addition to trustedOrigins). User-defined trustedOrigins(req) / trustedProviders(req) callbacks receive a Request synthesized from forwarded headers when no full Request is available.
    • Infer http for loopback hosts (localhost, 127.0.0.1, [::1], 0.0.0.0) on the headers-only protocol fallback, so local-dev calls don't silently resolve to https://localhost:3000.
    • hasRequest uses isRequestLike, which now rejects objects that spoof Symbol.toStringTag without a real url / headers.get shape.

    Plugin metadata helpers

    • oauthProviderAuthServerMetadata, oauthProviderOpenIdConfigMetadata, oAuthDiscoveryMetadata, and oAuthProtectedResourceMetadata forward the incoming request to their chained auth.api calls, so issuer and discovery URLs reflect the request host on dynamic configs.
    • withMcpAuth forwards the incoming request to getMcpSession, threads trustedProxyHeaders, and emits a bare Bearer challenge when baseURL can't be resolved (instead of Bearer resource_metadata="undefined/...").
    • metadataResponse in @better-auth/oauth-provider normalizes headers via new Headers() so callers can pass Headers, tuple arrays, or records without silently dropping entries.
  • #9118 314e06f Thanks @gustavovalverde! - feat(oauth-provider): add customTokenResponseFields callback and Zod validation for authorization codes

    Add customTokenResponseFields callback to OAuthOptions for injecting custom fields into token endpoint responses across all grant types. Standard OAuth fields (access_token, token_type, etc.) cannot be overridden. Follows the same pattern as customAccessTokenClaims and customIdTokenClaims.

    Authorization code verification values are now validated with a Zod schema at deserialization, consistently returning invalid_verification errors for malformed or corrupted values instead of potential 500s.

  • Updated dependencies [5142e9c, 484ce6a, f875897, c7d2253, 9a6d475, 513dabb, 6f2948e]:

    • better-auth@1.7.0-beta.1
    • @better-auth/core@1.7.0-beta.1

@better-auth/sso@1.7.0-beta.1

Minor Changes

  • #9117 b70f025 Thanks @gustavovalverde! - ### Breaking: SAML configuration changes

    callbackUrl removed from samlConfig.
    The ACS URL is now always derived from your baseURL and providerId. Remove callbackUrl from your SAML provider configuration. The post-login redirect destination is set per sign-in via callbackURL in signIn.sso():

    await authClient.signIn.sso({
      providerId: "my-provider",
      callbackURL: "/dashboard",
    });
    

    /sso/saml2/callback/:providerId endpoint removed.
    Update your IdP's ACS URL to /sso/saml2/sp/acs/:providerId. This endpoint handles both GET and POST requests.

    spMetadata is now optional.
    You no longer need to pass spMetadata: {} when registering a provider. SP metadata is auto-generated from your configuration.

    Removed unused fields from SAMLConfig:
    decryptionPvk, additionalParams, idpMetadata.entityURL, idpMetadata.redirectURL. These were stored but never read. Remove them from your configuration if present.

    Bug fixes

    • Fix SLO SessionIndex matching: LogoutRequests with a SessionIndex were silently failing to delete the correct session.
    • Audience validation now defaults to the SP entity ID when audience is not configured, per SAML Core section 2.5.1.
    • Restore AllowCreate in AuthnRequests, required by IdPs that use JIT provisioning.
    • SP metadata endpoint now reflects actual SP capabilities (encryption, signing, SLO).

Patch Changes

  • #9121 9603043 Thanks @gustavovalverde! - ### Security: upgrade samlify to 2.12.0

    Upgrades the SAML XML processing library from 2.10.2 to 2.12.0:

    • XPath injection protection: all XPath expressions now use value escaping instead of string interpolation
    • XXE prevention: the XML parser defaults to strict mode that rejects entity references
    • Dependency reduction: removes node-forge, pako, uuid, and camelcase in favor of Node built-ins

    PEM keys and certificates with leading whitespace are now normalized automatically before being passed to samlify. This prevents DECODER routines::unsupported errors when keys are copied from indented config files or environment variables.

    Requires Node 20+.

  • Updated dependencies [5142e9c, 484ce6a, f875897, c7d2253, 9a6d475, 513dabb, 6f2948e]:

    • better-auth@1.7.0-beta.1
    • @better-auth/core@1.7.0-beta.1

@better-auth/api-key@1.7.0-beta.1

Patch Changes

auth@1.7.0-beta.1

Patch Changes

@better-auth/drizzle-adapter@1.7.0-beta.1

Patch Changes

  • Updated dependencies []:
    • @better-auth/core@1.7.0-beta.1

@better-auth/i18n@1.7.0-beta.1

Patch Changes

@better-auth/kysely-adapter@1.7.0-beta.1

Patch Changes

  • Updated dependencies []:
    • @better-auth/core@1.7.0-beta.1

@better-auth/memory-adapter@1.7.0-beta.1

Patch Changes

  • Updated dependencies []:
    • @better-auth/core@1.7.0-beta.1

@better-auth/mongo-adapter@1.7.0-beta.1

Patch Changes

  • Updated dependencies []:
    • @better-auth/core@1.7.0-beta.1

@better-auth/passkey@1.7.0-beta.1

Patch Changes

@better-auth/prisma-adapter@1.7.0-beta.1

Patch Changes

  • Updated dependencies []:
    • @better-auth/core@1.7.0-beta.1

@better-auth/redis-storage@1.7.0-beta.1

Patch Changes

  • Updated dependencies []:
    • @better-auth/core@1.7.0-beta.1

@better-auth/scim@1.7.0-beta.1

Patch Changes

@better-auth/stripe@1.7.0-beta.1

Patch Changes

  • #9164 390a031 Thanks @gustavovalverde! - fix(stripe): drop unsafe keys when merging user-supplied metadata

    The Stripe plugin previously merged ctx.body.metadata through defu, which was vulnerable to prototype pollution when attacker-controlled __proto__ keys reached the second argument. Since Stripe metadata is a flat Record<string, string>, the deep-merge was never exercised on that path. The merge now ignores __proto__, constructor, and prototype, so the user-controlled surface no longer depends on defu. The remaining defu call sites (deep-merging developer-supplied CustomerCreateParams) also receive the patched range.

  • Updated dependencies [5142e9c, 484ce6a, f875897, c7d2253, 9a6d475, 513dabb, 6f2948e]:

    • better-auth@1.7.0-beta.1
    • @better-auth/core@1.7.0-beta.1

@better-auth/telemetry@1.7.0-beta.1

Patch Changes

  • Updated dependencies []:
    • @better-auth/core@1.7.0-beta.1

@better-auth/test-utils@1.7.0-beta.1

Patch Changes

@better-auth/core@1.7.0-beta.1


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/better-auth/better-auth/pull/9120 **Author:** [@better-release[bot]](https://github.com/apps/better-release) **Created:** 4/11/2026 **Status:** ✅ Merged **Merged:** 4/14/2026 **Merged by:** [@gustavovalverde](https://github.com/gustavovalverde) **Base:** `next` ← **Head:** `changeset-release/next` --- ### 📝 Commits (1) - [`d5ca8e2`](https://github.com/better-auth/better-auth/commit/d5ca8e23656d152fc33589517a9df11e8bac158b) chore: release (beta) ### 📊 Changes **41 files changed** (+367 additions, -20 deletions) <details> <summary>View changed files</summary> 📝 `.changeset/pre.json` (+12 -0) 📝 `packages/api-key/CHANGELOG.md` (+8 -0) 📝 `packages/api-key/package.json` (+1 -1) 📝 `packages/better-auth/CHANGELOG.md` (+60 -0) 📝 `packages/better-auth/package.json` (+1 -1) 📝 `packages/cli/CHANGELOG.md` (+9 -0) 📝 `packages/cli/package.json` (+1 -1) 📝 `packages/core/CHANGELOG.md` (+2 -0) 📝 `packages/core/package.json` (+1 -1) 📝 `packages/drizzle-adapter/CHANGELOG.md` (+7 -0) 📝 `packages/drizzle-adapter/package.json` (+1 -1) 📝 `packages/electron/CHANGELOG.md` (+22 -0) 📝 `packages/electron/package.json` (+1 -1) 📝 `packages/expo/CHANGELOG.md` (+22 -0) 📝 `packages/expo/package.json` (+1 -1) 📝 `packages/i18n/CHANGELOG.md` (+8 -0) 📝 `packages/i18n/package.json` (+1 -1) 📝 `packages/kysely-adapter/CHANGELOG.md` (+7 -0) 📝 `packages/kysely-adapter/package.json` (+1 -1) 📝 `packages/memory-adapter/CHANGELOG.md` (+7 -0) _...and 21 more files_ </details> ### 📄 Description This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to next, this PR will be updated. ⚠️⚠️⚠️⚠️⚠️⚠️ `next` is currently in **pre mode** so this branch has prereleases rather than normal releases. If you want to exit prereleases, run `changeset pre exit` on `next`. ⚠️⚠️⚠️⚠️⚠️⚠️ # Releases ## better-auth@1.7.0-beta.1 ### Minor Changes - [#9069](https://github.com/better-auth/better-auth/pull/9069) [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use `signIn.social` + `callback/:id` instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with `openid` scope injection, and typed provider IDs. **Breaking changes:** - `signIn.oauth2({ providerId })` replaced by `signIn.social({ provider })` - `oauth2.link()` replaced by `linkSocial()` - Callback URL changed from `/api/auth/oauth2/callback/:id` to `/api/auth/callback/:id` - `genericOAuthClient()` deprecated (no longer needed) - `pkce` defaults to `true` (was `false`); set `pkce: false` for providers that reject PKCE - `authorizationUrlParams` and `tokenUrlParams` only accept `Record<string, string>` - `issuer` and `requireIssuerValidation` config fields removed; issuer validation is automatic via OIDC discovery - `mapProfileToUser` profile typed as `OAuth2UserInfo & Record<string, unknown>` - [#9079](https://github.com/better-auth/better-auth/pull/9079) [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - feat(oauth-provider): compute `at_hash` in ID tokens per OIDC Core §3.1.3.6 ID tokens issued alongside an access token now include the `at_hash` claim, which cryptographically binds the two tokens to prevent token substitution attacks. The hash algorithm is selected based on the actual signing key's algorithm (EdDSA/Ed25519 uses SHA-512, RS/ES/PS384 uses SHA-384, RS/ES/PS512 uses SHA-512, all others use SHA-256). A new `resolveSigningKey()` export is available from `better-auth/plugins` to resolve the current JWKS signing key (including its algorithm). When using a custom `jwt.sign` callback, the signed ID token's header is validated against the declared algorithm to prevent `at_hash` mismatches. ### Patch Changes - [#9131](https://github.com/better-auth/better-auth/pull/9131) [`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - harden dynamic `baseURL` handling for direct `auth.api.*` calls and plugin metadata helpers **Direct `auth.api.*` calls** - Throw `APIError` with a clear message when the baseURL can't be resolved (no source and no `fallback`), instead of leaving `ctx.context.baseURL = ""` for downstream plugins to crash on. - Convert `allowedHosts` mismatches on the direct-API path to `APIError`. - Honor `advanced.trustedProxyHeaders` on the dynamic path (default `true`, unchanged). Previously `x-forwarded-host` / `-proto` were unconditionally trusted with `allowedHosts`; they now go through the same gate as the static path. The default flip to `false` ships in a follow-up PR. - `resolveRequestContext` rehydrates `trustedProviders` and cookies per call (in addition to `trustedOrigins`). User-defined `trustedOrigins(req)` / `trustedProviders(req)` callbacks receive a `Request` synthesized from forwarded headers when no full `Request` is available. - Infer `http` for loopback hosts (`localhost`, `127.0.0.1`, `[::1]`, `0.0.0.0`) on the headers-only protocol fallback, so local-dev calls don't silently resolve to `https://localhost:3000`. - `hasRequest` uses `isRequestLike`, which now rejects objects that spoof `Symbol.toStringTag` without a real `url` / `headers.get` shape. **Plugin metadata helpers** - `oauthProviderAuthServerMetadata`, `oauthProviderOpenIdConfigMetadata`, `oAuthDiscoveryMetadata`, and `oAuthProtectedResourceMetadata` forward the incoming request to their chained `auth.api` calls, so `issuer` and discovery URLs reflect the request host on dynamic configs. - `withMcpAuth` forwards the incoming request to `getMcpSession`, threads `trustedProxyHeaders`, and emits a bare `Bearer` challenge when `baseURL` can't be resolved (instead of `Bearer resource_metadata="undefined/..."`). - `metadataResponse` in `@better-auth/oauth-provider` normalizes headers via `new Headers()` so callers can pass `Headers`, tuple arrays, or records without silently dropping entries. - [#9122](https://github.com/better-auth/better-auth/pull/9122) [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - fix(two-factor): enforce 2FA on all sign-in paths The 2FA after-hook now triggers on any endpoint that creates a new session, covering magic-link, OAuth, passkey, email-OTP, SIWE, and all future sign-in methods. Authenticated requests (session refreshes, profile updates) are excluded. - [#7231](https://github.com/better-auth/better-auth/pull/7231) [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f) Thanks [@Byte-Biscuit](https://github.com/Byte-Biscuit)! - fix(two-factor): preserve backup codes storage format after verification After using a backup code, remaining codes are now re-saved using the same `storeBackupCodes` strategy (plain, encrypted, or custom) configured by the user. Previously, codes were always re-encrypted with the built-in symmetric encryption, breaking subsequent verifications for plain or custom storage modes. - [#9078](https://github.com/better-auth/better-auth/pull/9078) [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7) Thanks [@ping-maxwell](https://github.com/ping-maxwell)! - fix(client): prevent isMounted race condition causing many rps - [#9113](https://github.com/better-auth/better-auth/pull/9113) [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af) Thanks [@bytaesu](https://github.com/bytaesu)! - resolve dynamic `baseURL` from request headers on direct `auth.api` calls - Updated dependencies \[]: - @better-auth/core@1.7.0-beta.1 - @better-auth/drizzle-adapter@1.7.0-beta.1 - @better-auth/kysely-adapter@1.7.0-beta.1 - @better-auth/memory-adapter@1.7.0-beta.1 - @better-auth/mongo-adapter@1.7.0-beta.1 - @better-auth/prisma-adapter@1.7.0-beta.1 - @better-auth/telemetry@1.7.0-beta.1 ## @better-auth/electron@1.7.0-beta.1 ### Minor Changes - [#9069](https://github.com/better-auth/better-auth/pull/9069) [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use `signIn.social` + `callback/:id` instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with `openid` scope injection, and typed provider IDs. **Breaking changes:** - `signIn.oauth2({ providerId })` replaced by `signIn.social({ provider })` - `oauth2.link()` replaced by `linkSocial()` - Callback URL changed from `/api/auth/oauth2/callback/:id` to `/api/auth/callback/:id` - `genericOAuthClient()` deprecated (no longer needed) - `pkce` defaults to `true` (was `false`); set `pkce: false` for providers that reject PKCE - `authorizationUrlParams` and `tokenUrlParams` only accept `Record<string, string>` - `issuer` and `requireIssuerValidation` config fields removed; issuer validation is automatic via OIDC discovery - `mapProfileToUser` profile typed as `OAuth2UserInfo & Record<string, unknown>` ### Patch Changes - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/expo@1.7.0-beta.1 ### Minor Changes - [#9069](https://github.com/better-auth/better-auth/pull/9069) [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use `signIn.social` + `callback/:id` instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with `openid` scope injection, and typed provider IDs. **Breaking changes:** - `signIn.oauth2({ providerId })` replaced by `signIn.social({ provider })` - `oauth2.link()` replaced by `linkSocial()` - Callback URL changed from `/api/auth/oauth2/callback/:id` to `/api/auth/callback/:id` - `genericOAuthClient()` deprecated (no longer needed) - `pkce` defaults to `true` (was `false`); set `pkce: false` for providers that reject PKCE - `authorizationUrlParams` and `tokenUrlParams` only accept `Record<string, string>` - `issuer` and `requireIssuerValidation` config fields removed; issuer validation is automatic via OIDC discovery - `mapProfileToUser` profile typed as `OAuth2UserInfo & Record<string, unknown>` ### Patch Changes - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/oauth-provider@1.7.0-beta.1 ### Minor Changes - [#9069](https://github.com/better-auth/better-auth/pull/9069) [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Rewrite the generic OAuth plugin as a first-class social provider with OAuth 2.1 security defaults. Providers now use `signIn.social` + `callback/:id` instead of dedicated plugin endpoints, with PKCE required by default (OAuth 2.1), RFC 9207 issuer validation, OIDC auto-discovery with `openid` scope injection, and typed provider IDs. **Breaking changes:** - `signIn.oauth2({ providerId })` replaced by `signIn.social({ provider })` - `oauth2.link()` replaced by `linkSocial()` - Callback URL changed from `/api/auth/oauth2/callback/:id` to `/api/auth/callback/:id` - `genericOAuthClient()` deprecated (no longer needed) - `pkce` defaults to `true` (was `false`); set `pkce: false` for providers that reject PKCE - `authorizationUrlParams` and `tokenUrlParams` only accept `Record<string, string>` - `issuer` and `requireIssuerValidation` config fields removed; issuer validation is automatic via OIDC discovery - `mapProfileToUser` profile typed as `OAuth2UserInfo & Record<string, unknown>` - [#9079](https://github.com/better-auth/better-auth/pull/9079) [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - feat(oauth-provider): compute `at_hash` in ID tokens per OIDC Core §3.1.3.6 ID tokens issued alongside an access token now include the `at_hash` claim, which cryptographically binds the two tokens to prevent token substitution attacks. The hash algorithm is selected based on the actual signing key's algorithm (EdDSA/Ed25519 uses SHA-512, RS/ES/PS384 uses SHA-384, RS/ES/PS512 uses SHA-512, all others use SHA-256). A new `resolveSigningKey()` export is available from `better-auth/plugins` to resolve the current JWKS signing key (including its algorithm). When using a custom `jwt.sign` callback, the signed ID token's header is validated against the declared algorithm to prevent `at_hash` mismatches. ### Patch Changes - [#9123](https://github.com/better-auth/better-auth/pull/9123) [`e2e25a4`](https://github.com/better-auth/better-auth/commit/e2e25a49545f3e386cfcc4e86b33c1796a1430b1) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - fix(oauth-provider): override confidential auth methods to public in unauthenticated DCR When `allowUnauthenticatedClientRegistration` is enabled, unauthenticated DCR requests that specify `client_secret_post`, `client_secret_basic`, or omit `token_endpoint_auth_method` (which defaults to `client_secret_basic` per [RFC 7591 §2](https://datatracker.ietf.org/doc/html/rfc7591#section-2)) are now silently overridden to `token_endpoint_auth_method: "none"` (public client) instead of being rejected with HTTP 401. This follows [RFC 7591 §3.2.1](https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.1), which allows the server to "reject or replace any of the client's requested metadata values submitted during the registration and substitute them with suitable values." The registration response communicates the actual method back to the client, allowing compliant clients to adjust. This fixes interoperability with real-world MCP clients (Claude, Codex, Factory Droid, and others) that send `token_endpoint_auth_method: "client_secret_post"` in their DCR payload because the server metadata advertises it in `token_endpoint_auth_methods_supported`. Closes [#8588](https://github.com/better-auth/better-auth/issues/8588) - [#9131](https://github.com/better-auth/better-auth/pull/9131) [`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - harden dynamic `baseURL` handling for direct `auth.api.*` calls and plugin metadata helpers **Direct `auth.api.*` calls** - Throw `APIError` with a clear message when the baseURL can't be resolved (no source and no `fallback`), instead of leaving `ctx.context.baseURL = ""` for downstream plugins to crash on. - Convert `allowedHosts` mismatches on the direct-API path to `APIError`. - Honor `advanced.trustedProxyHeaders` on the dynamic path (default `true`, unchanged). Previously `x-forwarded-host` / `-proto` were unconditionally trusted with `allowedHosts`; they now go through the same gate as the static path. The default flip to `false` ships in a follow-up PR. - `resolveRequestContext` rehydrates `trustedProviders` and cookies per call (in addition to `trustedOrigins`). User-defined `trustedOrigins(req)` / `trustedProviders(req)` callbacks receive a `Request` synthesized from forwarded headers when no full `Request` is available. - Infer `http` for loopback hosts (`localhost`, `127.0.0.1`, `[::1]`, `0.0.0.0`) on the headers-only protocol fallback, so local-dev calls don't silently resolve to `https://localhost:3000`. - `hasRequest` uses `isRequestLike`, which now rejects objects that spoof `Symbol.toStringTag` without a real `url` / `headers.get` shape. **Plugin metadata helpers** - `oauthProviderAuthServerMetadata`, `oauthProviderOpenIdConfigMetadata`, `oAuthDiscoveryMetadata`, and `oAuthProtectedResourceMetadata` forward the incoming request to their chained `auth.api` calls, so `issuer` and discovery URLs reflect the request host on dynamic configs. - `withMcpAuth` forwards the incoming request to `getMcpSession`, threads `trustedProxyHeaders`, and emits a bare `Bearer` challenge when `baseURL` can't be resolved (instead of `Bearer resource_metadata="undefined/..."`). - `metadataResponse` in `@better-auth/oauth-provider` normalizes headers via `new Headers()` so callers can pass `Headers`, tuple arrays, or records without silently dropping entries. - [#9118](https://github.com/better-auth/better-auth/pull/9118) [`314e06f`](https://github.com/better-auth/better-auth/commit/314e06f0fd84ac90b55b5430624a74c5a8d62bfd) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - feat(oauth-provider): add `customTokenResponseFields` callback and Zod validation for authorization codes Add `customTokenResponseFields` callback to `OAuthOptions` for injecting custom fields into token endpoint responses across all grant types. Standard OAuth fields (`access_token`, `token_type`, etc.) cannot be overridden. Follows the same pattern as `customAccessTokenClaims` and `customIdTokenClaims`. Authorization code verification values are now validated with a Zod schema at deserialization, consistently returning `invalid_verification` errors for malformed or corrupted values instead of potential 500s. - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/sso@1.7.0-beta.1 ### Minor Changes - [#9117](https://github.com/better-auth/better-auth/pull/9117) [`b70f025`](https://github.com/better-auth/better-auth/commit/b70f025bfaad38c229305a25e87e08bc176f9503) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - ### Breaking: SAML configuration changes **`callbackUrl` removed from `samlConfig`.** The ACS URL is now always derived from your `baseURL` and `providerId`. Remove `callbackUrl` from your SAML provider configuration. The post-login redirect destination is set per sign-in via `callbackURL` in `signIn.sso()`: ```ts await authClient.signIn.sso({ providerId: "my-provider", callbackURL: "/dashboard", }); ``` **`/sso/saml2/callback/:providerId` endpoint removed.** Update your IdP's ACS URL to `/sso/saml2/sp/acs/:providerId`. This endpoint handles both GET and POST requests. **`spMetadata` is now optional.** You no longer need to pass `spMetadata: {}` when registering a provider. SP metadata is auto-generated from your configuration. **Removed unused fields from `SAMLConfig`:** `decryptionPvk`, `additionalParams`, `idpMetadata.entityURL`, `idpMetadata.redirectURL`. These were stored but never read. Remove them from your configuration if present. ### Bug fixes - Fix SLO SessionIndex matching: LogoutRequests with a SessionIndex were silently failing to delete the correct session. - Audience validation now defaults to the SP entity ID when `audience` is not configured, per SAML Core section 2.5.1. - Restore `AllowCreate` in AuthnRequests, required by IdPs that use JIT provisioning. - SP metadata endpoint now reflects actual SP capabilities (encryption, signing, SLO). ### Patch Changes - [#9121](https://github.com/better-auth/better-auth/pull/9121) [`9603043`](https://github.com/better-auth/better-auth/commit/960304354aebab2f03c0fadd0d7bfd02febfd246) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - ### Security: upgrade samlify to 2.12.0 Upgrades the SAML XML processing library from 2.10.2 to 2.12.0: - **XPath injection protection**: all XPath expressions now use value escaping instead of string interpolation - **XXE prevention**: the XML parser defaults to strict mode that rejects entity references - **Dependency reduction**: removes `node-forge`, `pako`, `uuid`, and `camelcase` in favor of Node built-ins PEM keys and certificates with leading whitespace are now normalized automatically before being passed to samlify. This prevents `DECODER routines::unsupported` errors when keys are copied from indented config files or environment variables. Requires Node 20+. - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/api-key@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## auth@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 - @better-auth/telemetry@1.7.0-beta.1 ## @better-auth/drizzle-adapter@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[]: - @better-auth/core@1.7.0-beta.1 ## @better-auth/i18n@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/kysely-adapter@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[]: - @better-auth/core@1.7.0-beta.1 ## @better-auth/memory-adapter@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[]: - @better-auth/core@1.7.0-beta.1 ## @better-auth/mongo-adapter@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[]: - @better-auth/core@1.7.0-beta.1 ## @better-auth/passkey@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/prisma-adapter@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[]: - @better-auth/core@1.7.0-beta.1 ## @better-auth/redis-storage@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[]: - @better-auth/core@1.7.0-beta.1 ## @better-auth/scim@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/stripe@1.7.0-beta.1 ### Patch Changes - [#9164](https://github.com/better-auth/better-auth/pull/9164) [`390a031`](https://github.com/better-auth/better-auth/commit/390a03190c988776e53c5e64cf6c2f60db1c5415) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - fix(stripe): drop unsafe keys when merging user-supplied metadata The Stripe plugin previously merged `ctx.body.metadata` through `defu`, which was vulnerable to prototype pollution when attacker-controlled `__proto__` keys reached the second argument. Since Stripe metadata is a flat `Record<string, string>`, the deep-merge was never exercised on that path. The merge now ignores `__proto__`, `constructor`, and `prototype`, so the user-controlled surface no longer depends on `defu`. The remaining `defu` call sites (deep-merging developer-supplied `CustomerCreateParams`) also receive the patched range. - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/telemetry@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[]: - @better-auth/core@1.7.0-beta.1 ## @better-auth/test-utils@1.7.0-beta.1 ### Patch Changes - Updated dependencies \[[`5142e9c`](https://github.com/better-auth/better-auth/commit/5142e9cec55825eb14da0f14022ae02d3c9dfd45), [`484ce6a`](https://github.com/better-auth/better-auth/commit/484ce6a262c39b9c1be91d37774a2a13de3a5a1f), [`f875897`](https://github.com/better-auth/better-auth/commit/f8758975ae475429d56b34aa6067e304ee973c8f), [`c7d2253`](https://github.com/better-auth/better-auth/commit/c7d22539ec4f7322d9625ae2953d397c3863d097), [`9a6d475`](https://github.com/better-auth/better-auth/commit/9a6d4759cd4451f0535d53f171bcfc8891c41db7), [`513dabb`](https://github.com/better-auth/better-auth/commit/513dabb132e2c08a5b6d3b7e88dd397fcd66c1af), [`6f2948e`](https://github.com/better-auth/better-auth/commit/6f2948e87bb5fa14bd2174a91f7143e1eced1b87)]: - better-auth@1.7.0-beta.1 - @better-auth/core@1.7.0-beta.1 ## @better-auth/core@1.7.0-beta.1 --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
GiteaMirror added the pull-request label 2026-04-15 22:50:58 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#25352