Blog post: Better Auth 1.6
better-auth
❗ Breaking Changes
- Aligned
freshAge calculation with session creation time instead of update time (#8762)
Migration: session.freshAge now calculates from createdAt. Set session: { freshAge: 0 } to disable the check entirely.
Features
- Added experimental OpenTelemetry instrumentation for endpoints, hooks, middleware, and database operations (#8027)
- Added
resendStrategy option to reuse existing OTP in email-otp plugin (#8560)
- Added
enable option for HaveIBeenPwned plugin (#8728)
- Added request metadata to
sendMagicLink callback (#8571)
- Added dedicated
secret option to OAuth proxy to reduce shared key exposure (#8699)
- Added explicit
organizationId parameter in team endpoints (#5062)
- Added WeChat social provider (#5189)
- Added
twoFactorPage config option for custom 2FA page routing (#5329)
Bug Fixes
- Deprecated
oidc-provider plugin in favor of @better-auth/oauth-provider (#8985)
- Fixed access control indexing type (#8155)
- Added origin check middleware to password reset request (#8392)
- Fixed account cookie comparison to use provider
accountId instead of internal id (#8786)
- Fixed session id generation when using secondary storage without database (#8927)
- Fixed
skipOriginCheck array handling (#8582)
- Fixed misleading rate limit IP warning (#8617)
- Passed
user field through idToken sign-in body for Apple name support (#8417)
- Preserved custom session fields on focus refresh (#8354)
- Fixed double encoded cookie (#8133)
- Prevented revoked sessions from being restored via database fallback (#8708)
- Resolved duplicate
operationId in admin plugin endpoints (#8570)
- Rethrew phone
sendOTP failures instead of silently swallowing them (#8842)
- Set stateless
cookieCache maxAge to match session.expiresIn (#8648)
- Threw on duplicate email when
autoSignIn: false without requireEmailVerification (#8521)
- Fixed
accountInfo endpoint to use accountId instead of internal id (#8346)
- Restored deprecated
createAdapter and type exports for backwards compatibility (#8461)
- Fixed
Response return for HTTP request contexts (#7521)
- Fixed
throw: true handling in client session refresh (#8610)
- Preserved stale session data on network or server errors (#8437)
- Fixed bundler re-export type resolution with direct imports (#8261)
- Fixed Set-Cookie header splitting with lookahead heuristic (#8301)
- Prioritized
generateId: "uuid" over adapter customIdGenerator (#8679)
- Fixed date string revival in
safeJSONParse for pre-parsed objects (#8248)
- Fixed postgres migration to use
CREATE INDEX (#8538)
- Triggered
sessionSignal after requesting email change in email-otp (#8816)
- Fixed generic-oauth to use discovery userinfo endpoint instead of hardcoded URLs (#8223)
- Normalized missing resolver path in last-login-method plugin (#8589)
- Returned additional fields in
/magic-link/verify (#7223)
- Fixed OAuth proxy to read callback params from body for
form_post (#8895)
- Fixed double-hashing of OAuth state when
storeIdentifier is hashed (#8980)
- Fixed
redirect_uri validation for prompt=none in oidc-provider (#8398)
- Opted into FedCM to suppress Google GSI deprecation warnings (#8720)
- Filtered null organizations in
listUserInvitations (#8694)
- Fixed multi-role user handling in invite and member removal checks (#8442)
- Enforced authorization on SCIM management endpoints and normalized passkey ownership checks (#8843)
- Allowed passwordless users to manage 2FA (#7243)
- Wired
twoFactorTable option to schema modelName (#8443)
- Prevented
any from collapsing auth.$Infer and client inference types (#8981)
- Fixed
updateUser to not overwrite unrelated username fields (#7570)
- Enforced username uniqueness in
updateUser (#8731)
- Used non-blocking scrypt for password hashing to avoid blocking the event loop (#8685)
For detailed changes, see CHANGELOG
@better-auth/sso
❗ Breaking Changes
- Enabled InResponseTo validation by default for SP-initiated SAML flows (#8736)
Migration: Set sso({ saml: { enableInResponseToValidation: false } }) to restore the previous behavior.
Features
- Added logging for OIDC callback code validation failures (#8693)
Bug Fixes
- Patched transitive
node-forge vulnerability via samlify pin (#8838)
- Fixed bare domain handling in domain verification (#8369)
- Preferred UserInfo endpoint over ID token and mapped
sub claim correctly (#8276)
- Fixed
provisionUser inconsistency and added provisionUserOnEveryLogin option (#8818)
- Skipped state cookie check for SAML ACS cross-site POST (#8735)
- Fixed verification operations to use
internalAdapter (#8353)
- Fixed ESM compatibility with namespace import for samlify (#8697)
For detailed changes, see CHANGELOG
@better-auth/mongo-adapter
❗ Breaking Changes
- Stored UUIDs as native BSON UUID type (#8681)
Migration: New documents use native BSON UUIDs. Existing string UUIDs continue to work. No data migration required.
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
Features
- Added pairwise subject identifiers (OIDC Core Section 8) (#8292)
- Added public client prelogin endpoint (#8214)
Bug Fixes
- Allowed localhost subdomains in
isLocalhost function (#8286)
- Fixed fetch redirect CORS after login (#8519)
- Allowed
customIdTokenClaims to override standard claims (#7865)
- Enforced DB-backed sessions when secondary storage is enabled (#8894)
- Fixed dist declaration type errors (#8701)
- Fixed dynamic
baseURL config handling in init (#8649)
- Improved allowed paths for
oauth_query in client plugin (#8320)
- Allowed
customIdTokenClaims to override acr and auth_time (#8633)
- Normalized
auth_time timestamps across adapter shapes (#8761)
- Returned JSON redirects from post-login OAuth continuation to fix CORS-blocked 302s (#8815)
- Fixed PAR scope loss, loopback redirect matching, and DCR
skip_consent (#8632)
- Added
prompt=none support (#8554)
For detailed changes, see CHANGELOG
@better-auth/stripe
Features
- Added customizable
prorationBehavior per plan (#8525)
Bug Fixes
- Improved organization customer search by adding
customerType check (#8609)
- Replaced
{CHECKOUT_SESSION_ID} placeholder in success callbackURL (#8568)
- Returned correct
priceId for annual subscriptions in list (#8810)
For detailed changes, see CHANGELOG
@better-auth/drizzle-adapter
Features
- Added case-insensitive query support (
mode: "insensitive") (#8556)
Bug Fixes
- Fixed Drizzle adapter failing date transformation (#8289)
- Used
IS NULL / IS NOT NULL for null value comparisons (#8660)
For detailed changes, see CHANGELOG
@better-auth/expo
Features
- Exposed plugin version field on all built-in plugins (#8750)
Bug Fixes
- Fixed shim
require issue (#8253)
- Fixed origin override handling across mutable and immutable requests (#8405)
For detailed changes, see CHANGELOG
@better-auth/prisma-adapter
Bug Fixes
- Moved adapter packages to dependencies to fix missing module errors (#8401)
- Used
updateMany fallback for non-unique updates (#8524)
- Used
deleteMany when deleting by non-unique field (#8314)
For detailed changes, see CHANGELOG
auth
Features
- Migrated MCP server URL to
mcp.better-auth.com (#8747)
Bug Fixes
- Fixed path alias resolution from extended tsconfig files (#8520)
- Treated omitted
required as true in Drizzle and Prisma generators (#8614)
For detailed changes, see CHANGELOG
@better-auth/electron
Bug Fixes
- Fixed verification operations with secondary storage (#8247)
- Handled
safeStorage encryption failures gracefully (#8530)
For detailed changes, see CHANGELOG
@better-auth/passkey
Features
- Added pre-auth registration and WebAuthn extensions support (#7154)
Bug Fixes
- Fixed error message strings in passkey client (#8751)
For detailed changes, see CHANGELOG
@better-auth/test-utils
Features
- Exported adapter test suites from
@better-auth/test-utils/adapter (#8564)
Bug Fixes
- Removed
using keyword for runtime compatibility (#8756)
For detailed changes, see CHANGELOG
@better-auth/api-key
Bug Fixes
- Fixed turbo caching, enforced lockfile integrity, and expanded pre-commit hooks (#8892)
For detailed changes, see CHANGELOG
@better-auth/core
Bug Fixes
- Stopped marking redirect
APIErrors as span errors in OpenTelemetry traces (#8850)
For detailed changes, see CHANGELOG
@better-auth/kysely-adapter
Bug Fixes
- Removed deprecated
numUpdatedOrDeletedRows from D1 dialect (#8798)
For detailed changes, see CHANGELOG
@better-auth/telemetry
Bug Fixes
- Used conditional exports to replace dynamic import hacks (#8458)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
@aarmful, @bytaesu, @dvanmali, @Eric-Song-Nop, @formatlos, @GautamBytes, @GoPro16, @gustavovalverde, @himself65, @jonathansamines, @jslno, @mrgrauel, @NathanColosimo, @okisdev, @olliethedev, @Oluwatobi-Mustapha, @OscarCornish, @ping-maxwell, @raihanbrillmark, @sicarius97, @Sigmabrogz, @wuzgood98, @xiaoyu2er, @YevheniiKotyrlo
Full changelog: v1.5.6...v1.6.0