better-auth
❗ Breaking Changes
- Consolidated
id_tokenverification for social providers into a single shared verifier (#9828)
Migration: Custom providers implementing
UpstreamProvidermust replace the removedverifyIdTokenmethod with anidTokenconfig object containingjwks,issuer, andaudience. For verification without a local JWKS, passidToken: { verify: async (token, nonce) => boolean }. PayPal no longer supports client-submittedid_tokensign-in (signIn.social({ idToken })); the redirect flow is unchanged.
Features
- Added
clientAssertionsupport to the Microsoft Entra ID social provider (#9898) - Added per-provider
requireEmailVerificationoption for social sign-in (#9929) - Added
id_tokenverification and client-submittedid_tokensign-in forgenericOAuthproviders configured with adiscoveryUrl(#9966)
Bug Fixes
- Fixed generated schema to accept
nullfor optional fields (#9841) - Fixed fresh age check in
listSessions(#9865) - Fixed admin plugin to return
USER_NOT_FOUNDwhen attempting to update a non-existent user (#9875) - Fixed missing
Origin/Referervalidation on cookieless email sign-in and sign-up (#9973) - Fixed plugin-owned session fields being incorrectly accepted as user input (#9965)
- Fixed
getSessionCookieto prefer the__Secure-prefixed cookie when available (#9806) - Fixed organization invitation verification to correctly scope email verification requirements:
listUserInvitationsalways requires a verified session, andrequireEmailVerificationOnInvitationapplies only to by-ID recipient operations (#9877) - Fixed session-delete hooks not firing for preserved sessions when using
secondaryStorage(#9969) - Fixed
update-sessionand token routes to respect server-side session deletion (#9967) - Improved cookie parsing regex character ranges for correctness (#9879)
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
❗ Breaking Changes
- Added OIDC Back-Channel Logout support, notifying connected apps and revoking access tokens immediately on sign-out (#9304)
Migration: Access tokens whose bound session has ended now return
{ active: false }at introspection and are rejected at/oauth2/userinfo. Runmigrate/generateto add three new schema fields:oauthClient.backchannelLogoutUri,oauthClient.backchannelLogoutSessionRequired, andoauthAccessToken.revoked. On serverless runtimes, configureadvanced.backgroundTasks.handlerto keep sign-out latency low.
- Enforced
max_ageparameter so users are now prompted to re-authenticate when their session exceeds the requested age (#9936)
Migration: Flows that relied on
max_agebeing silently ignored will now prompt users to log in again. No configuration change is required.
Features
- Added support for POST requests on the userinfo endpoint (#9937)
Bug Fixes
- Fixed various bugs across packages (#9974)
- Fixed
private_key_jwtJTI replay prevention to be atomic across processes (#9964) - Fixed JWT access token revocation to return
unsupported_token_typeinstead of a misleading success response (#9970) - Fixed configured hooks not running when an authorization request resumes (#9919)
For detailed changes, see CHANGELOG
@better-auth/sso
❗ Breaking Changes
- Hardened the
validateUserInfosource contract for SSO providers (#9940)
Migration: In
validateUserInfocallbacks, OIDC and SAML SSO sign-ins now passsource.sso(withssoProviderIdand provider claims or assertion attributes) instead ofsource.oauth. Update any callbacks that inspect provider data for SSO flows to read fromsource.ssowhensource.methodis'sso'.
Features
- Added
user.validateUserInfoprovisioning gate to allow rejecting identities before user creation or account linking (#9864) - Added a server-trusted state channel for OAuth redirects and fixed anonymous account linking in cookieless flows (#9930)
Bug Fixes
- Fixed SAML
AuthnRequestconsumption to be atomic (#9972) - Fixed SAML
ERR_SUBJECT_UNCONFIRMEDerrors by passingclockSkewto samlify'sclockDrifts(#9748)
For detailed changes, see CHANGELOG
@better-auth/electron
❗ Breaking Changes
- Enforced PKCE S256 and hardened custom-scheme origin matching in the Electron sign-in flow (#9645)
Migration: Upgrade both the
@better-auth/electronclient and server together, and ensure your app's custom scheme is listed intrustedOrigins. ThedisableOriginOverrideoption is removed. Custom-scheme entries intrustedOriginsnow match by scheme and authority instead of string prefix, somyapp://callbackno longer matchesmyapp://callback.attacker.tld.
For detailed changes, see CHANGELOG
auth
❗ Breaking Changes
- Changed OAuth account scopes from a single
scopestring to an accumulatedgrantedScopesarray, preserving incremental grants across sign-ins (#9825)
Migration: Run
migrate/generateto add thegrantedScopescolumn, then backfill fromaccount.scopeby splitting on commas and whitespace, trimming and deduping tokens. Encoding varies by adapter: native array on PostgreSQL with Drizzle/Prisma,jsonbwith Kysely, JSON string array on MySQL/SQLite/MSSQL. Drop the legacyscopecolumn after verifying. Custom providers must renameOAuthProvidertoUpstreamProviderand removedefaultScopes.
For detailed changes, see CHANGELOG
@better-auth/kysely-adapter
Bug Fixes
- Fixed migration constant imports to use
kysely/migration(#9811) - Fixed Turbopack build failures by inlining migration-table constants (#9933)
For detailed changes, see CHANGELOG
@better-auth/passkey
Features
- Added authenticator name resolution from AAGUID at read time (#9927)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@Bekacru, @bytaesu, @GautamBytes, @gustavovalverde, @ItalyPaleAle, @ping-maxwell, @seebykilian, @WilsonnnTan, @zeroknowledge0x
Full changelog: v1.7.0-beta.4...v1.7.0-beta.5