Changelog

All changes, fixes, and updates

Every release shipped to Better Auth, straight from GitHub.

CHANGELOG

better-auth

Bug Fixes

  • Fixed /admin/create-user leaving a user without a credential account when creating that account failed, such as a database hook throwing, which made retrying with the same email fail with USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL (#12338)
  • Fixed /admin/create-user leaving a user without a credential account when the password was rejected, such as by the Have I Been Pwned plugin, which made retrying with the same email fail with USER_ALREADY_EXISTS_USE_ANOTHER_EMAIL (#12335)
  • Fixed client actions ignoring the HTTP method passed in second-argument fetch options, and attaching a request body when the method was a lowercase get or HEAD (#12336)
  • Fixed plugin schema overrides (modelName and field names) leaking into other instances of the same plugin in one process (#12319)
  • Fixed /device/token returning invalid_grant instead of invalid_client when validateClient rejects the client_id, matching /device/code and RFC 6749 section 5.2 (#12246)
  • Fixed OAuth sign-in failing with state_mismatch during the daylight saving time fall-back hour when OAuth state is stored in the database and the server's time zone observes daylight saving time (#12320)
  • Fixed the OpenAPI schema to document query parameters for endpoints whose query schema is wrapped in z.optional(), such as /get-session and Stripe's /subscription/list (#12337)
  • Fixed organization.getInvitation to return the INVITATION_NOT_FOUND code for a missing, expired, or non-pending invitation (#12332)
  • Fixed listMembers failing with a syntax error on PostgreSQL and MSSQL when the filter matches no members or the offset is past the last member (#12318)
  • Fixed the active-sessions list in secondary storage being stored without an expiry when every remaining session had less than a second left (#12323)
  • Fixed SIWE sign-in leaving a user behind when creating its wallet address or account failed, which blocked that wallet from signing in again (#12366)
  • Fixed social sign-up hanging on single-connection databases when the username plugin is enabled and the provider profile maps a username (#12340)

For detailed changes, see CHANGELOG

auth

Bug Fixes

  • Fixed CLI commands hanging or exiting with code 0 at a prompt in CI or without a terminal. They now exit with code 2 and name what they need, such as --yes, and prompts appear on stderr so redirecting stdout no longer hides them (#12286)
  • Fixed CLI notices mixing into command output. auth info --json --copy now prints valid JSON, auth secret prints only the BETTER_AUTH_SECRET line on stdout, auth login and auth logout messages go to stderr, and auth info shows tips only in an interactive terminal (#12287)
  • Fixed CLI errors printing a stack trace instead of the cause. Config and database errors now show their message, and a mistyped --config path reports that the file doesn't exist. auth mcp and auth ai no longer report success after a failed step (#12305)
  • Fixed the CLI exiting with code 0 after a canceled or failed run. Canceling or declining a prompt, or pressing Ctrl+C, now exits with 130, and failures such as a missing config file or a failed auth mcp setup exit with 1 (#12275)

For detailed changes, see CHANGELOG

@better-auth/oauth-provider

Bug Fixes

  • Fixed auth.api.oauth2Consent({ headers, body }) failing with request not found when called from a server route (#12325)
  • Fixed a client secret without the configured prefix.clientSecret getting a different error than other wrong secrets. It now gets the standard invalid_client response: 401 with a WWW-Authenticate: Basic challenge for client_secret_basic, and 400 for client_secret_post (#12327)
  • Fixed OAuth client metadata being stored as a JSON string in its json column. It is now written as an object, so Postgres jsonb operators such as -> and @> work with adapters that pass JSON through natively (Drizzle pg). Rows written as strings by earlier versions are still read (#12328)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed failed fallback join queries printing the raw database error, including SQL and bound values, with console.error in addition to the configured logger (#12317)
  • Fixed getAccessToken and refreshToken returning the expired access token when a provider refuses a token refresh with a 200 status, as GitHub does (#12369)

For detailed changes, see CHANGELOG

@better-auth/expo

Bug Fixes

  • Fixed the Expo authorization proxy logging a provider configuration error on every OAuth sign-in when a social provider is set up for ID token sign-in only, such as Apple without a client secret (#12368)

For detailed changes, see CHANGELOG

@better-auth/mcp

Bug Fixes

  • Fixed MCP rejecting plain-HTTP resource URLs on .localhost subdomains as non-HTTPS (#12322)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

Adnan-HusaynAryaKesharwanibinaryshreybytaesuFaiziimamGourav224jashkarangiyaNoiceHaxPhillJKTushar-Khandelwal-2004Tyagiquamarumeraamir69unjicaYIOYIOIOI

Full changelog: v1.7.18...v1.7.19

Action required

  • If you use getTestInstance with testWith: "mysql", run a MySQL server at 127.0.0.1:3306 with the root password set to root_password. (#12244)

better-auth

Bug Fixes

  • Fixed "revoke all sessions" with secondaryStorage and storeSessionInDatabase to also revoke sessions created while the revocation is running, except sessions created by a session.delete.after hook, which stay active (#12259)
  • Fixed getTestInstance from better-auth/test to close its own Postgres connection pool and SQLite database when the test file finishes, while with Vitest's default sequence.hooks: "stack" your afterAll hooks still run first and can keep using the instance (#12250)
  • Fixed getTestInstance with testWith: "mysql" hanging, and added a separate database per instance so several instances can run in one test file (#12244)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • fix(core): accept introspected tokens when verifyOptions.typ is set (#12249)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

gustavovalverde

Full changelog: v1.7.17...v1.7.18

better-auth

Bug Fixes

  • Fixed sessions created by a session.delete.after hook being treated as revoked during "revoke all sessions" when using secondaryStorage with storeSessionInDatabase (#12212)
  • Fixed remembered sign-ins and sign-ups to refresh their session even if an earlier sign-in in the same browser used rememberMe: false (#12181)
  • Fixed denying a device authorization request to reject a revoked session that is still in the cookie cache (#12216)
  • Fixed IP wildcard trusted origins such as exp://192.168.*.*:* matching custom-scheme hosts with out-of-range or zero-padded octets (#12217)
  • Fixed the phone number plugin storing an empty phoneNumber on sign-up and replacing a verified number when linking an account with an empty phone number (#12219)
  • Fixed TOTP verification rejecting API key sessions so they can now finish two-factor enrollment (#12211)
  • Fixed trusted devices being ignored when an app runs the two-factor sign-in step from its own hook on another sign-in path, such as email OTP (#12228)

For detailed changes, see CHANGELOG

@better-auth/expo

Bug Fixes

  • Fixed Expo social sign-in to reject authorization URLs without a state parameter when OAuth state is stored in a cookie (#12218)

For detailed changes, see CHANGELOG

@better-auth/kysely-adapter

Bug Fixes

  • Fixed MySQL create with generateId: "serial" leaving an inserted row behind when the table reports no auto-increment id (#12220)

For detailed changes, see CHANGELOG

@better-auth/passkey

Bug Fixes

  • Fixed passkey registration and sign-in when one passkey() plugin is shared between auth instances where only some set baseURL (#12225)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

aliamanatalibytaesu

Full changelog: v1.7.16...v1.7.17

better-auth

Bug Fixes

  • Fixed revoked sessions staying usable with secondary storage or the cookie cache. Bulk revocation now ends sessions missing from the cached list, and passkey registration, device authorization, two-factor, social account linking, and phone number changes check the session store (#12198)
  • Fixed phone numbers being stored before they are verified. Sign-up and sign-in reject a phoneNumber in the request, social profiles no longer set an unverified number, and verification codes use their own namespace (#12198)
  • Fixed /admin/update-user changing phone numbers without permission. It now requires user:set-phone, so add set-phone to custom access control statements (#12198)
  • Fixed email OTP accepting more guesses than allowedAttempts under concurrent requests, and bound email change codes to the requesting account (#12198)
  • Fixed user lookup by email matching a different address on accent-insensitive database collations (#12198)
  • Fixed email verification and change email links working for an account other than the one they were issued to (#12198)
  • Fixed OAuth sign-in treating a string email_verified value such as "false" as verified, and bound generic OAuth profiles to the ID token subject (#12198)
  • Fixed organization roles with extra whitespace passing role checks, and limited pending invitations to members who can manage them (#12198)
  • Fixed wildcard trusted origins matching URLs outside the intended scheme, host, or path (#12198)
  • Fixed anonymous users being linked on a sign-in still waiting for a second factor (#12198)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed the Zoom provider ignoring disableSignUp, requireEmailVerification, and overrideUserInfoOnSignIn (#12198)
  • Fixed string email_verified claims from Cognito and Microsoft Entra ID being read as verified (#12198)

For detailed changes, see CHANGELOG

@better-auth/expo

Bug Fixes

  • Fixed the authorization proxy signing a state the server did not issue and redirecting to hosts that are not configured providers (#12198)

For detailed changes, see CHANGELOG

@better-auth/electron

Bug Fixes

  • Fixed sign-in returning the internal auth context when the transfer cookie is not a transfer request, and bound desktop authorization codes to the browser session that issued them (#12198)

For detailed changes, see CHANGELOG

@better-auth/passkey

Bug Fixes

  • Fixed the expected WebAuthn origin coming from the request instead of server configuration. Set origin when rpID is set and a wildcard in baseURL.allowedHosts covers it (#12198)
  • Fixed userVerification: "required" not being enforced, and applied it to authentication as well as registration (#12198)

For detailed changes, see CHANGELOG

@better-auth/stripe

Bug Fixes

  • Fixed sign-up and update-user requests setting stripeCustomerId. Server code that sets it through auth.api.updateUser must write it through the database adapter instead (#12198)
  • Fixed webhooks attributing a subscription to the wrong record when several records share a Stripe customer ID (#12198)

For detailed changes, see CHANGELOG

@better-auth/kysely-adapter

Bug Fixes

  • Fixed MySQL with generateId: "serial" returning another request's record on connection pools (#12198)

For detailed changes, see CHANGELOG

@better-auth/drizzle-adapter

Bug Fixes

  • Fixed MySQL with generateId: "serial" returning another request's record on connection pools (#12198)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesuBekacrugustavovalverdeAbhishek-B-R

Full changelog: v1.7.15...v1.7.16

better-auth

Bug Fixes

  • Fixed organization and API key metadata, and OAuth proxy sign-ins with a constructor field in additionalData, failing with a prototype pollution error (#12142)
  • Improved BETTER_AUTH_SECRETS error messages to report the entry position instead of including the entry value (#12098)
  • Fixed the admin update-user endpoint to reject data.id with a 400 error instead of attempting to change the user's primary key (#12099)
  • Fixed the admin plugin to reject banned users when a session is created outside an endpoint, such as through internalAdapter.createSession (#12100)
  • Fixed headers and cookies set by a non-returning hooks.before hook being dropped from the response, with the endpoint's value winning when both set the same header or cookie (#12145)
  • Fixed the Vue client's useSession(useFetch) returning no session during Nuxt SSR when baseURL is inferred from the environment (#12109)
  • Fixed the genericOAuth HubSpot helper truncating access tokens with reserved characters and now returning null instead of requesting /access-tokens/undefined when no token is present (#12108)
  • Fixed /sign-in/username and /is-username-available rejecting usernames that sign-up accepts when validationOrder.username is post-normalization (#12097)

For detailed changes, see CHANGELOG

auth

Bug Fixes

  • Fixed auth init for Remix and React Router v7 to generate an app/routes/api.auth.$.ts resource route that mounts auth.handler instead of a second auth instance with an unsupported database option (#12118)
  • Fixed auth ai overwriting MCP config files it cannot parse, such as those with comments or trailing commas, by leaving them unchanged and printing the config to add manually (#12111)
  • Fixed auth login and auth logout re-launching the CLI through npx auth@latest in an endless loop (#12110)
  • Fixed auth init hanging during database migration and removed a stray debug line about path aliases (#12148)

For detailed changes, see CHANGELOG

@better-auth/stripe

Bug Fixes

  • Fixed /subscription/success returning a 500 for non-string callbackURL and checkoutSessionId query values by rejecting them with a 400 (#12105)
  • Fixed /subscription/success to validate callbackURL against trusted origins after replacing {CHECKOUT_SESSION_ID}, preventing redirects to untrusted origins via checkoutSessionId (#12102)

For detailed changes, see CHANGELOG

@better-auth/api-key

Bug Fixes

  • Fixed API keys in secondary storage failing to verify, load, and list when the storage client returns already-parsed JSON, such as @upstash/redis (#12107)

For detailed changes, see CHANGELOG

@better-auth/cimd

Bug Fixes

  • Fixed the Node metadata transport crashing the process on responses with an out-of-range status or invalid reason phrase by reporting the client as invalid_client (#12103)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed built-in social providers following HTTP redirects on token exchange, refresh, verification, and JWKS signing key requests (#12106)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesu

Full changelog: v1.7.14...v1.7.15

better-auth

Bug Fixes

  • Fixed ACCOUNT_NOT_FOUND when retrieving an access token after stateless OAuth sign-in links a new provider to an existing user (#11300)

For detailed changes, see CHANGELOG

@better-auth/sso

Bug Fixes

  • Fixed SAML sign-in for providers that use samlConfig.callbackUrl as their ACS URL without spMetadata.metadata, which had failed with invalid_saml_response since 1.6.21 (#11730)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesugustavovalverde

Full changelog: v1.6.33...v1.6.34

better-auth

Bug Fixes

  • Fixed two-factor TOTP to accept imported Base32 secrets stored as base32:<secret> (#12031)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed Kakao sign-in to forward loginHint so the Kakao Account login page opens with the ID field prefilled (#12045)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesuhonuuk

Full changelog: v1.7.13...v1.7.14

better-auth

Bug Fixes

  • Fixed type declarations so type-only exports are no longer listed as values, making a value import fail type checking instead of failing at runtime (#11985)

For detailed changes, see CHANGELOG

@better-auth/core

Features

  • Added token endpoint authentication options to the Vercel social provider, including dynamic OIDC tokens and private key JWT client assertions, without replacing the built-in sign-in flow (#11948)

Bug Fixes

  • Added tokenEndpointAuth: { method } to the Cloudflare provider and deprecated tokenEndpointAuthMethod, which remains supported (#11997)

For detailed changes, see CHANGELOG

@better-auth/stripe

Features

  • Added support for Stripe SDK v23 in the Stripe plugin (#11954)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

allenzhou101bytaesugodwit-bo

Full changelog: v1.7.12...v1.7.13

Action required

  • If you use ID token sign-in with a provider that has no clientId, set clientId to every client ID your apps sign in with. (#11931)

better-auth

Bug Fixes

  • Fixed the JWT plugin to verify JWTs and session cookie-cache JWTs with the stored key's algorithm instead of the token header's, and to warn when signing or verifying a JWT without an issuer or audience (#11925)
  • Fixed OAuth callbacks completed through the OAuth proxy to run the same checks as the standard OAuth callback, including issuer and ID token nonce validation (#11930)
  • Fixed auth.api.getSession() to keep the original database error as error.cause when the session lookup fails (#11924)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed mapProfileToUser failing to typecheck under exactOptionalPropertyTypes when it returns undefined for name, email, or image (#11918)
  • Fixed ID token sign-in to reject tokens when the provider has no client ID, since their audience cannot be checked (#11931)
  • Fixed a custom Facebook getUserInfo to no longer receive client-submitted access tokens issued to another Facebook app, and ID tokens missing exp or iat are now rejected (#11919)
  • Restored the Twitch and Paybin ID token handling from before 1.7.11, which made account info fail once the ID token stored at sign-in expired (#11920)
  • Added a cause option as a third argument to APIError.from() to keep the underlying error for server-side callers without exposing it in the response (#11924)

For detailed changes, see CHANGELOG

@better-auth/mcp

Bug Fixes

  • Fixed requireMcpAuth to accept only OAuth access tokens and reject session JWTs from the JWT plugin, even when they share the issuer and audience (#11934)

For detailed changes, see CHANGELOG

@better-auth/sso

Bug Fixes

  • Fixed OIDC SSO sign-in to reject ID tokens missing exp or iat and providers with an empty client ID, matching social sign-in (#11935)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

alpcanaydinbytaesu

Full changelog: v1.7.11...v1.7.12

better-auth

Bug Fixes

  • Fixed repeated PostgreSQL migration diffs for int8 columns. (#10719)
  • Fixed database-backed rate limiting returning an excessively large X-Retry-After value. (#11521)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed plugin init returns with options: undefined failing type checks under exactOptionalPropertyTypes. (#11907)
  • Fixed ID token signature and claim validation for Twitch and Paybin sign-in. Custom Paybin issuers must publish RS256 signing keys at <issuer>/.well-known/jwks.json. (#11884)
  • Reduced installation size while preserving OpenTelemetry instrumentation attributes. (#11623)

For detailed changes, see CHANGELOG

@better-auth/oauth-provider

Bug Fixes

  • Fixed OpenAPI schemas for /oauth2/consent and /oauth2/continue to match their redirect responses. (#10881)
  • Fixed CIMD metadata refreshes overwriting concurrent administrator changes to discovered clients. (#11830)

For detailed changes, see CHANGELOG

@better-auth/expo

Bug Fixes

  • Fixed Expo social account linking with ID tokens when a session cookie is present. (#10207)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

aryan1306bytaesucpojergustavovalverdenoobnoocrendermanisahiljagtap08

Full changelog: v1.7.10...v1.7.11

better-auth

Bug Fixes

  • Fixed Captcha and OpenAPI plugin subpath imports and type resolution for better-auth/plugins/multi-session and better-auth/test. (#11822)
  • Fixed Google One Tap sign-ins not recording google as the last login method. (#11393)
  • Fixed imports from better-auth/plugins/one-tap failing with a not-exported error. (#11696)
  • Fixed Google One Tap ignoring plugin-level autoSelect and cancelOnTapOutside settings. (#11820)
  • Fixed Google One Tap sign-ins ignoring configured Google profile mapping and user info updates. (#11819)
  • Fixed Google One Tap calling a prompt method unsupported by FedCM and retrying skipped prompts. (#11821)

For detailed changes, see CHANGELOG

@better-auth/oauth-provider

Features

  • Added optional self-service signing key rotation for private_key_jwt clients. (#11695)

Bug Fixes

  • Fixed valid DPoP proofs being rejected for parameterized routes and URLs with trailing slashes. (#11786)
  • Fixed native clients with HTTP loopback callbacks being rejected when application type inference is enabled. (#11798)
  • Fixed device-code clients being unable to refresh access for approved resources omitted from a token poll. (#11815)
  • Fixed OAuth consent without a reference overwriting or reusing consent for a different reference. (#11801)
  • Fixed dynamic client registration rejecting requests that include both supported and unsupported grants. (#11797)
  • Fixed attempts to change cached trusted clients returning HTTP 500 instead of HTTP 400. (#11781)
  • Improved errors for unknown OAuth client_id values to say client not found. (#11799)
  • Fixed PKCE verifier errors to return the specified HTTP 400 response and error code. (#11724)
  • Fixed unknown OAuth clients receiving invalid_grant instead of invalid_client at the token endpoint. (#11176)
  • Fixed unverifiable JWT access tokens causing server errors at /oauth2/userinfo, /oauth2/introspect, and /oauth2/revoke. (#11596)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Limited JWKS refetches for unknown key IDs to protect servers from repeated requests. (#11805)
  • Fixed unreachable JWKS endpoints being reported as invalid tokens instead of server errors. (#11612)

For detailed changes, see CHANGELOG

@better-auth/mongo-adapter

Bug Fixes

  • Fixed MongoDB findMany ignoring ID sorting and potentially repeating or skipping paginated results. (#11801)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

Bekacrubreken-aidrewsephskigustavovalverdemahoorvhinayindia

Full changelog: v1.7.9...v1.7.10

better-auth

Bug Fixes

  • Fixed onAPIError.onError handlers to finish before responses are sent and log failures without interrupting requests (#11766)

For detailed changes, see CHANGELOG

@better-auth/oauth-provider

Bug Fixes

  • Added isContinuation to postLogin.shouldRedirect so users can complete authorization after selecting an organization (#11185)
  • Fixed DPoP validation for token and UserInfo requests behind proxies that rewrite request URLs (#10799)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesujohanneskares

Full changelog: v1.7.8...v1.7.9

better-auth

Bug Fixes

  • Aligned cookie security attributes with RFC 6265bis (#11540)
  • Added SvelteKit 3 to the supported peer dependency range (#11488)
  • Fixed stale cookies persisting after customSession sessions expire or are revoked (#10591)
  • Fixed customSession treating session lookup errors as signed-out users (#11391)
  • Fixed sign-in failures, replay checks, and SIWE email handling with generateId: "uuid" (#11625)
  • Removed non-returned custom fields from inferred output schema types (#11565)
  • Fixed Kysely migration foreign keys when custom table names match another model key (#11505)
  • Reduced organization plugin server bundles by excluding unused Zod locales (#10866)
  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)
  • Fixed generic OAuth providers remaining unavailable after discovery fails at startup by retrying on subsequent requests (#11750)
  • Fixed lastLoginMethod sign-in failures when cookieName or maxAge is explicitly undefined (#11549)
  • Fixed magic link verification changing percent-encoded characters in callback URLs (#11174)
  • Fixed type errors when using oauthProvider() or mcp() with exactOptionalPropertyTypes (#10266)
  • Fixed organization plugin type errors in projects with skipLibCheck: false (#11637)
  • Fixed failed password resets consuming reset links or OTPs before the new password is saved (#11646)
  • Fixed password resets and changes retaining the new password when database session revocation fails (#11626)
  • Fixed phone number password resets to use a configured verifyOTP callback (#10698)
  • Fixed secondary-storage session failures leaving sign-ups, passkey registrations, or SSO sign-ins in an inconsistent state (#11643)
  • Fixed missing device sessions and failed automatic session switching after cache eviction (#11718)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed ID token sign-in failures caused by up to 30 seconds of clock difference with identity providers (#11749)
  • Fixed Atlassian user info errors being mislabeled as Figma errors in logs (#11592)
  • Fixed authentication requests hanging after interrupted async context initialization (#11711)
  • Fixed recognition of valid AsyncLocalStorage initialized after importing Better Auth but before first use, and corrected misleading errors for invalid runtime-provided values in edge and browser fallbacks. (#11712)
  • Fixed after hooks being skipped for writes retained after a failed request on adapters without transactions (#11645)
  • Fixed Microsoft Entra ID sign-in and account linking with ID tokens when signing keys omit alg (#11663)
  • Fixed sign-in failures, replay checks, and SIWE email handling with generateId: "uuid" (#11625)
  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)
  • Fixed concurrent MongoDB writes failing with transaction conflicts by retrying transient errors (#11515)
  • Added support for host-bearing custom-scheme redirect URIs for native OAuth clients (#10956)
  • Fixed password resets and changes retaining the new password when database session revocation fails (#11626)
  • Fixed secondary-storage session failures leaving sign-ups, passkey registrations, or SSO sign-ins in an inconsistent state (#11643)
  • Fixed missing device sessions and failed automatic session switching after cache eviction (#11718)

For detailed changes, see CHANGELOG

@better-auth/oauth-provider

Features

  • Added support for pausing and resuming OAuth clients through adminUpdateOAuthClient (#11654)
  • Added support for linking protected resources when registering a client with adminCreateOAuthClient (#11655)
  • Added resource identifier validation for adminCreateOAuthResource and configured resources (#11655)
  • Added clientId to clientPrivileges checks for actions on existing OAuth clients (#11658)

Bug Fixes

  • Fixed sign-in failures, replay checks, and SIWE email handling with generateId: "uuid" (#11625)
  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)
  • Added support for host-bearing custom-scheme redirect URIs for native OAuth clients (#10956)
  • Fixed startup resource-seeding failures from blocking authentication routes until restart (#11726)
  • Fixed type errors when using oauthProvider() or mcp() with exactOptionalPropertyTypes (#10266)

For detailed changes, see CHANGELOG

@better-auth/sso

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)
  • Fixed SSO provider registration and updates rejecting partial mapping values that omit defaulted fields (#11378)
  • Fixed SAML providers with linked accounts rejecting IdP signing certificate rotation (#11687)
  • Rejected OIDC SSO providers whose configured issuer does not match discovery, preventing later sign-in failures (#11438)
  • Fixed SAML providers with linked accounts rejecting changes to their post-login callbackUrl (#11743)
  • Fixed OIDC sign-in when the mapped email claim contains a list of addresses (#11640)

For detailed changes, see CHANGELOG

@better-auth/scim

Bug Fixes

  • Fixed SCIM reprovisioning of inactive users with an existing externalId (#11167)
  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)
  • Fixed SCIM requests silently ignoring attribute names with different letter case (#11644)
  • Fixed concurrent SCIM updates to return 409 instead of 500 when a unique value is already claimed (#11669)
  • Fixed SCIM User and Group requests rejecting nullable attributes sent as JSON null (#11638)

For detailed changes, see CHANGELOG

@better-auth/mongo-adapter

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)
  • Fixed failed MongoDB transaction commits leaving transactions open and blocking other writes (#11602)
  • Fixed concurrent MongoDB writes failing with transaction conflicts by retrying transient errors (#11515)
  • Fixed MongoDB authentication errors masking the original transaction commit failure (#11014)

For detailed changes, see CHANGELOG

@better-auth/drizzle-adapter

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)
  • Fixed Drizzle sign-in, session refresh, and date filtering with string-based date columns (#11731)

For detailed changes, see CHANGELOG

@better-auth/kysely-adapter

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)
  • Fixed cross-request I/O errors from concurrent D1 queries on a shared auth instance with Kysely 0.29 (#11490)

For detailed changes, see CHANGELOG

@better-auth/mcp

Bug Fixes

  • Fixed @better-auth/mcp type errors with exactOptionalPropertyTypes and skipLibCheck: false (#11635)
  • Fixed type errors when using oauthProvider() or mcp() with exactOptionalPropertyTypes (#10266)

For detailed changes, see CHANGELOG

@better-auth/api-key

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)

For detailed changes, see CHANGELOG

@better-auth/cimd

Bug Fixes

  • Added support for host-bearing custom-scheme redirect URIs for native OAuth clients (#10956)

For detailed changes, see CHANGELOG

@better-auth/electron

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)

For detailed changes, see CHANGELOG

@better-auth/memory-adapter

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)

For detailed changes, see CHANGELOG

@better-auth/passkey

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)

For detailed changes, see CHANGELOG

@better-auth/prisma-adapter

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)

For detailed changes, see CHANGELOG

@better-auth/stripe

Bug Fixes

  • Stopped reporting completed one-time Stripe checkouts as webhook failures (#9684)

For detailed changes, see CHANGELOG

@better-auth/telemetry

Bug Fixes

  • Aligned @better-auth/utils and better-call dependency versions across official packages (#11512)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

aryan1306BekacruBilalAtiquebreken-aibytaesucodewithbharatdisbelldrewsephskigustavovalverdeheliohmjashkarangiyajonathansamineskaiizer777kdelaymaxnze1nikhilgupta58SandipxgshiminshenTushar-Khandelwal-2004

Full changelog: v1.7.7...v1.7.8

better-auth

Magic Link upgrade: Upgrade servers sharing verification storage together, request new Magic Links, and restart pending OAuth/SAML sign-ins. No database migration is required. See the critical advisory for affected configurations and custom storage changes.

Bug Fixes

  • Fixed a critical Magic Link account-takeover vulnerability. (#11494)
  • Fixed ID-token sign-in ignoring the social provider’s disableSignUp setting. (#11491)
  • Fixed OAuth Proxy accepting sign-in state as a provider profile. (#11494) Upgrade all OAuth Proxy participants together; see the OAuth Proxy upgrade guidance.
  • Fixed CAPTCHA errors missing the JSON Content-Type header. (#11476)
  • Fixed the active organization failing to refresh after sign-in when a session hook selects the initial organization. (#11375)
  • Fixed rate-limit errors missing the JSON Content-Type header. (#11469)

For detailed changes, see CHANGELOG

@better-auth/oauth-provider

Features

  • Added optional validateRedirectUri validation for trusted deployments with dynamic OAuth redirect URIs. (#8686)
  • Added verifyOAuthQueryParams to verify signed authorization queries before rendering a custom consent page. (#11402)

For detailed changes, see CHANGELOG

@better-auth/drizzle-adapter

Bug Fixes

  • Fixed concurrent PostgreSQL requests exceeding database-backed rate limits. (#11331)

For detailed changes, see CHANGELOG

@better-auth/kysely-adapter

Bug Fixes

  • Fixed consumeOne deleting a record after a concurrent write invalidates its original condition. (#11495)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

aryan1306bytaesugitmotiongustavovalverdelennondotw

Full changelog: v1.7.6...v1.7.7

better-auth

Features

  • Added support for a bannedUserMessage function that receives the banned user, allowing sign-in errors to include details such as the ban reason. (#11325)
  • Added Vercel BotID as a captcha provider for protected authentication routes. (#11016)

Bug Fixes

  • Passwords over maxPasswordLength are now rejected with PASSWORD_TOO_LONG before hashing or verification. (#11324)
  • Fixed React hydration mismatches when session or plugin auth queries resolve before streamed components hydrate. (#11316)
  • Prevented older auth-query responses from overwriting newer results when requests overlap. (#11376)
  • Fixed model identity when a custom model name matches another schema key. (#11333)
  • Fixed schema validation for Cloudflare D1 when the Kysely dialect cannot introspect the database. (#11366)
  • Fixed social account linking through the OAuth Proxy plugin. (#11268)

For detailed changes, see CHANGELOG

@better-auth/kysely-adapter

Bug Fixes

  • Fixed model identity when a custom model name matches another schema key. (#11333)
  • Fixed schema validation for SQLite-generated primary keys, including INTEGER PRIMARY KEY columns without AUTOINCREMENT. (#11374)
  • Fixed schema validation for Cloudflare D1 when the Kysely dialect cannot introspect the database. (#11366)

For detailed changes, see CHANGELOG

@better-auth/prisma-adapter

Bug Fixes

  • Fixed model identity when a custom model name matches another schema key. (#11333)
  • Fixed schema validation for capitalized custom Prisma model names. (#11319)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed model identity when a custom model name matches another schema key. (#11333)

For detailed changes, see CHANGELOG

@better-auth/drizzle-adapter

Bug Fixes

  • Fixed model identity when a custom model name matches another schema key. (#11333)

For detailed changes, see CHANGELOG

@better-auth/memory-adapter

Bug Fixes

  • Fixed model identity when a custom model name matches another schema key. (#11333)

For detailed changes, see CHANGELOG

@better-auth/mongo-adapter

Bug Fixes

  • Fixed model identity when a custom model name matches another schema key. (#11333)

For detailed changes, see CHANGELOG

@better-auth/stripe

Bug Fixes

  • Fixed automatic seat updates after an organization resubscribes, even when canceled subscriptions remain in its history. (#11347)

For detailed changes, see CHANGELOG

auth

Features

  • Added read-only check and check schema commands to validate your configured adapter schema on demand. (#11314)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesudavbritorwieruchSmidgeWadiouXXMOHAMED012

Full changelog: v1.7.5...v1.7.6

better-auth

Features

  • Added database.schemaName support for direct PostgreSQL connections. (#11203)

Bug Fixes

  • Improved server-side logging for Cloudflare Turnstile verification failures. (#11283)
  • Fixed PostgreSQL migrations incorrectly identifying tables and views across schemas. (#11270)
  • Fixed MySQL index validation for existing string columns. (#11272)
  • Removed the unused optional better-sqlite3 peer dependency to prevent installation conflicts. (#11209)

For detailed changes, see CHANGELOG

@better-auth/core

Features

  • Added database.schemaName support for direct PostgreSQL connections. (#11203)

Bug Fixes

  • Fixed database option type inference outside Cloudflare Workers. (#11290)

For detailed changes, see CHANGELOG

@better-auth/cimd

Bug Fixes

  • Fixed unnecessary pacing of consecutive CIMD OAuth requests when metadata cannot be cached. (#11161)

For detailed changes, see CHANGELOG

@better-auth/drizzle-adapter

Bug Fixes

  • Fixed lazy database initialization when using Drizzle relations. (#11263)

For detailed changes, see CHANGELOG

@better-auth/kysely-adapter

Features

  • Added database.schemaName support for direct PostgreSQL connections. (#11203)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesudshukertjrsiam923

Full changelog: v1.7.4...v1.7.5

@better-auth/core

Bug Fixes

  • Fixed database option type inference for projects that do not use Cloudflare Workers. (#11291)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

better-release

Full changelog: v1.6.32...v1.6.33

better-auth

Bug Fixes

  • Improved diagnostics for Cloudflare Turnstile verification failures (#11286)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

better-release

Full changelog: v1.6.31...v1.6.32

better-auth

Features

  • Added experimental.instrumentation.enabled to disable OpenTelemetry span creation per auth instance. (#11224)
  • Added support for additional session fields in testUtils auth helpers. (#11217)
  • Added Vitest 5 support to the testing utilities. (#11205)

For detailed changes, see CHANGELOG

@better-auth/core

Features

  • Added experimental.instrumentation.enabled to disable OpenTelemetry span creation per auth instance. (#11224)

Bug Fixes

  • Fixed Metro bundling when the optional OpenTelemetry API is not installed. (#11210)

For detailed changes, see CHANGELOG

@better-auth/expo

Bug Fixes

  • Fixed multibyte session data storage in Expo SecureStore. (#11238)
  • Fixed stale Expo secure-storage session data and corrupted cookies during concurrent updates. (#11200)

For detailed changes, see CHANGELOG

@better-auth/drizzle-adapter

Bug Fixes

  • Improved schema validation for the Drizzle Relations v2 adapter. (#11213)

For detailed changes, see CHANGELOG

@better-auth/test-utils

Features

  • Added Vitest 5 support to the testing utilities. (#11205)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesuonmax

Full changelog: v1.7.3...v1.7.4

better-auth

Features

  • Added an option to disable OpenTelemetry span creation for individual auth instances (#11228)

For detailed changes, see CHANGELOG

@better-auth/core

Features

  • Added an option to disable OpenTelemetry span creation for individual auth instances (#11228)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

better-release

Full changelog: v1.6.30...v1.6.31

Upgrading from 1.7.0–1.7.2:

We restored the 1.6 account core schema to avoid requiring a disruptive backfill for existing users. We recognize the cost to users who already migrated and are committed to keeping the core schema stable throughout v1.

If you applied the 1.7 issuer schema, follow the upgrade guide for the required cleanup. No backfill is needed.

better-auth

Features

  • Added Cloudflare as a built-in social provider with client-secret and PKCE support. (#9908)
  • Enabled schema validation during initialization by default, including in production, and rejected authentication requests on detected mismatches. (#11178)
  • Added isPasswordCompromised for checking passwords against Have I Been Pwned in custom server-side flows. (#11147)

Bug Fixes

  • Aligned generated OpenAPI required fields with runtime validation. (#11066)
  • Handled malformed custom-scheme callback URLs without excessive processing. (#11060)
  • Improved Auth0 domain normalization to avoid slow trailing-slash processing. (#11188)
  • Prevented generic OAuth discovery failures from taking down the authentication API. (#10978)
  • Tracked email OTP sign-ins in the last login method plugin. (#10963)
  • Fixed callback hooks being skipped after proxied OAuth sign-ins and preserved server state when callback cookies are unavailable. The legacy /oauth-proxy-callback endpoint is deprecated and will be removed in the next minor release. (#10988)
  • Fixed getSession failures when cookie caching is disabled and cached session cookies remain. (#11120)
  • Fixed TOTP re-enrollment replacing an active authenticator and its backup codes. (#11037)
  • Prevented duplicate session requests and hydration mismatches in Nuxt useFetch. (#11084)
  • Improved dynamic organization role permission check performance. (#11069)
  • Added type-safe Nuxt useFetch integration for the Vue client's useSession hook. (#11085)
  • Restored compatibility with 1.6 account schemas by identifying accounts with (providerId, accountId) instead of issuer. (#11153)

For detailed changes, see CHANGELOG

@better-auth/core

Features

  • Added Cloudflare as a built-in social provider with client-secret and PKCE support. (#9908)
  • Added initialization-time schema validation and actionable mismatch guidance for Drizzle and Prisma adapters. (#11179)
  • Enabled schema validation during initialization by default, including in production, and rejected authentication requests on detected mismatches. (#11178)
  • Added custom token endpoint authentication strategies for providers with non-standard request parameters. (#11101)

Bug Fixes

  • Restored optional consumeOne and incrementOne methods for custom database adapters. (#11189)
  • Fixed TikTok sign-in and token refresh with the documented clientKey and clientSecret options. (#11102)
  • Improved request IP validation performance. (#11068)
  • Improved PayPal authorization code and refresh token requests, including PKCE handling. (#11129)
  • Improved Reddit token requests with OAuth-compliant Basic authentication and redirect protection. (#11134)
  • Restored compatibility with 1.6 account schemas by identifying accounts with (providerId, accountId) instead of issuer. (#11153)

For detailed changes, see CHANGELOG

auth

Features

  • Added Cloudflare as a built-in social provider with client-secret and PKCE support. (#9908)
  • Added diagnostics in auth generate for required fields in existing Prisma schemas that Better Auth never writes. (#11179)
  • Added Codex as a supported target for configuring the Better Auth documentation MCP server. (#11100)
  • Added schema diagnostics to auth migrate and auth generate, blocking migrations when required columns that Better Auth never writes need manual repair. (#11178)

Bug Fixes

  • Updated auth info to report installed dependency versions instead of declared specifiers. (#11126)
  • Allowed auth init to complete when generated setup groups have no dependencies. (#11140)
  • Skipped unsupported dependency specifiers during auth upgrade with a clear warning. (#11127)

For detailed changes, see CHANGELOG

@better-auth/drizzle-adapter

Features

  • Added initialization-time schema validation and actionable mismatch guidance for Drizzle and Prisma adapters. (#11179)

For detailed changes, see CHANGELOG

@better-auth/test-utils

Bug Fixes

  • Improved adapter test suite performance by avoiding redundant cleanup queries. (#10762)
  • Updated adapter test suites to remove issuer-specific account requirements. (#11153)

For detailed changes, see CHANGELOG

@better-auth/cimd

Bug Fixes

  • Fixed CIMD client metadata discovery failures with ERR_INVALID_IP_ADDRESS on supported Node.js versions. (#10730)

For detailed changes, see CHANGELOG

@better-auth/expo

Bug Fixes

  • Prevented Expo apps from sending unauthenticated requests during interrupted cookie storage updates. (#11099)

For detailed changes, see CHANGELOG

@better-auth/kysely-adapter

Features

  • Enabled database schema validation by default and rejected authentication requests when the live schema does not match. (#11178)

For detailed changes, see CHANGELOG

@better-auth/oauth-provider

Bug Fixes

  • Allowed native OAuth clients using localhost loopback redirects to use ephemeral callback ports. (#11090)

For detailed changes, see CHANGELOG

@better-auth/prisma-adapter

Features

  • Added initialization-time schema validation and actionable mismatch guidance for Drizzle and Prisma adapters. (#11179)

For detailed changes, see CHANGELOG

@better-auth/sso

Bug Fixes

  • Restored compatibility with 1.6 account schemas by identifying accounts with (providerId, accountId) instead of issuer. (#11153)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

BetterAndBetterIIbytaesuerikpr1994gustavovalverdeharshil1712onmaxSalman-Arshadstarslingdevsupercell02thisismert

Full changelog: v1.7.2...v1.7.3

better-auth

Bug Fixes

  • Fixed permanent user bans to clear expiration dates from previous temporary bans. (#10823)
  • Fixed client types with more plugins being assignable to types declaring fewer plugins. (#10907)
  • Added warnings for invalid signed session data in the cookie cache. (#10934)
  • Fixed disabled MyISAM indexes from satisfying migration index checks. (#10877)
  • Fixed programmatic migrations on Cloudflare D1 while preserving existing-index validation. (#10875)
  • Allowed ~ in relative callback URLs validated by trusted-origin checks. (#10041)
  • Improved validation of relative callback and redirect URLs with paths, queries, and fragments. (#10979)
  • Allowed same-origin form submissions with Referrer-Policy: no-referrer while continuing to reject untrusted origins. (#10959)
  • Improved getTestInstance performance with a faster default password hasher. (#10879)
  • Standardized built-in placeholder emails to the namespaced {identifier}@{namespace}.placeholder.invalid format. (#10982)

For detailed changes, see CHANGELOG

@better-auth/core

Bug Fixes

  • Fixed async context loss in Cloudflare Workers bundles with multiple runtime conditions. (#10855)
  • Fixed auth request logs to respect the configured logger, log level, and disabled setting. (#10939)
  • Improved validation of relative callback and redirect URLs with paths, queries, and fragments. (#10979)
  • Standardized built-in placeholder emails to the namespaced {identifier}@{namespace}.placeholder.invalid format. (#10982)
  • Added synchronous and optional access to the current auth endpoint context. (#10938)

For detailed changes, see CHANGELOG

@better-auth/oauth-provider

Bug Fixes

  • Fixed Client ID Metadata Document registration when clients share at least one supported grant with the server. (#11010)
  • Improved validation of relative callback and redirect URLs with paths, queries, and fragments. (#10979)
  • Fixed relative redirect URLs containing fragments. (#10983)

For detailed changes, see CHANGELOG

@better-auth/drizzle-adapter

Bug Fixes

  • Fixed one-to-one Drizzle relations when usePlural is enabled. (#10941)
  • Added validation for missing Drizzle schema fields in compound where clauses. (#10859)

For detailed changes, see CHANGELOG

@better-auth/kysely-adapter

Bug Fixes

  • Fixed programmatic migrations on Cloudflare D1 while preserving existing-index validation. (#10875)

For detailed changes, see CHANGELOG

@better-auth/sso

Bug Fixes

  • Improved validation of relative callback and redirect URLs with paths, queries, and fragments. (#10979)

For detailed changes, see CHANGELOG

Contributors

Thanks to everyone who contributed to this release:

bytaesuGautamBytesheliohmsosyzstarslingdev

Full changelog: v1.7.1...v1.7.2