npm better-auth 1.7.0-rc.2
v1.7.0-rc.2

11 hours ago

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 (#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.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

Don't miss a new better-auth release

NewReleases is sending notifications on new releases.