Skip to content

Update dependency better-auth to v1.6.7#27

Open
renovate[bot] wants to merge 1 commit intomainfrom
renovate/better-auth-1.x
Open

Update dependency better-auth to v1.6.7#27
renovate[bot] wants to merge 1 commit intomainfrom
renovate/better-auth-1.x

Conversation

@renovate
Copy link
Copy Markdown
Contributor

@renovate renovate Bot commented Apr 5, 2026

ℹ️ Note

This PR body was truncated due to platform limits.

This PR contains the following updates:

Package Change Age Confidence
better-auth (source) 1.4.181.6.7 age confidence

Release Notes

better-auth/better-auth (better-auth)

v1.6.7

Compare Source

Patch Changes
  • #​9211 307196a Thanks @​stewartjarod! - Preserve Set-Cookie headers accumulated on ctx.responseHeaders when an endpoint throws APIError. Cookie side-effects from deleteSessionCookie (and any ctx.setCookie / ctx.setHeader calls before the throw) are no longer silently discarded on the error path.

  • #​9292 4f373ee Thanks @​gustavovalverde! - Accept an array of Client IDs on providers that verify ID tokens by audience (Google, Apple, Microsoft Entra, Facebook, Cognito). The first entry is used for the authorization code flow; all entries are accepted when verifying an ID token's aud claim, so a single backend can serve Web, iOS, and Android clients with their platform-specific Client IDs.

    socialProviders: {
      google: {
        clientId: [
          process.env.GOOGLE_WEB_CLIENT_ID!,
          process.env.GOOGLE_IOS_CLIENT_ID!,
          process.env.GOOGLE_ANDROID_CLIENT_ID!,
        ],
        clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
      },
    }

    Passing a single string keeps working; no migration needed.

    Also exports getPrimaryClientId from @better-auth/core/oauth2 for provider authors: it returns the primary Client ID (the raw string, or the entry at array index 0), paired with clientSecret for the authorization code flow. Providers now reject empty arrays, empty strings, and missing config at sign-in time instead of silently producing a malformed authorization URL. Google, Apple, and Facebook require both clientId and clientSecret because each of those providers mandates a client secret for their server-side code exchange. Microsoft Entra and Cognito only require clientId, since both support public-client flows with PKCE alone (no secret).

  • #​9293 e1b1cfc Thanks @​gustavovalverde! - Guard against c.body being undefined in parseState. Callback requests that arrive as GET leave c.body unset in some runtimes, which caused c.body.state to throw a TypeError before the existing error redirect could run. The state lookup now short-circuits on the query parameter and falls back to c.body?.state safely, so a callback without a state parameter redirects to the error page instead of crashing.

  • #​4894 d053a45 Thanks @​Kinfe123! - Fire callbackOnVerification when a phone number is verified with updatePhoneNumber: true. The callback previously only ran on initial verification, so consumers relying on it (e.g. to sync verified numbers to an external system) would miss the event when an authenticated user changed their number.

  • Updated dependencies [307196a, 4a180f0, 4f373ee]:

v1.6.6

Compare Source

