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.accountIdis renamed toAccount.providerAccountId, andAccount.issueris required. Account-specific APIs select the localAccount.idthroughaccountId; token and provider-profile APIs can instead select the signed account cookie withuseAccountCookie: true. Credential accounts uselocal:credentialand the linked user's stableidas their provider identity.OAuth provider identity now comes from raw verified profiles. OpenID Connect discovery uses
sub, plain OAuth usesid, and providers can declareaccountSubjectfor another immutable field; Better Auth no longer switches betweensubandidat runtime.getUserInfo().userno longer carries provider identity, andmapProfileToUsercannot returnid. Read the selected identity fromaccountInfo.account.providerAccountIdinstead ofaccountInfo.user.id. The genericmicrosoftEntraIdhelper 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
subclaim, and SAML uses the signedNameID;mapping.idis removed from both configurations. A manual SAML configuration without metadata XML must setidpMetadata.entityID, becausesamlConfig.issueridentifies 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
ctxtoverifyIdToken(#10376) - feat(db): add compound table indexes (#10402)
- feat(last-login-method):
beforeStoreCookieoption 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-cachecache 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 (#10234)
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.accountIdis renamed toAccount.providerAccountId, andAccount.issueris required. Account-specific APIs select the localAccount.idthroughaccountId; token and provider-profile APIs can instead select the signed account cookie withuseAccountCookie: true. Credential accounts uselocal:credentialand the linked user's stableidas their provider identity.OAuth provider identity now comes from raw verified profiles. OpenID Connect discovery uses
sub, plain OAuth usesid, and providers can declareaccountSubjectfor another immutable field; Better Auth no longer switches betweensubandidat runtime.getUserInfo().userno longer carries provider identity, andmapProfileToUsercannot returnid. Read the selected identity fromaccountInfo.account.providerAccountIdinstead ofaccountInfo.user.id. The genericmicrosoftEntraIdhelper 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
subclaim, and SAML uses the signedNameID;mapping.idis removed from both configurations. A manual SAML configuration without metadata XML must setidpMetadata.entityID, becausesamlConfig.issueridentifies 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.accountIdis renamed toAccount.providerAccountId, andAccount.issueris required. Account-specific APIs select the localAccount.idthroughaccountId; token and provider-profile APIs can instead select the signed account cookie withuseAccountCookie: true. Credential accounts uselocal:credentialand the linked user's stableidas their provider identity.OAuth provider identity now comes from raw verified profiles. OpenID Connect discovery uses
sub, plain OAuth usesid, and providers can declareaccountSubjectfor another immutable field; Better Auth no longer switches betweensubandidat runtime.getUserInfo().userno longer carries provider identity, andmapProfileToUsercannot returnid. Read the selected identity fromaccountInfo.account.providerAccountIdinstead ofaccountInfo.user.id. The genericmicrosoftEntraIdhelper 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
subclaim, and SAML uses the signedNameID;mapping.idis removed from both configurations. A manual SAML configuration without metadata XML must setidpMetadata.entityID, becausesamlConfig.issueridentifies 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