better-authFor detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@erquhart
Full changelog: v1.6.8...v1.6.9
better-authmapProfileToUser fallback for OAuth providers that may omit email from their profile response (#9331)id through beforeCreateTeam and beforeCreateInvitation hooks (#9253)For detailed changes, see CHANGELOG
@better-auth/oauth-providerstate parameter (#9328)For detailed changes, see CHANGELOG
@better-auth/passkeyexactOptionalPropertyTypes compiler option (#9270)For detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@baptisteArno, @gustavovalverde, @ping-maxwell
Full changelog: v1.6.7...v1.6.8
better-authuserId and organizationId parameters to the listUserTeams API for scoped team lookups without switching the active organization (#8977)forceAllowId UUIDs being ignored on PostgreSQL adapters when advanced.database.generateId is set to "uuid" (#9068)APIError is thrown (#9211)$sessionSignal not being triggered for session-rotating endpoints (#9087)partitioned cookie attribute being dropped on set-cookie round-trips (#9235)./instrumentation module to export a no-op in browser and edge environments (#9281)disableRefresh query parameter validation in custom sessions to correctly coerce string values to booleans (#9214)updateUser to allow removing a phone number (#9219)callbackOnVerification not being called when updatePhoneNumber is enabled (#4894)For detailed changes, see CHANGELOG
@better-auth/oauth-provider{ error, error_description } error envelopes for validation failures (#9277)Migration: All six OAuth endpoints (
/oauth2/token,/oauth2/authorize,/oauth2/revoke,/oauth2/introspect,/oauth2/register,/oauth2/end-session) now emit structured{ error, error_description }responses per RFC 6749 Β§5.2. Update any client code that previously parsed the raw validation error format from these endpoints.
Authorization header when called via auth.api (#9244)For detailed changes, see CHANGELOG
@better-auth/api-keymapConcurrent utility for bounded-concurrency iteration (#9227)For detailed changes, see CHANGELOG
@better-auth/drizzle-adapterdrizzle-orm ^0.45.2 and kysely ^0.28.14 peer versions to track vulnerability fixes (#9165)For detailed changes, see CHANGELOG
@better-auth/expoSecureStore on app startup (#8953)For detailed changes, see CHANGELOG
@better-auth/passkeyFor detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@bytaesu, @GautamBytes, @gustavovalverde, @Kinfe123, @ouwargui, @ping-maxwell, @ramonclaudio, @ruban-s, @stewartjarod, @TanishValesha, @terijaki
Full changelog: v1.7.0-beta.1...v1.7.0-beta.2
better-authAPIError is thrown (#9211)./instrumentation module in those environments (#9281)callbackOnVerification not being called when updatePhoneNumber is enabled (#4894)For detailed changes, see CHANGELOG
@better-auth/oauth-providerAuthorization header from request context when using auth.api (#9244)For detailed changes, see CHANGELOG
@better-auth/passkeyFor detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@gustavovalverde, @Kinfe123, @ouwargui, @ramonclaudio, @stewartjarod, @TanishValesha
Full changelog: v1.6.6...v1.6.7
better-authPartitioned attribute when forwarding Set-Cookie headers (#9235)disableRefresh query parameter in custom session validation (#9214)updateUser({ phoneNumber: null }) (#9219)For detailed changes, see CHANGELOG
@better-auth/coremapConcurrent, a bounded-concurrency async utility, at @better-auth/core/utils/async (#9227)@opentelemetry/api an optional peer dependency (#9111)For detailed changes, see CHANGELOG
@better-auth/api-keyFor detailed changes, see CHANGELOG
@better-auth/expoSecureStore on app startup, eliminating the login screen flash for returning users (#8953)For detailed changes, see CHANGELOG
@better-auth/oauth-providerFor detailed changes, see CHANGELOG
@better-auth/ssoFor detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@bytaesu, @gustavovalverde, @jonathansamines, @ping-maxwell, @terijaki
Full changelog: v1.6.5...v1.6.6
better-auth/change-password and /revoke-other-sessions (#9087)For detailed changes, see CHANGELOG
@better-auth/oauth-provider@better-auth/oauth-provider where unprivileged authenticated users could create OAuth clients when deployments relied on clientPrivileges to restrict client creation.@better-auth/oauth-provider@1.6.5.1.7.0-beta.0 and 1.7.0-beta.1) remains affected until a fixed beta release is published.For detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@GautamBytes, @ramonclaudio
Full changelog: v1.6.4...v1.6.5
better-authforceAllowId UUIDs set in database hooks being ignored on PostgreSQL adapters when advanced.database.generateId is set to "uuid" (#9068)For detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@GautamBytes, @gustavovalverde
Full changelog: v1.6.3...v1.6.4
better-authbaseURL resolution from request headers for direct auth.api calls (#9113)isMounted timing issues (#9078)storeBackupCodes storage strategy after verification (#7231)For detailed changes, see CHANGELOG
@better-auth/oauth-providerMigration: Replace
signIn.oauth2({ providerId })withsignIn.social({ provider }),oauth2.link()withlinkSocial(), and update your IdP callback URLs from/api/auth/oauth2/callback/:idto/api/auth/callback/:id. RemovegenericOAuthClient(),issuer, andrequireIssuerValidationfrom your config. Setpkce: falsefor providers that reject PKCE challenges.
customTokenResponseFields callback to inject custom fields into token endpoint responses, and hardened authorization code validation (#9118)at_hash claim to ID tokens to cryptographically bind them to their access tokens, per OIDC Core Β§3.1.3.6 (#9079)baseURL resolution to correctly handle trusted proxy headers, loopback addresses, and forwarded requests in plugin metadata helpers (#9131)For detailed changes, see CHANGELOG
@better-auth/ssocallbackUrl from samlConfig, and fixed SLO session matching (#9117)Migration: Remove
callbackUrlfromsamlConfig(the ACS URL is now auto-derived frombaseURLandproviderId) and update your IdP's ACS URL to/sso/saml2/sp/acs/:providerId. RemovedecryptionPvk,additionalParams,idpMetadata.entityURL, andidpMetadata.redirectURLfromSAMLConfigif present. ThespMetadatafield is now optional and can be removed.
samlify to 2.12.0, adding XPath injection protection and XXE prevention for SAML XML processing (#9121)For detailed changes, see CHANGELOG
@better-auth/cimd β¨@better-auth/cimd plugin for Client ID Metadata Document support, enabling URL-based client identification for MCP and dynamic client discovery flows (#9159)For package details, see README
@better-auth/stripeFor detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@bytaesu, @Byte-Biscuit, @gustavovalverde, @ping-maxwell
Full changelog: v1.7.0-beta.0...v1.7.0-beta.1
better-authoperationId for the requestPasswordResetCallback endpoint in the OpenAPI spec (#9072)baseURL resolution from request headers for direct auth.api calls (#9113)isMounted race condition that caused excessive requests per second in the client (#9078)storeBackupCodes storage strategy after verification (#7231)For detailed changes, see CHANGELOG
@better-auth/oauth-providercustomTokenResponseFields callback for injecting custom fields into token endpoint responses, and hardened authorization code validation (#9118)baseURL resolution for direct auth.api calls and plugin metadata helpers (#9131)For detailed changes, see CHANGELOG
@better-auth/ssoFor detailed changes, see CHANGELOG
@better-auth/stripeFor detailed changes, see CHANGELOG
authFor detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@bytaesu, @Byte-Biscuit, @gustavovalverde, @Oluwatobi-Mustapha, @ping-maxwell, @ramonclaudio
Full changelog: v1.6.2...v1.6.3
better-authfeat(two-factor)!: add OTP enablement and discriminated response (#9057)
enableTwoFactor now accepts a method parameter ("otp" | "totp", default "totp") and returns a discriminated response with a method field.
method: "otp"twoFactorEnabled: true immediately.{ method: "otp" }.otpOptions.sendOTP to be configured on the server; rejects with OTP_NOT_CONFIGURED otherwise.method: "totp" (default){ method: "totp", totpURI, backupCodes }.TOTP_NOT_CONFIGURED if totpOptions.disable is set.skipVerificationOnEnable: use method: "otp" for immediate activation, or the standard TOTP verification flow.enableTwoFactor includes a method field in the response ("otp" or "totp").operationId in password reset callback endpoint (#9072)For detailed changes, see CHANGELOG
@better-auth/ssofix(sso)!: harden SAML response validation (InResponseTo, Audience, SessionIndex) (#9055)
allowIdpInitiated now defaults to false β IdP-initiated SSO (unsolicited SAML responses) is disabled by default. Set saml.allowIdpInitiated: true to restore the previous behavior. This aligns with the SAML2Int interoperability profile which recommends against IdP-initiated SSO due to its susceptibility to injection attacks.extract.inResponseTo (always undefined) instead of samlify's actual path extract.response.inResponseTo. SP-initiated InResponseTo validation now works as intended in both ACS handlers.<AudienceRestriction> element. Audience is now validated against the configured samlConfig.audience value per SAML 2.0 Core Β§2.5.1.sessionIndex from login responses as { authnInstant, sessionNotOnOrAfter, sessionIndex }, but the code stored the whole object. SLO session-index comparisons always failed silently. The correct inner sessionIndex string is now extracted.validateInResponseTo() and validateAudience() into packages/sso/src/saml/response-validation.ts, eliminating ~160 lines of duplicated validation logic between the two ACS handlers.SAMLAssertionExtract type to match samlify's actual extractor output shape.For detailed changes, see CHANGELOG
@better-auth/oauth-providerprivate_key_jwt client authentication (RFC 7523) (#8836)For detailed changes, see CHANGELOG
authFor detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@bytaesu, @gustavovalverde, @Oluwatobi-Mustapha, @ramonclaudio
Full changelog: v1.6.2...v1.7.0-beta.0
better-authMigration: Schema migration required.
Add the
verifiedcolumn to thetwoFactortable, then regenerate/apply your ORM migration.
- Prisma: run
npx auth@latest generate, thennpx prisma migrate dev(ornpx prisma db push) andnpx prisma generate.- Drizzle: run
npx auth@latest generate, thennpx drizzle-kit generateandnpx drizzle-kit migrate.
Existing rows do not need a backfill because the column defaults to
true.
nextCookies() by replacing cookie probe with header-based RSC detection (#9059)RelayState in signed SAML AuthnRequests (#9058)For detailed changes, see CHANGELOG
@better-auth/oauth-providerskip_consent at schema level in dynamic client registration (#8998)For detailed changes, see CHANGELOG
@better-auth/ssoFor detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@aarmful, @cyphercodes, @dvanmali, @gustavovalverde, @jaydeep-pipaliya, @ping-maxwell
Full changelog: v1.6.1...v1.6.2
better-authINVALID_PASSWORD for all checkPassword failures (#8902)getSession accessibility in generic Auth<O> context (#9017)For detailed changes, see CHANGELOG
Thanks to everyone who contributed to this release:
@bytaesu, @jonathansamines, @ping-maxwell
Full changelog: v1.6.0...v1.6.1
Blog post: Better Auth 1.6
better-authfreshAge calculation with session creation time instead of update time (#8762)Migration:
session.freshAgenow calculates fromcreatedAt. Setsession: { freshAge: 0 }to disable the check entirely.
resendStrategy option to reuse existing OTP in email-otp plugin (#8560)enable option for HaveIBeenPwned plugin (#8728)sendMagicLink callback (#8571)secret option to OAuth proxy to reduce shared key exposure (#8699)organizationId parameter in team endpoints (#5062)twoFactorPage config option for custom 2FA page routing (#5329)oidc-provider plugin in favor of @better-auth/oauth-provider (#8985)accountId instead of internal id (#8786)skipOriginCheck array handling (#8582)user field through idToken sign-in body for Apple name support (#8417)operationId in admin plugin endpoints (#8570)sendOTP failures instead of silently swallowing them (#8842)cookieCache maxAge to match session.expiresIn (#8648)autoSignIn: false without requireEmailVerification (#8521)accountInfo endpoint to use accountId instead of internal id (#8346)createAdapter and type exports for backwards compatibility (#8461)Response return for HTTP request contexts (#7521)throw: true handling in client session refresh (#8610)generateId: "uuid" over adapter customIdGenerator (#8679)safeJSONParse for pre-parsed objects (#8248)CREATE INDEX (#8538)sessionSignal after requesting email change in email-otp (#8816)/magic-link/verify (#7223)form_post (#8895)storeIdentifier is hashed (#8980)redirect_uri validation for prompt=none in oidc-provider (#8398)listUserInvitations (#8694)twoFactorTable option to schema modelName (#8443)any from collapsing auth.$Infer and client inference types (#8981)updateUser to not overwrite unrelated username fields (#7570)updateUser (#8731)For detailed changes, see CHANGELOG
@better-auth/ssoMigration: Set
sso({ saml: { enableInResponseToValidation: false } })to restore the previous behavior.
node-forge vulnerability via samlify pin (#8838)sub claim correctly (#8276)provisionUser inconsistency and added provisionUserOnEveryLogin option (#8818)internalAdapter (#8353)For detailed changes, see CHANGELOG
@better-auth/mongo-adapterMigration: New documents use native BSON UUIDs. Existing string UUIDs continue to work. No data migration required.
For detailed changes, see CHANGELOG
@better-auth/oauth-providerisLocalhost function (#8286)customIdTokenClaims to override standard claims (#7865)baseURL config handling in init (#8649)oauth_query in client plugin (#8320)customIdTokenClaims to override acr and auth_time (#8633)auth_time timestamps across adapter shapes (#8761)skip_consent (#8632)prompt=none support (#8554)For detailed changes, see CHANGELOG
@better-auth/stripeprorationBehavior per plan (#8525)customerType check (#8609){CHECKOUT_SESSION_ID} placeholder in success callbackURL (#8568)priceId for annual subscriptions in list (#8810)For detailed changes, see CHANGELOG
@better-auth/drizzle-adaptermode: "insensitive") (#8556)IS NULL / IS NOT NULL for null value comparisons (#8660)For detailed changes, see CHANGELOG
@better-auth/exporequire issue (#8253)For detailed changes, see CHANGELOG
@better-auth/prisma-adapterupdateMany fallback for non-unique updates (#8524)deleteMany when deleting by non-unique field (#8314)For detailed changes, see CHANGELOG
authmcp.better-auth.com (#8747)required as true in Drizzle and Prisma generators (#8614)For detailed changes, see CHANGELOG
@better-auth/electronsafeStorage encryption failures gracefully (#8530)For detailed changes, see CHANGELOG
@better-auth/passkeyFor detailed changes, see CHANGELOG
@better-auth/test-utils@better-auth/test-utils/adapter (#8564)using keyword for runtime compatibility (#8756)For detailed changes, see CHANGELOG
@better-auth/api-keyFor detailed changes, see CHANGELOG
@better-auth/coreAPIErrors as span errors in OpenTelemetry traces (#8850)For detailed changes, see CHANGELOG
@better-auth/kysely-adapternumUpdatedOrDeletedRows from D1 dialect (#8798)For detailed changes, see CHANGELOG
@better-auth/telemetryFor detailed changes, see CHANGELOG
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
No significant changes
resendStrategy option to reuse existing OTP Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8560 <samp>(bbe1a)</samp>secret option to reduce shared key exposure surface Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8699 <samp>(faffb)</samp>organizationId in team endpoints Β -Β by @xiaoyu2er and @himself65 in https://github.com/better-auth/better-auth/issues/5062 <samp>(5d60d)</samp>prorationBehavior per plan Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8525 <samp>(9fdd6)</samp>@better-auth/test-utils/adapter Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8564 <samp>(6578b)</samp>twoFactorPage in config Β -Β by @wuzgood98 in https://github.com/better-auth/better-auth/issues/5329 <samp>(caa9f)</samp>user field through idToken sign-in body for Apple name support Β -Β by @bytaesu and Copilot in https://github.com/better-auth/better-auth/issues/8417 <samp>(d8139)</samp>autoSignIn: false without requireEmailVerification Β -Β by @himself65 in https://github.com/better-auth/better-auth/issues/8521 <samp>(f72e2)</samp>skipOriginCheck array Β -Β by @jslno in https://github.com/better-auth/better-auth/issues/8582 <samp>(92895)</samp>required as true in Drizzle and Prisma generators Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8614 <samp>(b0069)</samp>throw:true in session refresh Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8610 <samp>(f0c1a)</samp>CREATE INDEX for postgres migration Β -Β by @himself65 in https://github.com/better-auth/better-auth/issues/8538 <samp>(a980b)</samp>{CHECKOUT_SESSION_ID} placeholder in success callbackURL Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8568 <samp>(db470)</samp>resendStrategy option to reuse existing OTP Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8560 <samp>(98c8e)</samp>organizationId in team endpoints Β -Β by @xiaoyu2er and @himself65 in https://github.com/better-auth/better-auth/issues/5062 <samp>(8f470)</samp>prorationBehavior per plan Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8525 <samp>(98cea)</samp>@better-auth/test-utils/adapter Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8564 <samp>(6be0f)</samp>twoFactorPage in config Β -Β by @wuzgood98 in https://github.com/better-auth/better-auth/issues/5329 <samp>(4f41b)</samp>skipOriginCheck array Β -Β by @jslno in https://github.com/better-auth/better-auth/issues/8582 <samp>(331c4)</samp>throw:true in session refresh Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8610 <samp>(275ca)</samp>{CHECKOUT_SESSION_ID} placeholder in success callbackURL Β -Β by @bytaesu in https://github.com/better-auth/better-auth/issues/8568 <samp>(32704)</samp>user field through idToken sign-in body for Apple name support Β -Β by @bytaesu and Copilot in https://github.com/better-auth/better-auth/issues/8417 <samp>(d364e)</samp>autoSignIn: false without requireEmailVerification Β -Β by @himself65 in https://github.com/better-auth/better-auth/issues/8521 <samp>(e3e66)</samp>CREATE INDEX for postgres migration Β -Β by @himself65 in https://github.com/better-auth/better-auth/issues/8538 <samp>(b9e54)</samp>