Patch Changes
  • #​9214 4debfb6 Thanks @​ping-maxwell! - fix(custom-session): use coerced boolean for disableRefresh query param validation

  • #​9235 9ea7eb1 Thanks @​bytaesu! - Preserve the Partitioned attribute when the customSession plugin and framework integrations forward Set-Cookie headers.

  • #​9266 ab4c10f Thanks @​ping-maxwell! - fix(organization): infer team additional fields correctly

  • #​9219 a61083e Thanks @​bytaesu! - Allow removing a phone number with updateUser({ phoneNumber: null }). The verified flag is reset atomically. Changing to a different number still requires OTP verification through verify({ updatePhoneNumber: true }).

  • #​9226 e64ff72 Thanks @​gustavovalverde! - Consolidate host/IP classification behind @better-auth/core/utils/host and close several loopback/SSRF bypasses that the previous per-package regex checks missed.

    Electron user-image proxy: SSRF bypasses closed (@better-auth/electron). fetchUserImage previously gated outbound requests with a bespoke IPv4/IPv6 regex that missed multiple vectors. All of the following were reachable in production and are now blocked:

    • http://tenant.localhost/ and other *.localhost names (RFC 6761 reserves the entire TLD for loopback).
    • http://[::ffff:169.254.169.254]/ (IPv4-mapped IPv6 to AWS IMDS, the classic SSRF bypass).
    • http://metadata.google.internal/, http://metadata.goog/ (GCP instance metadata).
    • http://instance-data/, http://instance-data.ec2.internal/ (AWS IMDS alternate FQDNs).
    • http://100.100.100.200/ (Alibaba Cloud IMDS; lives in RFC 6598 shared address space 100.64/10, which the old regex did not cover).
    • http://0.0.0.0:PORT/ (the Linux/macOS kernel routes the unspecified address to loopback: Oligo's "0.0.0.0 Day").
    • http://[fc00::...]/, http://[fd00::...]/ (IPv6 ULA per RFC 4193) and IPv6 link-local fe80::/10, neither of which the regex recognized.

    Documentation ranges (RFC 5737 / RFC 3849), benchmarking (198.18/15), multicast, and broadcast are also now rejected.

    better-auth: 0.0.0.0 is no longer treated as loopback. The previous isLoopbackHost implementation in packages/better-auth/src/utils/url.ts classified 0.0.0.0 alongside 127.0.0.1 / ::1 / localhost. 0.0.0.0 is the unspecified address, not loopback; treating it as such lets browser-origin requests reach localhost-bound dev services (Oligo's "0.0.0.0 Day"). The helper now accepts the full 127.0.0.0/8 range and any *.localhost name, and rejects 0.0.0.0.

    better-auth: trusted-origin substring hardening. getTrustedOrigins previously used host.includes("localhost") || host.includes("127.0.0.1") when deciding whether to add an http:// variant for a dynamic baseURL.allowedHosts entry. Misconfigurations like evil-localhost.com or 127.0.0.1.nip.io would incorrectly gain an HTTP origin in the trust list. The check now uses the shared classifier, so only real loopback hosts get the HTTP variant.

    @better-auth/oauth-provider: RFC 8252 compliance.

    • §7.3 redirect URI matching now accepts the full 127.0.0.0/8 range (not just 127.0.0.1) plus [::1], with port-flexible comparison. Port-flexible matching is limited to IP literals; DNS names such as localhost continue to use exact-string matching per §8.3 ("NOT RECOMMENDED" for loopback).
    • validateIssuerUrl uses the shared loopback check rather than a two-hostname literal comparison.

    New module: @better-auth/core/utils/host. Exposes classifyHost, isLoopbackIP, isLoopbackHost, and isPublicRoutableHost. One RFC 6890 / RFC 6761 / RFC 8252 implementation that handles IPv4, IPv6 (including bracketed literals, zone IDs, IPv4-mapped addresses, and 6to4 / NAT64 / Teredo tunnel forms with embedded-IPv4 recursion), and FQDNs, with a curated cloud-metadata FQDN set. All bespoke loopback/private/link-local checks across the monorepo now route through it.

  • Updated dependencies [b5742f9, a844c7d, e64ff72]:

v1.6.5

Compare Source

Patch Changes

v1.6.4

Compare Source

Patch Changes
  • #​9205 9aed910 Thanks @​gustavovalverde! - fix(two-factor): revert enforcement broadening from #​9122

    Restores the pre-#​9122 enforcement scope. 2FA is challenged only on /sign-in/email, /sign-in/username, and /sign-in/phone-number, matching the behavior that shipped through v1.6.2. Non-credential sign-in flows (magic link, email OTP, OAuth, SSO, passkey, SIWE, one-tap, phone-number OTP, device authorization, email-verification auto-sign-in) are no longer gated by a 2FA challenge by default.

    A broader enforcement scope with per-method opt-outs and alignment to NIST SP 800-63B-4 authenticator assurance levels is planned for a future minor release.

  • #​9068 acbd6ef Thanks @​GautamBytes! - Fix forced UUID user IDs from create hooks being ignored on PostgreSQL adapters when advanced.database.generateId is set to "uuid".

  • #​9165 39d6af2 Thanks @​gustavovalverde! - chore(adapters): require patched drizzle-orm and kysely peer versions

    Narrows the drizzle-orm peer to ^0.45.2 and the kysely peer to ^0.28.14. Both new ranges track the minor line that carries the vulnerability fix and nothing newer, so the adapters only advertise support for versions that have actually been tested against. Consumers on older ORM releases see an install-time warning and can upgrade alongside the adapter; the peer is marked optional, so installs do not hard-fail.

  • Updated dependencies [39d6af2]:

v1.6.3

Compare Source

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.

  • #​9072 6ce30cf Thanks @​ramonclaudio! - fix(api): align top-level operationId on requestPasswordResetCallback with the OpenAPI resetPasswordCallback

  • #​8389 f6428d0 Thanks @​Oluwatobi-Mustapha! - fix(open-api): correct get-session nullable schema for OAS 3.1

  • #​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

  • #​8926 c5066fe Thanks @​bytaesu! - omit quantity for metered prices in checkout and upgrades

  • #​9084 5f84335 Thanks @​bytaesu! - support Stripe SDK v21 and v22

  • Updated dependencies []:

v1.6.2

Compare Source

Patch Changes
  • #​8949 9deb793 Thanks @​ping-maxwell! - security: verify OAuth state parameter against cookie-stored nonce to prevent CSRF on cookie-backed flows

  • #​8983 2cbcb9b Thanks @​jaydeep-pipaliya! - fix(oauth2): prevent cross-provider account collision in link-social callback

    The link-social callback used findAccount(accountId) which matched by account ID across all providers. When two providers return the same numeric ID (e.g. both Google and GitHub assign 99999), the lookup could match the wrong provider's account, causing a spurious account_already_linked_to_different_user error or silently updating the wrong account's tokens.

    Replaced with findAccountByProviderId(accountId, providerId) to scope the lookup to the correct provider, matching the pattern already used in the generic OAuth plugin.

  • #​9059 b20fa42 Thanks @​gustavovalverde! - fix(next-js): replace cookie probe with header-based RSC detection in nextCookies() to prevent infinite router refresh loops and eliminate leaked __better-auth-cookie-store cookie. Also fix two-factor enrollment flows to set the new session cookie before deleting the old session.

  • #​9058 608d8c3 Thanks @​gustavovalverde! - fix(sso): include RelayState in signed SAML AuthnRequests per SAML 2.0 Bindings §3.4.4.1

    • RelayState is now passed to samlify's ServiceProvider constructor so it is included in the redirect binding signature. Previously it was appended after the signature, causing spec-compliant IdPs to reject signed AuthnRequests.
    • authnRequestsSigned: true without a private key now throws instead of silently sending unsigned requests.
  • #​8772 8409843 Thanks @​aarmful! - feat(two-factor): include enabled 2fa methods in sign-in redirect response

    The 2FA sign-in redirect now returns twoFactorMethods (e.g. ["totp", "otp"]) so frontends can render the correct verification UI without guessing. The onTwoFactorRedirect client callback receives twoFactorMethods as a context parameter.

    • TOTP is included only when the user has a verified TOTP secret and TOTP is not disabled in config.
    • OTP is included when otpOptions.sendOTP is configured.
    • Unverified TOTP enrollments are excluded from the methods list.
  • #​8711 e78a7b1 Thanks @​aarmful! - fix(two-factor): prevent unverified TOTP enrollment from gating sign-in

    Adds a verified boolean column to the twoFactor table that tracks whether a TOTP secret has been confirmed by the user.

    • First-time enrollment: enableTwoFactor creates the row with verified: false. The row is promoted to verified: true only after verifyTOTP succeeds with a valid code.
    • Re-enrollment (calling enableTwoFactor when TOTP is already verified): the new row preserves verified: true, so the user is never locked out of sign-in while rotating their TOTP secret.
    • Sign-in: verifyTOTP rejects rows where verified === false, preventing abandoned enrollments from blocking authentication. Backup codes and OTP are unaffected and work as fallbacks during unfinished enrollment.

    Migration: The new column defaults to true, so existing twoFactor rows are treated as verified. No data migration is required. skipVerificationOnEnable: true is also unaffected — the row is created as verified: true in that mode.

  • Updated dependencies []:

v1.6.1

Compare Source

Patch Changes

v1.6.0

Compare Source

Minor Changes
Patch Changes

v1.5.6

Compare Source

   🚀 Features
   🐞 Bug Fixes
    View changes on GitHub

v1.5.5

Compare Source

   🚀 Features
   🐞 Bug Fixes
    View changes on GitHub

v1.5.4

Compare Source

   🐞 Bug Fixes
    View changes on GitHub

v1.5.3

Compare Source

   🐞 Bug Fixes
    View changes on GitHub

v1.5.2

Compare Source

   🐞 Bug Fixes

Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from 8960427 to ab9cf2b Compare April 6, 2026 16:43
@renovate renovate Bot changed the title chore(deps): update dependency better-auth to v1.5.6 chore(deps): update dependency better-auth to v1.6.0 Apr 6, 2026
@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from ab9cf2b to fb6a9d7 Compare April 15, 2026 13:38
@renovate renovate Bot changed the title chore(deps): update dependency better-auth to v1.6.0 Update dependency better-auth to v1.6.4 Apr 15, 2026
@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from fb6a9d7 to efd42cf Compare April 16, 2026 15:06
@renovate renovate Bot changed the title Update dependency better-auth to v1.6.4 Update dependency better-auth to v1.6.5 Apr 16, 2026
@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from efd42cf to 03ee1ea Compare April 21, 2026 20:13
@renovate renovate Bot changed the title Update dependency better-auth to v1.6.5 Update dependency better-auth to v1.6.6 Apr 21, 2026
@renovate renovate Bot force-pushed the renovate/better-auth-1.x branch from 03ee1ea to 970e0a9 Compare April 22, 2026 16:17
@renovate renovate Bot changed the title Update dependency better-auth to v1.6.6 Update dependency better-auth to v1.6.7 Apr 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants