Better Auth Release Notes
134 release notes curated from 1 source by the Releasebot Team. Last updated: Oct 1, 2026
Better Auth Products
- Sep 30, 2026
- Date parsed from source:Sep 30, 2026
- First seen by Releasebot:Oct 1, 2026
v1.7.7
Better Auth ships a security-focused update with a critical Magic Link takeover fix, safer OAuth and SAML sign-in handling, and new OAuth provider validation options. It also improves CAPTCHA and rate-limit responses and includes adapter reliability fixes.
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:
@aryan1306, @bytaesu, @gitmotion, @gustavovalverde, @lennondotw
Full changelog: v1.7.6...v1.7.7
Original source - Sep 24, 2026
- Date parsed from source:Sep 24, 2026
- First seen by Releasebot:Sep 24, 2026
v1.7.6
Better Auth releases new auth features and fixes, adding banned user messages, Vercel BotID captcha support, and on-demand schema validation commands, while improving password checks, React hydration, query handling, social account linking, and adapter and Stripe stability.
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:
@bytaesu, @davbrito, @rwieruch, @Smidge, @Wadiou, @XXMOHAMED012
Full changelog: v1.7.5...v1.7.6
Original source All of your release notes in one feed
Join Releasebot and get updates from Better Auth and hundreds of other software products.
- Sep 14, 2026
- Date parsed from source:Sep 14, 2026
- First seen by Releasebot:Sep 15, 2026
v1.7.5
Better Auth adds database.schemaName support for direct PostgreSQL connections and fixes PostgreSQL migrations, MySQL index validation, Cloudflare Turnstile logging, Drizzle lazy init, and CIMD OAuth pacing, while removing an unused better-sqlite3 peer dependency.
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:
@bytaesu, @dshukertjr, @siam923
Full changelog: v1.7.4...v1.7.5
Original source - Sep 14, 2026
- Date parsed from source:Sep 14, 2026
- First seen by Releasebot:Sep 15, 2026
v1.6.33
Better Auth fixes database option type inference for non-Cloudflare Workers projects in a bug fix release.
@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[bot]
Full changelog: v1.6.32...v1.6.33
Original source - Sep 14, 2026
- Date parsed from source:Sep 14, 2026
- First seen by Releasebot:Sep 15, 2026
v1.6.32
Better Auth fixes Cloudflare Turnstile verification diagnostics for clearer failure handling.
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[bot]
Full changelog: v1.6.31...v1.6.32
Original source Similar to Better Auth with recent updates:
- xAI release notes269 release notes · Latest Oct 2, 2026
- Anthropic release notes866 release notes · Latest Oct 6, 2026
- OpenAI release notes1094 release notes · Latest Oct 6, 2026
- Vercel release notes2869 release notes · Latest Oct 5, 2026
- Vercel Labs release notes321 release notes · Latest Oct 2, 2026
- Smokeball release notes147 release notes · Latest Oct 2, 2026
- Sep 10, 2026
- Date parsed from source:Sep 10, 2026
- First seen by Releasebot:Sep 10, 2026
v1.7.4
Better Auth adds experimental instrumentation controls, broader test helper support, and Vitest 5 compatibility, while fixing Expo storage issues, Metro bundling, and Drizzle adapter validation for a smoother release across core, Expo, and testing tools.
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:
@bytaesu, @onmax
Full changelog: v1.7.3...v1.7.4
Original source - Sep 10, 2026
- Date parsed from source:Sep 10, 2026
- First seen by Releasebot:Sep 10, 2026
v1.6.31
Better Auth adds per-instance control to disable OpenTelemetry span creation for auth flows.
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[bot]
Full changelog: v1.6.30...v1.6.31
Original source - Sep 6, 2026
- Date parsed from source:Sep 6, 2026
- First seen by Releasebot:Sep 6, 2026
v1.7.3
Better Auth releases broader Cloudflare social login support, default schema validation at init, and new password compromise checks, while fixing OAuth, session, TOTP, Nuxt, and adapter issues. It also restores 1.6 schema compatibility and tightens diagnostics across the stack.
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:
@BetterAndBetterII, @bytaesu, @erikpr1994, @gustavovalverde, @harshil1712, @onmax, @Salman-Arshad, @starslingdev[bot], @supercell02, @thisismert
Full changelog: v1.7.2...v1.7.3
Original source - Aug 26, 2026
- Date parsed from source:Aug 26, 2026
- First seen by Releasebot:Aug 28, 2026
v1.7.2
Better Auth ships bug fixes and validation improvements across auth, OAuth, SSO, and database adapters, including stronger redirect and callback checks, Cloudflare D1 migration fixes, better session warnings, and cleaner placeholder emails.
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:
@bytaesu, @GautamBytes, @heliohm, @sosyz, @starslingdev[bot]
Full changelog: v1.7.1...v1.7.2
Original source - Aug 18, 2026
- Date parsed from source:Aug 18, 2026
- First seen by Releasebot:Aug 19, 2026
v1.7.1
Better Auth releases bug fixes and compatibility updates across core auth, SCIM, SSO, CIMD, and the Kysely adapter, including native transaction support, stronger SAML and SCIM handling, smarter metadata caching, improved scope errors, and updated bundled dependencies.
better-auth
Bug Fixes
Added native database transaction support to test instances for PostgreSQL and MySQL.
Updated bundled dependencies (jose, nanostores, noble crypto packages, SimpleWebAuthn) to their latest compatible releases, with no changes required to existing projects.
For detailed changes, see CHANGELOG
@better-auth/scim
Bug Fixes
Fixed case-insensitive parsing of string Boolean values for SCIM User active and the primary sub-attribute of emails, phoneNumbers, addresses, roles, and entitlements at the HTTP ingress, improving Microsoft Entra interoperability.
Added an optional SCIM-owned connection and credential catalog: configure managedConnections to allow trusted server code to create runtime tenant connections and issue, rotate, and revoke bearer credentials through server-only auth.api methods, without a code-defined connection or an application-owned verifier.
Fixed an issue where trusted server code could not retain a terminal connection binding before a dynamic SCIM connection's first authenticated request when supplying a provisioning domain during decommissioning.
For detailed changes, see CHANGELOG
@better-auth/sso
Bug Fixes
Fixed SSO provider registration to allow reusing a SCIM connection ID, as SCIM connections no longer participate in the authentication provider namespace.
Fixed SAML assertion signature verification to validate signatures on the raw assertion instead of trusting an already-parsed response, and enforced signing policy and size limits on SP metadata. wantAssertionsSigned now correctly controls whether the SP requires signed assertions, matching real-world IdP signing behavior.
For detailed changes, see CHANGELOG
@better-auth/cimd
Bug Fixes
Fixed Client ID Metadata Document caching to follow shared-cache freshness rules: the plugin now prefers s-maxage over max-age and Expires, honors s-maxage=0, conditionally revalidates with ETag or Last-Modified, and treats invalid or duplicate freshness directives as immediately stale. Concurrent refreshes now converge on a single client-resource link instead of failing on a unique constraint.
For detailed changes, see CHANGELOG
@better-auth/kysely-adapter
Bug Fixes
Fixed native adapter transactions for raw database instances (better-sqlite3, node:sqlite, bun:sqlite, mysql2, pg) passed directly as database, matching the behavior of the explicit { db }/{ dialect } config shapes. Plugins requiring native transactions (such as @better-auth/scim) now work correctly when using the quickstart database: new Database(...) form.
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
Bug Fixes
Fixed scope error responses so MCP clients now receive a 403 with an RFC 6750 insufficient_scope WWW-Authenticate challenge naming every missing scope, allowing clients to request all needed scopes in a single authorization request.
For detailed changes, see CHANGELOG
auth
Bug Fixes
Fixed the CLI to refuse adding required columns without default values to already-populated tables (#10863)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@gustavovalverde
Full changelog: v1.7.0...v1.7.1
Original source - Aug 18, 2026
- Date parsed from source:Aug 18, 2026
- First seen by Releasebot:Aug 18, 2026
- Modified by Releasebot:Aug 19, 2026
v1.7.0
Better Auth 1.7 ships major auth and SSO upgrades, stable database joins, stronger OAuth and OIDC controls, MCP split into its own package, and broader security hardening across sessions, SCIM, Electron, Expo, and passkeys.
Blog post: Better Auth 1.7
better-auth
❗ Breaking Changes
Moved database joins out of experimental into the stable advanced.database.joins option (#10359)
Migration: Replace experimental: { joins: true } with advanced: { database: { joins: true } }. Drizzle and Prisma users should regenerate their schema (npx auth@latest generate) so it includes the required relations.
Scoped account identity by trusted issuer, keying accounts on (issuer, accountId) (#10403)
Migration: Accounts now require Account.issuer. Read provider identity from accountInfo.account.accountId, drop mapping.id from SSO configs, and give the microsoftEntraId helper a concrete tenant GUID. Apply the account-identity backfill in the 1.7 upgrade guide before deploying.
Required captcha endpoint entries to match full auth paths, with wildcard support (#10004)
Migration: Replace partial paths such as /sign-in with explicit wildcards like /sign-in/* or /sign-in/**.
Moved the MCP plugin into its own @better-auth/mcp package built on the OAuth provider (#9992)
Migration: Install @better-auth/mcp and @better-auth/cimd, add the now-required jwt() plugin, and move options nested under oidcConfig to flat mcp({ ... }) options. Rename withMcpAuth to requireMcpAuth and mcpHandler to createMcpProtectedRequestHandler. Regenerate the schema (npx auth migrate): oauthApplication becomes oauthClient, plus new oauthRefreshToken and oauthClientAssertion tables.
Added OIDC back-channel logout so ending a session cuts off every connected app's API access (#9304)
Migration: Introspecting an access token whose session has ended now returns { active: false }, and /oauth2/userinfo rejects it. Clients opt into notifications by registering backchannel_logout_uri. Run the schema migration for the new oauthClient and oauthAccessToken columns.
Modeled OAuth protected resources explicitly, with per-resource TTLs, scopes, claims, and signing pins (#9648)
Migration: validAudiences is removed: move each resource identifier into resources and link restricted clients through oauthClientResource. @better-auth/mcp now requires an explicit resource. Run npx @better-auth/cli generate and apply the migration before deploying.
Decoupled SCIM provisioning from the organization plugin (#10390)
Migration: SCIM configuration, client APIs, database schema, and the Group model are all replaced, and provisioning state cannot migrate in place. Follow the SCIM cutover in the 1.7 upgrade guide, including a full directory reprovision, before resuming traffic.
Added OTP-only two-factor enablement with a discriminated enableTwoFactor response (#9057)
Migration: enableTwoFactor now returns a method field ("otp" or "totp"); narrow on it before reading totpURI and backupCodes. Pass method: "otp" for OTP enrollment, which requires otpOptions.sendOTP.
Resolved the auth origin from Host by default when using a dynamic baseURL (#9134)
Migration: If your proxy exposes the public hostname only through x-forwarded-host, set advanced.trustedProxyHeaders: true. Deployments where the proxy rewrites Host (nginx default, Vercel, Cloudflare, Netlify) are unaffected.
Added unique lookup indexes for the device authorization deviceCode and userCode columns (#10059)
Migration: Resolve duplicate code values before applying the migration. MySQL and SQL Server installations must also convert both columns to bounded strings and clean up values longer than 191 characters.
Enforced S256 PKCE in the Electron sign-in flow and hardened custom-scheme origin checks (#9645)
Migration: Upgrade the @better-auth/electron client and server together and add your app's scheme to trustedOrigins. The code_challenge_method parameter and disableOriginOverride option are removed, and host-bearing custom-scheme entries now match that host exactly.
Identified Microsoft Entra accounts by the stable oid claim (#10204)
Migration: Migrate existing Microsoft account rows created from sub before upgrading. Tokens without a valid oid are rejected.
Required a Google client ID before Google One Tap verifies ID tokens (#10036)
Migration: Configure oneTap({ clientId }) or socialProviders.google.clientId.
Removed the deprecated oidcProvider plugin (#10031)
Migration: Move OIDC authorization-server integrations to @better-auth/oauth-provider.
Rewrote the generic OAuth plugin as a first-class social provider with OAuth 2.1 defaults (#9069)
Migration: Replace signIn.oauth2({ providerId }) with signIn.social({ provider }), oauth2.link() with linkSocial(), and drop genericOAuthClient(). Callbacks move to /api/auth/callback/:id, pkce now defaults to true, and issuer and requireIssuerValidation are removed in favor of OIDC discovery.
Separated OAuth device grant ownership into oauthDeviceAuthorization() (#10746)
Migration: The OAuth integration replaces the optional resource column with oauthClientId and resources, so regenerate and apply the schema. Let pending device codes expire before upgrading from an earlier 1.7 prerelease.
Verified provider id_tokens with a single shared verifier (#9828)
Migration: Custom UpstreamProvider implementations replace the removed verifyIdToken method with an idToken config carrying a JWKS source, issuer, and audience. PayPal client id_token sign-in now returns ID_TOKEN_NOT_SUPPORTED; its redirect flow is unchanged.
Features
Added clientAssertion support to the Microsoft Entra ID social provider (#9898)
Made the Auth instance directly fetchable (#9431)
Added per-provider requireEmailVerification for social sign-in (#9929)
Added a user.validateUserInfo gate for rejecting an identity before a user is created or linked (#9864)
Added hydrateSession so useSession returns server-fetched data on the first render (#8733)
Added compound table indexes to plugin database schemas (#10402)
Added allowIdpInitiated support for IdP-initiated flows through a secure server-side bounce (#9301)
Added RP-initiated logout so signOut() can also sign users out of the OpenID provider (#9368)
Added refreshTokenParams for forwarding extra parameters on generic OAuth token refresh (#9948)
Verified discovery id_tokens against the provider JWKS and enabled id_token sign-in for generic OAuth (#9966)
Added the OAuth device authorization grant (RFC 8628) (#10135)
Added DPoP sender-constrained access tokens (RFC 9449) (#10039)
Added the at_hash claim to ID tokens issued alongside an access token, per OIDC Core §3.1.3.6 (#9079)
Added private_key_jwt client authentication for token endpoint requests (RFC 7523) (#8836)
Sent Cache-Control: no-store on every OAuth response that carries credentials (#10065)
Added per-request additionalParams and loginHint across signIn.social, linkSocial, and signIn.sso (#9305)
Added a server-trusted OAuth state channel, fixing anonymous account linking in in-app browsers (#9930)
Allowed passing userId and organizationId to the listUserTeams API (#8977)
Added organization.getOrganization() for metadata-only fetches (#10397)
Added a server-only consumePhoneNumberOTP API for custom phone OTP flows (#9766)
Added JWKS-backed asymmetric JWTs for the session cookie cache (#8931)
Added transactional OIDC user resolution for SSO sign-ins (#10473)
Added an immutable username option (#9240)
Allowed omitting the username plugin's separate displayUsername field (#10330)
Bug Fixes
Allowed test instances to enable native database transactions for PostgreSQL and MySQL.
Refreshed bundled dependencies (jose, nanostores, the noble crypto packages, and SimpleWebAuthn) to their latest compatible releases. These updates are backward compatible and require no changes to existing projects.
Widened the drizzle-kit peer dependency range (#10299)
Decoupled the session cookie cache from JWT plugin internals (#10666)
Allowed auth migrate to add required columns with static defaults and nullable unique columns to existing tables (#10293)
Bound the ID token nonce to the authorization request in the generic OAuth redirect flow (#10095)
Fixed a sign-up deadlock when JWT cookie caching ran on a single-connection SQLite database with native transactions (#10622)
Created new OAuth accounts inside the user creation transaction (#10125)
Derived the OAuth redirect_uri from the per-request base URL in multi-host deployments (#10127)
Preserved previously granted account.scope values across re-authentication and token refresh (#10128)
Preserved the resolved OAuth user when overrideUserInfo returns null (#10124)
Fired session-delete hooks and revoked bound OAuth tokens for preserved sessions on secondaryStorage (#9969)
Issued SIWE nonces before the wallet address and chain ID are known (#10234)
Fixed client plugin composition so One Tap, Electron, and Expo type-check with createAuthClient (#10505)
Single-sourced HTTP Basic credential encoding and decoding for OAuth client authentication (#9657)
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
❗ Breaking Changes
Moved the MCP plugin into its own @better-auth/mcp package built on the OAuth provider (#9992)
Migration: Install @better-auth/mcp and @better-auth/cimd, add the now-required jwt() plugin, and move options nested under oidcConfig to flat mcp({ ... }) options. Rename withMcpAuth to requireMcpAuth and mcpHandler to createMcpProtectedRequestHandler. Regenerate the schema (npx auth migrate): oauthApplication becomes oauthClient, plus new oauthRefreshToken and oauthClientAssertion tables.
Added OIDC back-channel logout so ending a session cuts off every connected app's API access (#9304)
Migration: Introspecting an access token whose session has ended now returns { active: false }, and /oauth2/userinfo rejects it. Clients opt into notifications by registering backchannel_logout_uri. Run the schema migration for the new oauthClient and oauthAccessToken columns.
Aligned OAuth client registration and metadata with MCP authorization 2026-07-28 (#10577)
Migration: Add applicationType and nullable clientDiscoveryId columns, deduplicate existing (clientId, resourceId) links before the new compound unique index, then drop the legacy type and public columns. Replace clientCredentialGrantDefaultScopes with per-client clientCredentialsScopes, backfilling every client to [] and reassigning approved machine scopes after an audit. mcp() no longer enables unauthenticated DCR: compose it with cimd() or enable both DCR flags explicitly.
Enforced the max_age authorization request parameter (#9936)
Migration: Users who authenticated longer ago than the requested max_age are now sent back to log in, and the ID token's auth_time reflects the fresh login. Flows that relied on max_age being ignored will prompt again.
Made ID token claim authority explicit, reserving OIDC protocol claims for the provider (#10140)
Migration: customIdTokenClaims, extension claims, and per-issuance idTokenClaims can no longer set protocol claims such as issuer, subject, audience, nonce, auth_time, acr, amr, or azp; use namespaced custom claims instead. ID tokens now carry acr: "0" and discovery advertises only "0".
Modeled OAuth protected resources explicitly, with per-resource TTLs, scopes, claims, and signing pins (#9648)
Migration: validAudiences is removed: move each resource identifier into resources and link restricted clients through oauthClientResource. @better-auth/mcp now requires an explicit resource. Run npx @better-auth/cli generate and apply the migration before deploying.
Bound OAuth client authentication to the grant being issued (#10063)
Migration: Remove grantType from provider.authenticateClient(...), and return { clientId, confirmation? } from a custom OAuthClientAuthenticationStrategy.authenticate instead of a client record.
Bound RFC 8707 resource indicators to the authorization grant (#9836)
Migration: Token and refresh requests may only narrow the authorization's resource; a broader request returns invalid_target. customAccessTokenClaims now receives a resources array in place of the resource string. Run the schema migration to add the new resource columns.
Returned RFC-compliant OAuth error envelopes from validation failures (#9277)
Migration: Authorization errors now redirect to a registered client's trusted redirect URI with state and iss instead of rendering the server error page, and confidential clients must use their registered token_endpoint_auth_method.
Rewrote the generic OAuth plugin as a first-class social provider with OAuth 2.1 defaults (#9069)
Migration: Replace signIn.oauth2({ providerId }) with signIn.social({ provider }), oauth2.link() with linkSocial(), and drop genericOAuthClient(). Callbacks move to /api/auth/callback/:id, pkce now defaults to true, and issuer and requireIssuerValidation are removed in favor of OIDC discovery.
Separated OAuth device grant ownership into oauthDeviceAuthorization() (#10746)
Migration: The OAuth integration replaces the optional resource column with oauthClientId and resources, so regenerate and apply the schema. Let pending device codes expire before upgrading from an earlier 1.7 prerelease.
Features
Added token endpoint client authentication configuration across the OAuth stack (#9625)
Added the @better-auth/cimd Client ID Metadata Document plugin (#9159)
Added the OAuth device authorization grant (RFC 8628) (#10135)
Added DPoP sender-constrained access tokens (RFC 9449) (#10039)
Added an extension surface for registering grants, client authentication methods, discovery metadata, and claim contributors (#10030)
Added a refresh token reuse interval that replays the same response for duplicate refresh requests (#10145)
Allowed confidential DCR clients to complete authorization-code flows without PKCE (#10146)
Added the at_hash claim to ID tokens issued alongside an access token, per OIDC Core §3.1.3.6 (#9079)
Made token introspection consistent across opaque and JWT tokens and scoped it to the audience (#10045)
Exposed the issuing sessionId to id_token claim contributors (#10113)
Honored requested UserInfo claims through a claim registry (#10156)
Removed the silenceWarnings option and the well-known endpoint warnings it suppressed (#10703)
Added protected dynamic client registration using RFC 7591 initial access tokens (#10037)
Added private_key_jwt client authentication for token endpoint requests (RFC 7523) (#8836)
Sent Cache-Control: no-store on every OAuth response that carries credentials (#10065)
Added a server-trusted OAuth state channel, fixing anonymous account linking in in-app browsers (#9930)
Bug Fixes
Enforced RFC 8628 request cardinality and client authentication on the device flow endpoints (#10752)
Accepted the OpenID Provider issuer as the aud of private_key_jwt client assertions (#10811)
Accepted UserInfo bearer tokens sent in a form-encoded request body (#10155)
Allowed nonce-bound confidential clients to request offline_access without PKCE (#10153)
Returned a 401 invalid_token challenge from /oauth2/userinfo for invalid tokens (#10068)
Completed the RP-initiated logout flow with form-encoded POST support and confirmation pages (#10812)
Deferred token revocation and back-channel logout delivery until the session deletion commits (#10472)
Accepted form-encoded POST authorization requests and rejected unsupported OIDC request objects (#10151)
Handled voluntary and essential acr claim requests per OIDC Core (#10790)
Kept profile and email scope claims on the UserInfo response instead of ID tokens (#10152)
Made the private_key_jwt jti single-use atomic across processes (#9964)
Made redirect_uri conditional at the token endpoint, required only when the authorization included one (#10159)
Preserved client key metadata and the requested authentication method during dynamic client registration (#10144)
Redirected authorization requests missing response_type to the verified client redirect URI (#10149)
Rejected authorization code replay with invalid_grant and revoked tokens issued from that code (#10150)
Reported unsupported_token_type when revoking a JWT access token (#9970)
Required the openid scope for authorization requests that use the claims parameter (#10791)
Returned invalid_grant when a client presents a refresh token issued to another client (#10154)
MCP clients that hit a scope wall now learn exactly which scopes to ask for: missing protected scopes produce a 403 with an RFC 6750 insufficient_scope challenge naming every one of them, so clients can request them in a single authorization redirect.
Single-sourced HTTP Basic credential encoding and decoding for OAuth client authentication (#9657)
For detailed changes, see CHANGELOG
@better-auth/core
❗ Breaking Changes
Moved database joins out of experimental into the stable advanced.database.joins option (#10359)
Migration: Replace experimental: { joins: true } with advanced: { database: { joins: true } }. Drizzle and Prisma users should regenerate their schema (npx auth@latest generate) so it includes the required relations.
Scoped account identity by trusted issuer, keying accounts on (issuer, accountId) (#10403)
Migration: Accounts now require Account.issuer. Read provider identity from accountInfo.account.accountId, drop mapping.id from SSO configs, and give the microsoftEntraId helper a concrete tenant GUID. Apply the account-identity backfill in the 1.7 upgrade guide before deploying.
Decoupled SCIM provisioning from the organization plugin (#10390)
Migration: SCIM configuration, client APIs, database schema, and the Group model are all replaced, and provisioning state cannot migrate in place. Follow the SCIM cutover in the 1.7 upgrade guide, including a full directory reprovision, before resuming traffic.
Identified Microsoft Entra accounts by the stable oid claim (#10204)
Migration: Migrate existing Microsoft account rows created from sub before upgrading. Tokens without a valid oid are rejected.
Verified provider id_tokens with a single shared verifier (#9828)
Migration: Custom UpstreamProvider implementations replace the removed verifyIdToken method with an idToken config carrying a JWKS source, issuer, and audience. PayPal client id_token sign-in now returns ID_TOKEN_NOT_SUPPORTED; its redirect flow is unchanged.
Features
Added clientAssertion support to the Microsoft Entra ID social provider (#9898)
Added per-provider requireEmailVerification for social sign-in (#9929)
Added a user.validateUserInfo gate for rejecting an identity before a user is created or linked (#9864)
Added compound table indexes to plugin database schemas (#10402)
Added allowIdpInitiated support for IdP-initiated flows through a secure server-side bounce (#9301)
Added RP-initiated logout so signOut() can also sign users out of the OpenID provider (#9368)
Added refreshTokenParams for forwarding extra parameters on generic OAuth token refresh (#9948)
Added an includeGrantedScopes option to the Google provider (#10129)
Added DPoP sender-constrained access tokens (RFC 9449) (#10039)
Added private_key_jwt client authentication for token endpoint requests (RFC 7523) (#8836)
Sent Cache-Control: no-store on every OAuth response that carries credentials (#10065)
Added per-request additionalParams and loginHint across signIn.social, linkSocial, and signIn.sso (#9305)
Added JWKS-backed asymmetric JWTs for the session cookie cache (#8931)
Added transactional OIDC user resolution for SSO sign-ins (#10473)
Bug Fixes
Routed CIMD client_id SSRF checks through the shared host classifier, which now rejects IPv4-compatible IPv6, the 6to4 relay prefix, and site-local addresses (#10126)
Derived the OAuth redirect_uri from the per-request base URL in multi-host deployments (#10127)
Preserved previously granted account.scope values across re-authentication and token refresh (#10128)
Fixed client plugin composition so One Tap, Electron, and Expo type-check with createAuthClient (#10505)
Single-sourced HTTP Basic credential encoding and decoding for OAuth client authentication (#9657)
For detailed changes, see CHANGELOG
@better-auth/sso
❗ Breaking Changes
Scoped account identity by trusted issuer, keying accounts on (issuer, accountId) (#10403)
Migration: Accounts now require Account.issuer. SSO subjects are protocol-defined (sub for OIDC, signed NameID for SAML) and mapping.id is removed; a manual SAML config without metadata XML must set idpMetadata.entityID. Apply the account-identity backfill in the 1.7 upgrade guide before deploying.
Added rolling SAML certificate rotation by accepting an array of IdP signing certificates (#8805)
Migration: getSSOProvider, listSSOProviders, and updateSSOProvider now always return samlConfig.certificate as an array, so drop any Array.isArray branching. Registration rejects SAML configs with no signing-cert source with CERT_SOURCE_MISSING.
Hardened the validateUserInfo source contract so it cannot be bypassed or spoofed (#9940)
Migration: createUser now fails closed when validateUserInfo is configured but no endpoint context or provisioning source is available. Read SSO metadata from source.sso instead of source.oauth, and handle the source.method values sso-oidc and sso-saml.
Hardened SAML response validation for InResponseTo, audience restriction, and SessionIndex (#9055)
Migration: allowIdpInitiated now defaults to false. Set saml.allowIdpInitiated: true to keep accepting unsolicited SAML responses.
Consolidated the SAML ACS endpoint, made spMetadata optional, and fixed Single Logout (#9117)
Migration: Point your IdP's ACS URL at /sso/saml2/sp/acs/:providerId; /sso/saml2/callback/:providerId is removed. callbackUrl is now the post-auth redirect only, and the unused decryptionPvk, additionalParams, idpMetadata.entityURL, and idpMetadata.redirectURL fields are gone.
Features
Added a user.validateUserInfo gate for rejecting an identity before a user is created or linked (#9864)
Added allowIdpInitiated support for IdP-initiated flows through a secure server-side bounce (#9301)
Added private_key_jwt client authentication for token endpoint requests (RFC 7523) (#8836)
Added per-request additionalParams and loginHint across signIn.social, linkSocial, and signIn.sso (#9305)
Added a server-trusted OAuth state channel, fixing anonymous account linking in in-app browsers (#9930)
Added transactional OIDC user resolution for SSO sign-ins (#10473)
Extended resolveUser to SAML sign-ins and hardened the provider lifecycle (#10621)
Added additionalFields support on ssoProvider (#9445)
Bug Fixes
Allowed an SSO provider registration to reuse a SCIM connection ID, since SCIM connections no longer share the authentication provider namespace.
Rejected redirecting OIDC discovery, token, userinfo, and JWKS endpoints so SSO works on Cloudflare Workers (#10072)
Updated samlify to 2.13.1 for a signed-assertion XML injection fix (#9821)
Upgraded samlify to 2.12.0 with XPath injection and XXE fixes (#9121)
Single-sourced HTTP Basic credential encoding and decoding for OAuth client authentication (#9657)
Verified SAML assertion signatures directly instead of trusting an already-parsed response, and applied the same signing policy and size limit to SP metadata as to IdP metadata. wantAssertionsSigned now controls whether signed assertions are required rather than signed response messages, matching how IdPs sign SAML responses in practice.
For detailed changes, see CHANGELOG
@better-auth/scim
❗ Breaking Changes
Decoupled SCIM provisioning from the organization plugin (#10390)
Migration: SCIM configuration, client APIs, database schema, and the Group model are all replaced, and provisioning state cannot migrate in place. Follow the SCIM cutover in the 1.7 upgrade guide, including a full directory reprovision, before resuming traffic.
Isolated SCIM provider connections from the organization and SSO plugins (#10249)
Migration: Define connections statically, resolve them with authentication.verifyBearerToken, or use the optional managedConnections catalog, and connect SCIM resources to users and roles through identity and projection callbacks. Legacy SCIM state is not migrated: back it up, issue new credentials, and fully reprovision Users and Groups.
Bound personal SCIM connections to their creator and removed user-session connection management (#9840)
Migration: The legacy connection management endpoints and providerOwnership are gone, so authorize SCIM administration in your own application. Legacy scimProvider rows and credentials are not migrated: follow the 1.7 SCIM upgrade guide, issue new credentials, and reprovision Users and Groups.
Features
Added a user.validateUserInfo gate for rejecting an identity before a user is created or linked (#9864)
Added durable SCIM Group resources with connection-scoped membership and lifecycle endpoints (#10018)
Added the SCIM Enterprise User extension and the standard User attributes for interop conformance (#10620)
Added a managed connection catalog and runtime connection resolution (#10592)
Added acquireActiveSCIMUserLink for transaction-safe authentication of provisioned users (#10474)
Bug Fixes
Accepted exact case-insensitive string boolean values for SCIM User active and the primary sub-attribute of emails, phoneNumbers, addresses, roles, and entitlements at the HTTP ingress, for Microsoft Entra interoperability.
Added an optional SCIM-owned connection and credential catalog. Configure managedConnections so trusted server code can create runtime tenant connections and issue, rotate, and revoke their bearer credentials through server-only auth.api methods, without a code-defined connection or an application-owned verifier.
Allowed trusted server code to retain a terminal connection binding before a dynamic SCIM connection's first authenticated request by supplying its provisioning domain during decommissioning.
Created filtered SCIM PATCH values when no target matches instead of rejecting the request (#10682)
For detailed changes, see CHANGELOG
@better-auth/mcp ✨
❗ Breaking Changes
Moved the MCP plugin into its own @better-auth/mcp package built on the OAuth provider (#9992)
Migration: Install @better-auth/mcp and @better-auth/cimd, add the now-required jwt() plugin, and move options nested under oidcConfig to flat mcp({ ... }) options. Rename withMcpAuth to requireMcpAuth and mcpHandler to createMcpProtectedRequestHandler. Regenerate the schema (npx auth migrate): oauthApplication becomes oauthClient, plus new oauthRefreshToken and oauthClientAssertion tables.
Aligned OAuth client registration and metadata with MCP authorization 2026-07-28 (#10577)
Migration: Add applicationType and nullable clientDiscoveryId columns, deduplicate existing (clientId, resourceId) links before the new compound unique index, then drop the legacy type and public columns. Replace clientCredentialGrantDefaultScopes with per-client clientCredentialsScopes, backfilling every client to [] and reassigning approved machine scopes after an audit. mcp() no longer enables unauthenticated DCR: compose it with cimd() or enable both DCR flags explicitly.
Modeled OAuth protected resources explicitly, with per-resource TTLs, scopes, claims, and signing pins (#9648)
Migration: mcp() now requires an explicit resource identifier, for example resource: "https://api.example.com/mcp". validAudiences is removed: move each resource identifier into resources. Run npx @better-auth/cli generate and apply the migration before deploying.
Features
Added DPoP sender-constrained access tokens (RFC 9449) (#10039)
Added a refresh token reuse interval that replays the same response for duplicate refresh requests (#10145)
For detailed changes, see CHANGELOG
@better-auth/electron
❗ Breaking Changes
Enforced S256 PKCE in the Electron sign-in flow and hardened custom-scheme origin checks (#9645)
Migration: Upgrade the @better-auth/electron client and server together and add your app's scheme to trustedOrigins. The code_challenge_method parameter and disableOriginOverride option are removed, and host-bearing custom-scheme entries now match that host exactly.
Rewrote the generic OAuth plugin as a first-class social provider with OAuth 2.1 defaults (#9069)
Migration: Replace signIn.oauth2({ providerId }) with signIn.social({ provider }), oauth2.link() with linkSocial(), and drop genericOAuthClient(). Callbacks move to /api/auth/callback/:id, pkce now defaults to true, and issuer and requireIssuerValidation are removed in favor of OIDC discovery.
Bug Fixes
Fixed client plugin composition so One Tap, Electron, and Expo type-check with createAuthClient (#10505)
For detailed changes, see CHANGELOG
@better-auth/expo
❗ Breaking Changes
Switched Expo secure storage to async access so apps no longer crash when the iOS Keychain is unavailable (#10438)
Migration: getCookie() now returns a promise, and custom storage implementations must provide both synchronous and asynchronous SecureStore methods. storageAdapter.setItem() stays synchronous, so use setItemAsync() when the write must be awaited.
Rewrote the generic OAuth plugin as a first-class social provider with OAuth 2.1 defaults (#9069)
Migration: Replace signIn.oauth2({ providerId }) with signIn.social({ provider }), oauth2.link() with linkSocial(), and drop genericOAuthClient(). Callbacks move to /api/auth/callback/:id, pkce now defaults to true, and issuer and requireIssuerValidation are removed in favor of OIDC discovery.
Bug Fixes
Fixed client plugin composition so One Tap, Electron, and Expo type-check with createAuthClient (#10505)
For detailed changes, see CHANGELOG
@better-auth/stripe
❗ Breaking Changes
Made the event parameter of onSubscriptionCancel required (#9531)
Migration: Declare event as a required parameter in your callback and remove any undefined guards around it.
Removed the optional marker from the onSubscriptionCancel event parameter (#9359)
Migration: event is always supplied, so drop undefined handling from the callback.
For detailed changes, see CHANGELOG
auth
❗ Breaking Changes
Accumulated OAuth granted scopes in a new grantedScopes string array (#9825)
Migration: grantedScopes replaces the comma-joined account.scope string with no read-time fallback, so backfill it from the existing values. The client provider contract is renamed from OAuthProvider to UpstreamProvider.
Features
Added a create-admin command for creating an initial admin user (#9547)
Added compound table indexes to plugin database schemas (#10402)
Bug Fixes
Preserved issuer-scoped account identities by restoring Account.accountId alongside the required issuer (#10668)
Exported the generated pgSchema binding so drizzle-kit can emit CREATE SCHEMA for custom PostgreSQL namespaces (#10770)
Loaded the auth config through c12 v4 resolveModule, adding support for the export default { auth } shape (#9477)
Reverted the granted scopes architecture, restoring the previous account.scope storage (#10123)
For detailed changes, see CHANGELOG
@better-auth/drizzle-adapter
❗ Breaking Changes
Moved database joins out of experimental into the stable advanced.database.joins option (#10359)
Migration: Replace experimental: { joins: true } with advanced: { database: { joins: true } }, and regenerate the schema (npx auth@latest generate) so it includes the required relations.
Features
Added compound table indexes to plugin database schemas (#10402)
Added a relations-v2 entry point for projects using Drizzle Relations v2 (#9489)
Added a schemaName option that generates the Drizzle schema inside a pgSchema namespace (#7169)
Bug Fixes
Exported the generated pgSchema binding so drizzle-kit can emit CREATE SCHEMA for custom PostgreSQL namespaces (#10770)
For detailed changes, see CHANGELOG
@better-auth/cimd ✨
❗ Breaking Changes
Aligned OAuth client registration and metadata with MCP authorization 2026-07-28 (#10577)
Migration: Add applicationType and nullable clientDiscoveryId columns, deduplicate existing (clientId, resourceId) links before the new compound unique index, then drop the legacy type and public columns. Client ID Metadata Documents preserve an omitted application_type as null and cannot assign clientCredentialsScopes. Compose mcp() with cimd() for metadata-document clients.
Features
Added the @better-auth/cimd Client ID Metadata Document plugin (#9159)
Bug Fixes
Client ID Metadata Documents now follow shared-cache freshness rules and fail closed when freshness is ambiguous. The plugin prefers s-maxage over max-age and Expires, honors s-maxage=0, revalidates conditionally with ETag or Last-Modified, and treats invalid or duplicate freshness directives as immediately stale. Concurrent refreshes converge on one client-resource link instead of failing on its unique constraint.
For detailed changes, see CHANGELOG
@better-auth/api-key
❗ Breaking Changes
Hardened atomic state transitions so concurrent requests cannot race past single-use or rate-limit guards (#10000)
Migration: Custom adapters must implement native consumeOne and incrementOne, secondary storage needs atomic consume and increment operations, and custom rate-limit storage makes one consume decision per request. The read-then-delete and read-then-update fallbacks are removed.
For detailed changes, see CHANGELOG
@better-auth/kysely-adapter
Bug Fixes
Fixed SQLite dialect bundles on Kysely 0.29 by mirroring the migration-table constants locally (#10377)
Raw database instances (better-sqlite3, node:sqlite, bun:sqlite, mysql2, pg) passed directly as database now get native adapter transactions automatically, matching the behavior of the explicit { db } and { dialect } config shapes. This unblocks plugins that require native transactions (such as @better-auth/scim) when the database is provided in the quickstart database: new Database(...) shape.
For detailed changes, see CHANGELOG
@better-auth/i18n
Features
Added built-in translations for 22 languages (#9157)
For detailed changes, see CHANGELOG
@better-auth/mongo-adapter
Features
Added compound table indexes to plugin database schemas (#10402)
For detailed changes, see CHANGELOG
@better-auth/passkey
Features
Added an optional createSession setting that signs the user in on successful passkey registration (#9873)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@adrianmxb, @brentmitchell25, @bytaesu, @dvanmali, @eluce2, @GautamBytes, @gustavovalverde, @ItalyPaleAle, @jonathansamines, @KingIronMan2011, @momomuchu, @OscarCornish, @pi0, @ping-maxwell, @ruban-s, @sovetski, @yordis
Full changelog: v1.6.30...v1.7.0
Original source - Aug 17, 2026
- Date parsed from source:Aug 17, 2026
- First seen by Releasebot:Aug 18, 2026
v1.6.30
Better Auth fixes cold-start auth and transaction context loss, and tightens SSO organization assignment and domain verification to prevent incorrect joins when provider domains change or only appear verified.
better-auth
Bug Fixes
Fixed concurrent cold-start requests from intermittently losing authentication or transaction context due to an async storage initialization race (#10833)
For detailed changes, see CHANGELOG
@better-auth/sso
Bug Fixes
Fixed automatic organization assignment via email domain to require both a verified provider domain and a verified stored user email, preventing social sign-in from joining an organization whose SSO provider merely claims that domain.
Fixed domain verification to snapshot the provider's domains at request start, returning 409 with SSO_PROVIDER_CHANGED if the provider changes during DNS resolution so callers can reload and retry.
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@bytaesu
Full changelog: v1.6.29...v1.6.30
Original source - Aug 14, 2026
- Date parsed from source:Aug 14, 2026
- First seen by Releasebot:Aug 14, 2026
v1.7.0-rc.6
Better Auth ships bug fixes across the core, OAuth provider, Drizzle adapter, Electron, and Expo, restoring TypeScript compatibility, reducing duplicate session requests, and improving logout, claims, and schema handling.
better-auth
Bug Fixes
Restored client plugin declaration compatibility for downstream TypeScript consumers. (#10794)
Fixed duplicate session requests during transient Suspense remounts while ensuring incomplete refreshes are revalidated. (#10769)
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
Bug Fixes
Fixed private_key_jwt client assertions to accept the issuer URL as a valid aud claim (string or array) on token, introspection, and revocation requests. (#10811)
Completed the RP-Initiated Logout flow with form-encoded POST support, explicit confirmation pages, and strict post_logout_redirect_uri validation. (#10812)
Fixed handling of voluntary and essential ACR requests in authorization flows. (#10790)
Fixed claims requests to require the openid scope. (#10791)
For detailed changes, see CHANGELOG
@better-auth/drizzle-adapter
Bug Fixes
Fixed missing pgSchema export so drizzle-kit can emit CREATE SCHEMA for custom PostgreSQL namespaces. (#10770)
For detailed changes, see CHANGELOG
@better-auth/electron
Bug Fixes
Restored declaration compatibility for downstream TypeScript consumers. (#10794)
For detailed changes, see CHANGELOG
@better-auth/expo
Bug Fixes
Restored declaration compatibility for downstream TypeScript consumers. (#10794)
For detailed changes, see CHANGELOG
auth
Bug Fixes
Fixed missing pgSchema export so drizzle-kit can emit CREATE SCHEMA for custom PostgreSQL namespaces. (#10770)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@bytaesu, @gustavovalverde, @ping-maxwell
Full changelog: v1.7.0-rc.5...v1.7.0-rc.6
Original source - Aug 14, 2026
- Date parsed from source:Aug 14, 2026
- First seen by Releasebot:Aug 14, 2026
v1.6.29
Better Auth improves performance and SSO security with faster parallel session deletes and tighter domain verification for social sign-in and email-based organization assignment.
better-auth
Bug Fixes
Improved deleteSessions performance by running deletes in parallel instead of sequentially (#10805)
For detailed changes, see CHANGELOG
@better-auth/sso
Bug Fixes
Fixed automatic email-domain organization assignment to require both a verified provider domain and a verified user email, preventing social sign-in from granting access when an SSO provider merely claims a domain.
Fixed domain verification to snapshot the provider's domains at request start, returning 409 with SSO_PROVIDER_CHANGED if the provider changes during DNS verification so callers can reload and retry.
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@Emmaccen
Full changelog: v1.6.28...v1.6.29
Original source - Aug 13, 2026
- Date parsed from source:Aug 13, 2026
- First seen by Releasebot:Aug 14, 2026
v1.6.28
Better Auth ships bug fixes that prevent duplicate session requests during React Suspense retries while preserving revalidation for interrupted refreshes, and restores client plugin declaration compatibility for downstream TypeScript consumers across better-auth, Electron, and Expo.
better-auth
Bug Fixes
- Prevented duplicate session requests during React Suspense retries while preserving revalidation for interrupted refreshes (#10769)
- Restored client plugin declaration compatibility for downstream TypeScript consumers (#10794)
For detailed changes, see the CHANGELOG.
@better-auth/electron
Bug Fixes
- Restored client plugin declaration compatibility for downstream TypeScript consumers (#10794)
For detailed changes, see the CHANGELOG.
@better-auth/expo
Bug Fixes
- Restored client plugin declaration compatibility for downstream TypeScript consumers (#10794)
For detailed changes, see the CHANGELOG.
Contributors
Thanks to everyone who contributed to this release:
- @bytaesu
Full changelog: v1.6.27...v1.6.28
Original source
Curated by the Releasebot team
Releasebot is an aggregator of official release notes from hundreds of software vendors and thousands of sources.
Our editorial process involves the manual review and audit of release notes procured with the help of automated systems.