Better Auth Updates & Release Notes
125 updates curated from 1 source by the Releasebot Team. Last updated: Aug 19, 2026
- 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 All of your release notes in one feed
Join Releasebot and get updates from Better Auth and hundreds of other software products.
- 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 Similar to Better Auth with recent updates:
- Claude Code updates423 release notes · Latest Aug 22, 2026
- ChatGPT updates209 release notes · Latest Aug 21, 2026
- OpenAI Models updates49 release notes · Latest Aug 18, 2026
- Gemini updates395 release notes · Latest Aug 20, 2026
- Gemini API updates134 release notes · Latest Aug 13, 2026
- Claude updates129 release notes · Latest Aug 21, 2026
- 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 - Aug 11, 2026
- Date parsed from source:Aug 11, 2026
- First seen by Releasebot:Aug 13, 2026
v1.7.0-rc.5
Better Auth releases a new update with a major OAuth device grant refactor, a new oauthDeviceAuthorization() flow, and a username plugin option to hide displayName. It also tightens device authorization behavior, removes startup warning controls, and fixes CLI and SCIM issues.
better-auth
❗ Breaking Changes
Refactored OAuth device grant ownership to use
oauthDeviceAuthorization()alongsideoauthProvider()ormcp()(#10746)Migration: Replace the standalone
deviceCodeGrant()plugin withoauthDeviceAuthorization()used alongsideoauthProvider()ormcp(). Regenerate and apply the schema (resource column is replaced byoauthClientIdandresources). Let any pending device codes expire or delete them before upgrading, as they cannot be exchanged through the new integration.Features
Added option to disable displayName in the username plugin (#10330)
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
❗ Breaking Changes
Refactored OAuth device grant ownership to use
oauthDeviceAuthorization()alongsideoauthProvider()ormcp()(#10746)Migration: Replace the standalone
deviceCodeGrant()plugin withoauthDeviceAuthorization()used alongsideoauthProvider()ormcp(). Regenerate and apply the schema (resource column is replaced byoauthClientIdandresources). Let any pending device codes expire or delete them before upgrading, as they cannot be exchanged through the new integration.Features
Removed the silenceWarnings config option and startup warnings for well-known metadata endpoints (#10703)
Bug Fixes
Fixed device authorization flow to enforce RFC requirements (#10752)
For detailed changes, see CHANGELOG
@better-auth/scim
Bug Fixes
Fixed type alignment between auth endpoints and better-call (#10657)
For detailed changes, see CHANGELOG
auth
Bug Fixes
Fixed CLI to align installed packages with the running CLI version (#10743)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@bytaesu, @gustavovalverde, @ping-maxwell
Full changelog: v1.7.0-rc.4...v1.7.0-rc.5
Original source - Aug 11, 2026
- Date parsed from source:Aug 11, 2026
- First seen by Releasebot:Aug 13, 2026
v1.6.27
Better Auth fixes duplicate session requests, SCIM endpoint types, and CLI package version alignment in this bugfix release.
better-auth
Bug Fixes
Fixed duplicate session requests being made across Suspense retries (#10676)
For detailed changes, see CHANGELOG
@better-auth/scim
Bug Fixes
Fixed auth endpoint types to align with better-call (#10657)
For detailed changes, see CHANGELOG
auth
Bug Fixes
Fixed the CLI to align installed packages with the running CLI version (#10743)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@bytaesu
Full changelog: v1.6.26...v1.6.27
Original source - Aug 5, 2026
- Date parsed from source:Aug 5, 2026
- First seen by Releasebot:Aug 5, 2026
v1.7.0-rc.4
Better Auth adds a placeholder email utility and ships a broad round of bug fixes across sessions, OAuth, OTP, JWT, React, Next.js, Redis storage, and SCIM, plus async secure storage changes for Expo to improve stability and reliability.
better-auth
Features
- Added a placeholder email utility for generating temporary email addresses (#10576)
Bug Fixes
Fixed sessions not being cleaned up when a user is deleted (#10520)
Fixed missing PKCE challenge in Apple OAuth flows (#10294)
Fixed duplicate in-flight session requests when React retries a suspended component (#10676)
Fixed cookie cache to work independently of the JWT plugin internals (#10666)
Fixed findSessions to skip null-parsed session tokens instead of returning early (#10580)
Fixed missing verification type when sending email OTP during sign-up (#10608)
Fixed OTP being cleared after password validation errors in email OTP flows (#10552)
Fixed email OTP to verify the code before revealing whether the email exists (#10605)
Fixed client plugin type inference when using jwtClient (#10513)
Fixed JWT signing to use the transaction-scoped adapter (#10623)
Fixed Apple user data being lost when using the OAuth proxy (#10599)
Fixed Google One Tap to enforce provider signup restrictions (#10479)
Fixed client plugin type inference when using oneTapClient (#10635)
Fixed rate limit database cleanup to be awaited by default (#10619)
Fixed $fetch and $store not being exposed on the Solid client (#10444)
Improved Next.js performance by reusing the next/headers import promise in production (#10467)
For detailed changes, see CHANGELOG
@better-auth/expo
❗ Breaking Changes
- Switched to async secure storage access to prevent crashes when iOS Keychain is unavailable (#10438)
Migration: getCookie() now returns a Promise. Custom storage implementations must provide both sync and async SecureStore methods, and should use setItemAsync() when the write must be awaited.
For detailed changes, see CHANGELOG
@better-auth/redis-storage
Bug Fixes
- Fixed Redis storage to use SCAN instead of KEYS to avoid blocking the server (#10507)
For detailed changes, see CHANGELOG
@better-auth/scim
Bug Fixes
- Fixed SCIM PATCH to create filtered attribute values when no target matches, instead of rejecting with a noTarget error (#10682)
For detailed changes, see CHANGELOG
auth
Bug Fixes
- Fixed issuer-scoped account identities being overwritten during OAuth flows (#10668)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@birkskyum, @bytaesu, @Emmaccen, @gustavovalverde, @jashkarangiya, @jeroenvandermerwe, @jlucaso1, @jsj, @krish-vachhani, @mrosberghaus, @XXMOHAMED012
Full changelog: v1.7.0-rc.3...v1.7.0-rc.4
Original source - Aug 4, 2026
- Date parsed from source:Aug 4, 2026
- First seen by Releasebot:Aug 5, 2026
v1.6.26
Better Auth releases bug fixes and a new utility for stable placeholder emails, while improving session cleanup, OTP flows, JWT handling, Redis performance, and Next.js instrumentation efficiency.
better-auth
Bug Fixes
Fixed session cleanup on user deletion to also remove sessions from secondary storage (#10520)
Fixed findSessions to skip invalid secondary-storage session entries without discarding other valid sessions (#10580)
Fixed email OTP sign-up to pass the verification type to custom OTP generators (#10608)
Fixed email OTP password reset to allow retrying after entering an invalid password (#10552)
Fixed email OTP verification to no longer reveal whether an email is registered before the OTP is verified (#10605)
Fixed jwtClient() collapsing createAuthClient type inference when combined with other client plugins (#10513)
Fixed JWT key minting inside database transactions to use the transaction-scoped adapter, preventing deadlocks on SQLite and ensuring keys commit with their surrounding transaction on Postgres and MySQL (#10623)
Fixed oAuthProxy to preserve Apple user data from form_post callbacks (#10599)
Fixed oneTapClient() collapsing createAuthClient type inference when combined with other client plugins (#10635)
Fixed database rate-limit cleanup to complete when no background task handler is configured (#10619)
Improved nextCookies performance in instrumented Next.js applications by reusing the next/headers import promise (#10467)
For detailed changes, see CHANGELOG
@better-auth/core
Features
Added a utility for creating stable, namespaced placeholder emails on the reserved placeholder.invalid domain (#10576)
For detailed changes, see CHANGELOG
@better-auth/redis-storage
Bug Fixes
Fixed listKeys() and clear() to use SCAN instead of KEYS so large keyspaces no longer block the Redis server (#10507)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@bytaesu, @Emmaccen, @gustavovalverde, @jashkarangiya, @jeroenvandermerwe, @jlucaso1, @krish-vachhani, @mrosberghaus, @XXMOHAMED012
Full changelog: v1.6.25...v1.6.26
Original source - Aug 3, 2026
- Date parsed from source:Aug 3, 2026
- First seen by Releasebot:Aug 4, 2026
v1.7.0-rc.3
Better Auth ships a broad release with device authorization flow indexing, OAuth device grant support, RP-initiated logout, Microsoft account identifier changes, SCIM and SSO improvements, MCP spec alignment, passkey auto sign-in, and several bug fixes and TypeScript cleanup.
better-auth
❗ Breaking Changes
Added database indexes for device and user code lookups in the device authorization flow (#10059)
Migration: MySQL and SQL Server users must convert device code and user code columns to bounded strings (max 191 characters) and resolve any oversized values before applying the migration.
Changed Microsoft and microsoftEntraId accounts to use the stable oid claim as the account identifier instead of sub (#10204)
Migration: Migrate existing Microsoft account rows keyed by sub to oid before upgrading; tokens without a valid oid claim are rejected after the update.
Features
Added RP-initiated logout support for Generic OAuth providers, redirecting users to their OpenID provider's logout endpoint on sign-out (#9368)
Added RFC 8628 device authorization grant support to the OAuth provider, enabling device-flow token exchanges for registered OAuth clients (#10135)
Bug Fixes
Enabled native database transactions in test instances for Postgres and MySQL databases.
Fixed a deadlock during sign-up when JWT session caching and native transactions are both enabled on single-connection databases (#10622)
Fixed TypeScript errors when composing One Tap, Electron, and Expo plugins with createAuthClient (#10505)
For detailed changes, see CHANGELOG
@better-auth/core
❗ Breaking Changes
Changed Microsoft and microsoftEntraId accounts to use the stable oid claim as the account identifier instead of sub (#10204)
Migration: Migrate existing Microsoft account rows keyed by sub to oid before upgrading; tokens without a valid oid claim are rejected after the update.
Features
Added RP-initiated logout support for Generic OAuth providers, redirecting users to their OpenID provider's logout endpoint on sign-out (#9368)
Bug Fixes
Fixed TypeScript errors when composing One Tap, Electron, and Expo plugins with createAuthClient (#10505)
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
❗ Breaking Changes
Aligned MCP authorization with the 2026-07-28 specification, replacing legacy type/public client fields with applicationType and enforcing stricter redirect validation and scope controls (#10577)
Migration: Apply a database migration to add applicationType, nullable clientDiscoveryId, and clientCredentialsScopes columns; backfill applicationType from existing values and clientCredentialsScopes to [] for all clients; deduplicate (clientId, resourceId) pairs before applying the new unique index. Replace OAuthClient string-index accesses with OAuthClient & YourExtensionMetadata, and compose mcp() with cimd() explicitly if using Client ID Metadata Documents.
Features
Added RFC 8628 device authorization grant support to the OAuth provider, enabling device-flow token exchanges for registered OAuth clients (#10135)
Bug Fixes
Fixed MCP scope enforcement to return a 403 with an RFC 6750 insufficient_scope WWW-Authenticate challenge listing all missing scopes, allowing clients to request them in a single authorization request.
For detailed changes, see CHANGELOG
@better-auth/cimd
❗ Breaking Changes
Aligned MCP authorization with the 2026-07-28 specification, replacing legacy type/public client fields with applicationType and enforcing stricter redirect validation and scope controls (#10577)
Migration: Apply a database migration to add applicationType, nullable clientDiscoveryId, and clientCredentialsScopes columns; backfill applicationType from existing values and clientCredentialsScopes to [] for all clients; deduplicate (clientId, resourceId) pairs before applying the new unique index. Replace OAuthClient string-index accesses with OAuthClient & YourExtensionMetadata, and compose mcp() with cimd() explicitly if using Client ID Metadata Documents.
Bug Fixes
Fixed Client ID Metadata Document caching to follow shared-cache freshness rules, preferring s-maxage, honoring conditional revalidation, and treating ambiguous or duplicate freshness directives as immediately stale to prevent unique-constraint failures on concurrent refreshes.
For detailed changes, see CHANGELOG
@better-auth/mcp
❗ Breaking Changes
Aligned MCP authorization with the 2026-07-28 specification, replacing legacy type/public client fields with applicationType and enforcing stricter redirect validation and scope controls (#10577)
Migration: Apply a database migration to add applicationType, nullable clientDiscoveryId, and clientCredentialsScopes columns; backfill applicationType from existing values and clientCredentialsScopes to [] for all clients; deduplicate (clientId, resourceId) pairs before applying the new unique index. Replace OAuthClient string-index accesses with OAuthClient & YourExtensionMetadata, and compose mcp() with cimd() explicitly if using Client ID Metadata Documents.
For detailed changes, see CHANGELOG
@better-auth/scim
Features
Added SCIM Enterprise User extension attributes and classic user attributes with improved Microsoft Entra interoperability (#10620)
Added a managed connection catalog for runtime SCIM tenant connection and credential management through server-only auth.api methods (#10592)
Bug Fixes
Fixed Microsoft Entra interoperability by accepting case-insensitive string boolean values for the SCIM active field and primary sub-attributes of emails, phoneNumbers, addresses, roles, and entitlements at the HTTP ingress.
Added managedConnections configuration to allow trusted server code to create, issue, rotate, and revoke SCIM tenant connections and bearer credentials through server-only auth.api methods without a code-defined connection.
Fixed dynamic SCIM connection decommissioning to allow retaining a terminal connection binding by supplying the provisioning domain before the first authenticated request.
For detailed changes, see CHANGELOG
@better-auth/sso
Features
Extended resolveUser to SAML sign-ins with a discriminated protocol field, and added guardProviderMutation to authorize SSO provider updates and deletions (#10621)
Bug Fixes
Fixed SSO provider registration to allow reusing a SCIM connection ID, since SCIM connections no longer participate in the authentication provider namespace.
Improved SAML security by verifying assertion signatures on the raw XML rather than a pre-parsed response, enforcing signing policy and size limits on SP metadata, and correcting wantAssertionsSigned to control assertion signing instead of response signing.
For detailed changes, see CHANGELOG
@better-auth/electron
Bug Fixes
Fixed TypeScript errors when composing One Tap, Electron, and Expo plugins with createAuthClient (#10505)
For detailed changes, see CHANGELOG
@better-auth/expo
Bug Fixes
Fixed TypeScript errors when composing One Tap, Electron, and Expo plugins with createAuthClient (#10505)
For detailed changes, see CHANGELOG
@better-auth/kysely-adapter
Bug Fixes
Fixed raw database instances (better-sqlite3, node:sqlite, bun:sqlite, mysql2, pg) passed directly as database to automatically receive native adapter transactions, matching the explicit { db }/{ dialect } config shapes and unblocking plugins like @better-auth/scim when using the quickstart configuration.
For detailed changes, see CHANGELOG
@better-auth/passkey
Features
Added an optional createSession setting to passkey registration that signs the user in automatically on successful registration (#9873)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@brentmitchell25, @GautamBytes, @gustavovalverde
Full changelog: v1.7.0-rc.2...v1.7.0-rc.3
Original source - Jul 23, 2026
- Date parsed from source:Jul 23, 2026
- First seen by Releasebot:Jul 24, 2026
v1.6.25
Better Auth fixes Apple OAuth PKCE, Google One Tap sign-up handling, Solid client exposure for $fetch and $store, and adapter query routing for built-in tables, improving reliability across auth flows and data models.
better-auth
Bug Fixes
- Fixed Apple OAuth not sending the PKCE code challenge during authorization, causing token exchange failures (#10294)
- Fixed Google One Tap creating new users when sign-up was disabled on the Google provider (#10479)
- Fixed $fetch and $store not being exposed on the Solid client (#10444)
- Fixed internal adapter queries being routed to the wrong table when a built-in table's modelName was set to another table's schema key (e.g. user.modelName = "account").
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@birkskyum, @jsj, @krish-vachhani
Full changelog: v1.6.24...v1.6.25
Original source - Jul 22, 2026
- Date parsed from source:Jul 22, 2026
- First seen by Releasebot:Jul 24, 2026
v1.7.0-rc.2
Better Auth ships a major release candidate with breaking auth and SCIM changes, new issuer-based account scoping, joins moved to advanced.database.joins, transactional OIDC resolution, compound indexes, and multiple bug fixes across adapters and plugins.
better-auth
❗ Breaking Changes
chore!: move joins to advanced.database.joins (#10359)
If you previously set experimental: { joins: true }, update your config to:
advanced: { database: { joins: true, }, }Adapters that support native joins use them when enabled. If an adapter cannot return joined data for a query, Better Auth falls back to additional queries and combines the results. Drizzle and Prisma users should ensure their schema includes the required relations (npx auth@latest generate).
feat(auth)!: scope accounts by issuer (#10403)
This release is breaking. Account.accountId is renamed to Account.providerAccountId, and Account.issuer is required. Account-specific APIs select the local Account.id through accountId; token and provider-profile APIs can instead select the signed account cookie with useAccountCookie: true. Credential accounts use local:credential and the linked user's stable id as their provider identity.
OAuth provider identity now comes from raw verified profiles. OpenID Connect discovery uses sub, plain OAuth uses id, and providers can declare accountSubject for another immutable field; Better Auth no longer switches between sub and id at runtime. getUserInfo().user no longer carries provider identity, and mapProfileToUser cannot return id. Read the selected identity from accountInfo.account.providerAccountId instead of accountInfo.user.id. The generic microsoftEntraId helper now requires a concrete tenant GUID; use the built-in Microsoft provider for multi-tenant authorities.
SSO account subjects are now protocol-defined. OIDC uses the verified sub claim, and SAML uses the signed NameID; mapping.id is removed from both configurations. A manual SAML configuration without metadata XML must set idpMetadata.entityID, because samlConfig.issuer identifies the service provider and no longer acts as the IdP identity.
Apply the reviewed account-identity backfill in the Better Auth 1.7 upgrade guide before deploying. The generated schema migration cannot assign trusted issuers or resolve existing identity collisions automatically.
feat(scim)!: decouple provisioning from the organization plugin (#10390)
This replaces the previous SCIM configuration, client APIs, database schema, and organization-backed Group model. Existing SCIM installations cannot migrate provisioning state in place. Follow the SCIM cutover in the 1.7 upgrade guide, including full directory reprovisioning, before resuming traffic.
Deferred database side effects now run only after a successful transaction. A rolled-back User update no longer refreshes its cached profile, and a rolled-back bulk session revocation no longer invalidates sessions.
Features
- feat: add ctx to verifyIdToken (#10376)
- feat(db): add compound table indexes (#10402)
- feat(last-login-method): beforeStoreCookie option for GDPR compliance (#5753)
- feat(organization): add getOrganization for metadata-only fetches (#10397)
- feat(sso): add transactional OIDC user resolution (#10473)
Bug Fixes
- chore: widen drizzle-kit peer dependency range (#10299)
- fix: get-session should have no-cache cache control headers (#10222)
- fix: recognize BIGINT as valid number type for SQLite in migrations. (#10316)
- fix(auth): handle request clone failures in callbacks (#10336)
- fix(client): preserve null in useSession().data type with throw:true (#9787)
- fix(client): restore auth query lifecycle after remount (#10379)
- fix(cookies): tighten CookieAttributes index signature type (#10441) (#10442)
- fix(core): dedup request-state AsyncLocalStorage init to fix intermittent "No request state found" (#9862)
- fix(core): resolve user.modelName collisions in references and adapter (#10235)
- fix(db): avoid duplicate unique indexes in kysely migrations (#10357)
- fix(magic-link, email-otp): force-validate Origin on cookieless send endpoints (#10368)
- fix(mcp): expose remote auth challenge headers (#10290)
- fix(open-api): include plugin user fields on sign-up/update bodies (#10453)
- fix(organization): apply membershipLimit to listMembers user fetch (#10342)
- fix(organization): let the database generate invitation ids (#10040)
- fix(siwe): issue addressless nonces (#10324)
For detailed changes, see CHANGELOG
@better-auth/core
❗ Breaking Changes
chore!: move joins to advanced.database.joins (#10359)
If you previously set experimental: { joins: true }, update your config to:
advanced: { database: { joins: true, }, }Adapters that support native joins use them when enabled. If an adapter cannot return joined data for a query, Better Auth falls back to additional queries and combines the results. Drizzle and Prisma users should ensure their schema includes the required relations (npx auth@latest generate).
feat(auth)!: scope accounts by issuer (#10403)
This release is breaking. Account.accountId is renamed to Account.providerAccountId, and Account.issuer is required. Account-specific APIs select the local Account.id through accountId; token and provider-profile APIs can instead select the signed account cookie with useAccountCookie: true. Credential accounts use local:credential and the linked user's stable id as their provider identity.
OAuth provider identity now comes from raw verified profiles. OpenID Connect discovery uses sub, plain OAuth uses id, and providers can declare accountSubject for another immutable field; Better Auth no longer switches between sub and id at runtime. getUserInfo().user no longer carries provider identity, and mapProfileToUser cannot return id. Read the selected identity from accountInfo.account.providerAccountId instead of accountInfo.user.id. The generic microsoftEntraId helper now requires a concrete tenant GUID; use the built-in Microsoft provider for multi-tenant authorities.
SSO account subjects are now protocol-defined. OIDC uses the verified sub claim, and SAML uses the signed NameID; mapping.id is removed from both configurations. A manual SAML configuration without metadata XML must set idpMetadata.entityID, because samlConfig.issuer identifies the service provider and no longer acts as the IdP identity.
Apply the reviewed account-identity backfill in the Better Auth 1.7 upgrade guide before deploying. The generated schema migration cannot assign trusted issuers or resolve existing identity collisions automatically.
feat(scim)!: decouple provisioning from the organization plugin (#10390)
This replaces the previous SCIM configuration, client APIs, database schema, and organization-backed Group model. Existing SCIM installations cannot migrate provisioning state in place. Follow the SCIM cutover in the 1.7 upgrade guide, including full directory reprovisioning, before resuming traffic.
Deferred database side effects now run only after a successful transaction. A rolled-back User update no longer refreshes its cached profile, and a rolled-back bulk session revocation no longer invalidates sessions.
Features
- feat(db): add compound table indexes (#10402)
- feat(sso): add transactional OIDC user resolution (#10473)
For detailed changes, see CHANGELOG
@better-auth/drizzle-adapter
❗ Breaking Changes
chore!: move joins to advanced.database.joins (#10359)
If you previously set experimental: { joins: true }, update your config to:
advanced: { database: { joins: true, }, }Adapters that support native joins use them when enabled. If an adapter cannot return joined data for a query, Better Auth falls back to additional queries and combines the results. Drizzle and Prisma users should ensure their schema includes the required relations (npx auth@latest generate).
Features
- feat(db): add compound table indexes (#10402)
- feat(drizzle): generate drizzle schema with schema namespace (#7169)
For detailed changes, see CHANGELOG
@better-auth/sso
❗ Breaking Changes
feat(auth)!: scope accounts by issuer (#10403)
This release is breaking. Account.accountId is renamed to Account.providerAccountId, and Account.issuer is required. Account-specific APIs select the local Account.id through accountId; token and provider-profile APIs can instead select the signed account cookie with useAccountCookie: true. Credential accounts use local:credential and the linked user's stable id as their provider identity.
OAuth provider identity now comes from raw verified profiles. OpenID Connect discovery uses sub, plain OAuth uses id, and providers can declare accountSubject for another immutable field; Better Auth no longer switches between sub and id at runtime. getUserInfo().user no longer carries provider identity, and mapProfileToUser cannot return id. Read the selected identity from accountInfo.account.providerAccountId instead of accountInfo.user.id. The generic microsoftEntraId helper now requires a concrete tenant GUID; use the built-in Microsoft provider for multi-tenant authorities.
SSO account subjects are now protocol-defined. OIDC uses the verified sub claim, and SAML uses the signed NameID; mapping.id is removed from both configurations. A manual SAML configuration without metadata XML must set idpMetadata.entityID, because samlConfig.issuer identifies the service provider and no longer acts as the IdP identity.
Apply the reviewed account-identity backfill in the Better Auth 1.7 upgrade guide before deploying. The generated schema migration cannot assign trusted issuers or resolve existing identity collisions automatically.
Features
- feat(sso): add transactional OIDC user resolution (#10473)
Bug Fixes
- fix(sso): redirect idp initiated saml flows in split origin deployments (#10388)
For detailed changes, see CHANGELOG
@better-auth/scim
❗ Breaking Changes
feat(scim)!: decouple provisioning from the organization plugin (#10390)
This replaces the previous SCIM configuration, client APIs, database schema, and organization-backed Group model. Existing SCIM installations cannot migrate provisioning state in place. Follow the SCIM cutover in the 1.7 upgrade guide, including full directory reprovisioning, before resuming traffic.
Deferred database side effects now run only after a successful transaction. A rolled-back User update no longer refreshes its cached profile, and a rolled-back bulk session revocation no longer invalidates sessions.
Features
- feat(scim): expose active provisioned user links (#10474)
For detailed changes, see CHANGELOG
auth
Features
- feat(db): add compound table indexes (#10402)
Bug Fixes
- fix: stub SvelteKit's explicit-environment-variables modules (#10221)
- fix(cli): avoid duplicate unique indexes in drizzle schema (#10333)
- fix(cli): disambiguate Drizzle relations with relationName (#10352)
- fix(cli): recover when auth generate's config self-imports its own output (#10302)
For detailed changes, see CHANGELOG
@better-auth/electron
Bug Fixes
- fix(electron): forward each Set-Cookie from /electron/init-oauth-proxy individually (#9672)
For detailed changes, see CHANGELOG
@better-auth/kysely-adapter
Bug Fixes
- fix(kysely-adapter): restore local migration constants (#10377)
For detailed changes, see CHANGELOG
@better-auth/mongo-adapter
Features
- feat(db): add compound table indexes (#10402)
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
Bug Fixes
- fix(oauth-provider): defer logout effects until commit (#10472)
For detailed changes, see CHANGELOG
@better-auth/stripe
Bug Fixes
- fix(organization): pass endpoint context to organization delete hooks (#10190)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@akshatmalik-bruh, @ayushman46, @c-nicol, @gaurav-init, @gaurav0107, @GautamBytes, @gustavovalverde, @momomuchu, @OrangeManLi, @paoloricciuti, @ping-maxwell, @shiminshen, @swithek, @Tushar-Khandelwal-2004, @vinay-oppuri
Full changelog: v1.7.0-rc.1...v1.7.0-rc.2
Original source - Jul 22, 2026
- Date parsed from source:Jul 22, 2026
- First seen by Releasebot:Jul 24, 2026
v1.6.24
Better Auth ships a broad stability and security update with request-context support for token verification, GDPR-friendly cookie controls, stronger session and OAuth handling, improved schema and migration generation, and fixes across core, SvelteKit, Electron, SSO, and Stripe integrations.
better-auth
Features
- Added request context (ctx) as a third argument to verifyIdToken, enabling custom ID token verifiers to read request headers (#10376)
- Added beforeStoreCookie option to the last-login-method plugin for GDPR compliance (#5753)
Bug Fixes
- Replaced flaky MongoDB where-coercion integration test with a direct unit test for more reliable test runs (#10369)
- Fixed the get-session endpoint to include no-store cache control headers, preventing stale session data from being served (#10222)
- Fixed SQLite migration diffs to recognize BIGINT as a valid number type, preventing spurious pending changes on rate limiter columns (#10316)
- Fixed auth requests failing when request cloning throws an error inside verification callbacks (#10336)
- Fixed useSession({ throw: true }) incorrectly excluding null from its data type (#9787)
- Fixed auth query revalidation and signal listeners not being restored after a client component remounts (#10379)
- Fixed the CookieAttributes index signature type to be more precise (#10442)
- Fixed silent misrouting of adapter queries when user.modelName was set to a value that collides with another schema key (#10235)
- Fixed Kysely migration generation producing duplicate indexes for fields marked both unique and index (#10357)
- Fixed magic-link and email-OTP send endpoints to validate the Origin header on cookieless requests, preventing cross-origin abuse (#10368)
- Fixed remote MCP auth 401 challenge headers being hidden from browser clients due to missing CORS exposure (#10290)
- Fixed OpenAPI schema to include plugin user fields (such as username and displayUsername) in /sign-up/email and /update-user request bodies (#10453)
- Fixed organization.listMembers failing with "User not found for member" for organizations with more than ~100 members (#10342)
- Fixed organization invitations to use database-generated IDs when advanced.database.generateId is configured, matching the behavior of other models (#10040)
- Fixed getDefaultModelName to prefer exact schema key matches over modelName aliases, preventing adapter queries from being misrouted when a built-in table's name collides with another schema key
For detailed changes, see CHANGELOG
auth
Bug Fixes
- Fixed SvelteKit builds by stubbing explicit-environment-variables modules (#10221)
- Fixed Drizzle schema generation producing duplicate indexes for fields marked both unique and index (#10333)
- Fixed Drizzle schema generation for tables with multiple foreign keys to the same model by adding disambiguating relationName values (#10352)
- Fixed auth generate failing when the config file imports the not-yet-generated output file (e.g. on a Convex first run) (#10302)
For detailed changes, see CHANGELOG
@better-auth/electron
Bug Fixes
- Updated compatibility testing to include Electron 43 (peer range unchanged at >=36.0.0) (#10440)
- Fixed /electron/init-oauth-proxy forwarding multiple Set-Cookie headers as a single comma-joined string, which caused the browser to drop the transfer-token cookie during OAuth handoff (#9672)
For detailed changes, see CHANGELOG
@better-auth/core
Bug Fixes
- Fixed an intermittent "No request state found" error caused by a race condition in AsyncLocalStorage initialization on serverless cold starts (e.g. Cloudflare Workers) (#9862)
For detailed changes, see CHANGELOG
@better-auth/sso
Bug Fixes
- Fixed IdP-initiated SAML sign-ins in split-origin deployments to redirect users to the configured application URL instead of the authentication server, using idpInitiatedCallbackUrl (#10388)
For detailed changes, see CHANGELOG
@better-auth/stripe
Bug Fixes
- Fixed beforeDeleteOrganization and afterDeleteOrganization hooks not receiving the endpoint context as the second argument (#10190)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@akshatmalik-bruh, @ayushman46, @c-nicol, @gaurav-init, @gaurav0107, @GautamBytes, @momomuchu, @OrangeManLi, @paoloricciuti, @ping-maxwell, @shiminshen, @swithek, @Tushar-Khandelwal-2004, @vinay-oppuri
Full changelog: v1.6.23...v1.6.24
Original source - Jul 2, 2026
- Date parsed from source:Jul 2, 2026
- First seen by Releasebot:Jul 3, 2026
v1.7.0-rc.1
Better Auth adds Yandex as a supported OAuth social provider and improves database migration reliability and adapter behavior. The release also fixes affected row counting in D1 and postgres-js, plus better escaping for string default values in generated Drizzle schema.
better-auth
Features
- Added Yandex as a supported OAuth social provider (#9138)
Bug Fixes
- Fixed auth migrate to no longer abort when adding required or unique columns to an existing table (#10293)
For detailed changes, see CHANGELOG
@better-auth/drizzle-adapter
Bug Fixes
- Fixed affected row counting for D1 and postgres-js adapters (#10257)
For detailed changes, see CHANGELOG
auth
Bug Fixes
- Fixed string default values to be properly escaped in generated Drizzle schema (#10259)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@bytaesu, @gustavovalverde, @vladflotsky
Full changelog: v1.7.0-rc.0...v1.7.0-rc.1
Original source
Curated by the Releasebot team
Releasebot is an aggregator of official product update announcements 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.