# Better Auth changelog > Framework-agnostic authentication and authorization for TypeScript. - Vendor: Better Auth - Category: Frameworks & Libraries - Official site: https://better-auth.com - Tracked by: What's New (https://whatsnew.fyi/product/better-auth) - Harvested from: GitHub (better-auth/better-auth) - Entries below: 10 (newest first) What's New is an index, not a publisher: every entry below links to the vendor's own release notes, which are the authoritative source. Entries are labelled where they are hand-curated sample data, pre-releases, or drawn from a secondary source such as a developer blog. ## Releases ### v1.6.25 - Date: 2026-07-23 - Version: v1.6.25 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.6.25 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.6.25 - **fixed** — Fixed Apple OAuth not sending the PKCE code challenge during authorization, causing token exchange failures - **fixed** — Fixed Google One Tap creating new users when sign-up was disabled on the Google provider - **fixed** — Fixed $fetch and $store not being exposed on the Solid client - **fixed** — Fixed internal adapter queries being routed to the wrong table when a built-in table's modelName was set to another table's schema key ##### `better-auth` ###### Bug Fixes - Fixed Apple OAuth not sending the PKCE code challenge during authorization, causing token exchange failures ([#10294](https://github.com/better-auth/better-auth/pull/10294)) - Fixed Google One Tap creating new users when sign-up was disabled on the Google provider ([#10479](https://github.com/better-auth/better-auth/pull/10479)) - Fixed `$fetch` and `$store` not being exposed on the Solid client ([#10444](https://github.com/better-auth/better-auth/pull/10444)) - Fixed internal adapter queries being routed to the wrong table when a built-in table's `modelName` was set to another table's schema key (e.g. `user.modelName = "account"`). For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/07a646ea190167370fbbb60a0fa2c3be3bec5522/packages/better-auth/CHANGELOG.md) ##### Contributors Thanks to everyone who contributed to this release: @birkskyum, @jsj, @krish-vachhani **Full changelog:** [`v1.6.24...v1.6.25`](https://github.com/better-auth/better-auth/compare/v1.6.24...v1.6.25) ### v1.7.0-rc.2 - Date: 2026-07-22 - Version: v1.7.0-rc.2 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.7.0-rc.2 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.7.0-rc.2 - Labels: Pre-release - **changed** — Move joins configuration from experimental.joins to advanced.database.joins - **changed** — Rename Account.accountId to Account.providerAccountId and make Account.issuer required - **changed** — Change account-specific APIs to select Account.id through accountId parameter - **changed** — Use token and provider-profile APIs with useAccountCookie option for signed account cookie selection - **changed** — Use local:credential as credential accounts provider identity - **changed** — OAuth provider identity now comes from raw verified profiles with OIDC using sub and plain OAuth using id - **changed** — Providers can declare accountSubject for another immutable field instead of switching between sub and id at runtime - **changed** — getUserInfo().user no longer carries provider identity and mapProfileToUser cannot return id - **changed** — Read selected identity from accountInfo.account.providerAccountId instead of accountInfo.user.id - **changed** — Generic microsoftEntraId helper now requires a concrete tenant GUID - **changed** — SSO account subjects now use protocol-defined values with OIDC using verified sub claim and SAML using signed NameID - **removed** — Remove mapping.id from OIDC and SAML configurations - **removed** — Remove SCIM configuration, client APIs, database schema, and organization-backed Group model - **changed** — Deferred database side effects now run only after successful transaction - **added** — Add ctx parameter to verifyIdToken - **added** — Add compound table indexes to database - **added** — Add beforeStoreCookie option to last-login-method plugin for GDPR compliance - **added** — Add getOrganization method for metadata-only fetches in organization plugin - **added** — Add transactional OIDC user resolution to SSO - **fixed** — Add no-cache cache control headers to get-session endpoint - **fixed** — Recognize BIGINT as valid number type for SQLite in migrations - **fixed** — Handle request clone failures in callbacks ##### `better-auth` ###### ❗ Breaking Changes - chore!: move joins to advanced.database.joins ([#10359](https://github.com/better-auth/better-auth/pull/10359)) If you previously set `experimental: { joins: true }`, update your config to: ```ts 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](https://github.com/better-auth/better-auth/pull/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](https://github.com/better-auth/better-auth/pull/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](https://github.com/better-auth/better-auth/pull/10376)) - feat(db): add compound table indexes ([#10402](https://github.com/better-auth/better-auth/pull/10402)) - feat(last-login-method): `beforeStoreCookie` option for GDPR compliance ([#5753](https://github.com/better-auth/better-auth/pull/5753)) - feat(organization): add getOrganization for metadata-only fetches ([#10397](https://github.com/better-auth/better-auth/pull/10397)) - feat(sso): add transactional OIDC user resolution ([#10473](https://github.com/better-auth/better-auth/pull/10473)) ###### Bug Fixes - chore: widen drizzle-kit peer dependency range ([#10299](https://github.com/better-auth/better-auth/pull/10299)) - fix: get-session should have `no-cache` cache control headers ([#10222](https://github.com/better-auth/better-auth/pull/10222)) - fix: recognize BIGINT as valid number type for SQLite in migrations. ([#10316](https://github.com/better-auth/better-auth/pull/10316)) - fix(aut _[Truncated at 4000 characters — full notes: https://github.com/better-auth/better-auth/releases/tag/v1.7.0-rc.2]_ ### v1.6.24 - Date: 2026-07-22 - Version: v1.6.24 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.6.24 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.6.24 - **added** — Request context (ctx) as a third argument to verifyIdToken, enabling custom ID token verifiers to read request headers - **added** — beforeStoreCookie option to the last-login-method plugin for GDPR compliance - **fixed** — get-session endpoint to include no-store cache control headers, preventing stale session data from being served - **fixed** — SQLite migration diffs to recognize BIGINT as a valid number type, preventing spurious pending changes on rate limiter columns - **fixed** — Auth requests failing when request cloning throws an error inside verification callbacks - **fixed** — useSession({ throw: true }) incorrectly excluding null from its data type - **fixed** — Auth query revalidation and signal listeners not being restored after a client component remounts - **fixed** — CookieAttributes index signature type to be more precise - **fixed** — Silent misrouting of adapter queries when user.modelName was set to a value that collides with another schema key - **fixed** — Kysely migration generation producing duplicate indexes for fields marked both unique and index - **fixed** — Magic-link and email-OTP send endpoints to validate the Origin header on cookieless requests, preventing cross-origin abuse - **fixed** — Remote MCP auth 401 challenge headers being hidden from browser clients due to missing CORS exposure - **fixed** — OpenAPI schema to include plugin user fields (such as username and displayUsername) in /sign-up/email and /update-user request bodies - **fixed** — organization.listMembers failing with "User not found for member" for organizations with more than ~100 members - **fixed** — Organization invitations to use database-generated IDs when advanced.database.generateId is configured, matching the behavior of other models - **fixed** — getDefaultModelName to prefer exact schema key matches over modelName aliases, preventing adapter queries from being misrouted - **fixed** — SvelteKit builds by stubbing explicit-environment-variables modules - **fixed** — Drizzle schema generation producing duplicate indexes for fields marked both unique and index - **fixed** — Drizzle schema generation for tables with multiple foreign keys to the same model by adding disambiguating relationName values - **fixed** — /electron/init-oauth-proxy forwarding multiple Set-Cookie headers as a single comma-joined string, which caused the browser to drop the transfer-token cookie during OAuth handoff - **fixed** — Intermittent "No request state found" error caused by a race condition in AsyncLocalStorage initialization on serverless cold starts ##### `better-auth` ###### Features - Added request context (`ctx`) as a third argument to `verifyIdToken`, enabling custom ID token verifiers to read request headers ([#10376](https://github.com/better-auth/better-auth/pull/10376)) - Added `beforeStoreCookie` option to the last-login-method plugin for GDPR compliance ([#5753](https://github.com/better-auth/better-auth/pull/5753)) ###### Bug Fixes - Replaced flaky MongoDB where-coercion integration test with a direct unit test for more reliable test runs ([#10369](https://github.com/better-auth/better-auth/pull/10369)) - Fixed the `get-session` endpoint to include `no-store` cache control headers, preventing stale session data from being served ([#10222](https://github.com/better-auth/better-auth/pull/10222)) - Fixed SQLite migration diffs to recognize `BIGINT` as a valid number type, preventing spurious pending changes on rate limiter columns ([#10316](https://github.com/better-auth/better-auth/pull/10316)) - Fixed auth requests failing when request cloning throws an error inside verification callbacks ([#10336](https://github.com/better-auth/better-auth/pull/10336)) - Fixed `useSession({ throw: true })` incorrectly excluding `null` from its `data` type ([#9787](https://github.com/better-auth/better-auth/pull/9787)) - Fixed auth query revalidation and signal listeners not being restored after a client component remounts ([#10379](https://github.com/better-auth/better-auth/pull/10379)) - Fixed the `CookieAttributes` index signature type to be more precise ([#10442](https://github.com/better-auth/better-auth/pull/10442)) - Fixed silent misrouting of adapter queries when `user.modelName` was set to a value that collides with another schema key ([#10235](https://github.com/better-auth/better-auth/pull/10235)) - Fixed Kysely migration generation producing duplicate indexes for fields marked both `unique` and `index` ([#10357](https://github.com/better-auth/better-auth/pull/10357)) - Fixed magic-link and email-OTP send endpoints to validate the `Origin` header on cookieless requests, preventing cross-origin abuse ([#10368](https://github.com/better-auth/better-auth/pull/10368)) - Fixed remote MCP auth 401 challenge headers being hidden from browser clients due to missing CORS exposure ([#10290](https://github.com/better-auth/better-auth/pull/10290)) - Fixed OpenAPI schema to include plugin user fields (such as `username` and `displayUsername`) in `/sign-up/email` and `/update-user` request bodies ([#10453](https://github.com/better-auth/better-auth/pull/10453)) - Fixed `organization.listMembers` failing with "User not found for member" for organizations with more than ~100 members ([#10342](https://github.com/better-auth/better-auth/pull/10342)) - Fixed organization invitations to use database-generated IDs when `advanced.database.generateId` is configured, matching the behavior of other models ([#10040](https://github.com/better-auth/better-auth/pull/10040)) - Fixed `getDefaultModelName` to prefer exact schema key matches over `modelName` aliases, preventing adapter queries from being misrouted when a built-in table's name collides with another schema key For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/9a661c7b7abceaa81123b2c56757ee24f3ad2ed6/packages/better-auth/CHANGELOG.md) ##### `auth` ###### Bug Fixes - Fixed SvelteKit builds by stubbing explicit-environment-variables modules ([#10221](https://github.com/better-auth/better-auth/pull/10221)) - Fixed Drizzle schema generation producing duplicate indexes for fields marked both `unique` and `index` ([#10333](https://github.com/better-auth/better-auth/pull/10333)) - Fixed Drizzle schema generation for tables with multiple foreign keys to the same model by adding disambiguating `relationName` values ([#10352](https://github.com/better-auth/better-auth/pull/10352)) - Fixed `auth generate` failing when the config file imports the not-yet-generated output file (e.g. on a Convex first run _[Truncated at 4000 characters — full notes: https://github.com/better-auth/better-auth/releases/tag/v1.6.24]_ ### v1.7.0-rc.1 - Date: 2026-07-02 - Version: v1.7.0-rc.1 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.7.0-rc.1 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.7.0-rc.1 - Labels: Pre-release - **added** — Add Yandex as a supported OAuth social provider - **fixed** — Fix auth migrate to no longer abort when adding required or unique columns to an existing table - **fixed** — Fix affected row counting for D1 and postgres-js adapters - **fixed** — Fix string default values to be properly escaped in generated Drizzle schema ##### `better-auth` ###### Features - Added Yandex as a supported OAuth social provider ([#9138](https://github.com/better-auth/better-auth/pull/9138)) ###### Bug Fixes - Fixed `auth migrate` to no longer abort when adding required or unique columns to an existing table ([#10293](https://github.com/better-auth/better-auth/pull/10293)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/fb1dff141c3ae8de325f190b154a7f9e9f86979a/packages/better-auth/CHANGELOG.md) ##### `@better-auth/drizzle-adapter` ###### Bug Fixes - Fixed affected row counting for D1 and postgres-js adapters ([#10257](https://github.com/better-auth/better-auth/pull/10257)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/fb1dff141c3ae8de325f190b154a7f9e9f86979a/packages/drizzle-adapter/CHANGELOG.md) ##### `auth` ###### Bug Fixes - Fixed string default values to be properly escaped in generated Drizzle schema ([#10259](https://github.com/better-auth/better-auth/pull/10259)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/fb1dff141c3ae8de325f190b154a7f9e9f86979a/packages/cli/CHANGELOG.md) ##### Contributors Thanks to everyone who contributed to this release: @bytaesu, @gustavovalverde, @vladflotsky **Full changelog:** [`v1.7.0-rc.0...v1.7.0-rc.1`](https://github.com/better-auth/better-auth/compare/v1.7.0-rc.0...v1.7.0-rc.1) ### v1.6.23 - Date: 2026-06-29 - Version: v1.6.23 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.6.23 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.6.23 - **added** — Add Yandex as a social OAuth provider - **fixed** — Fix affected row counting for D1 and postgres-js adapters - **fixed** — Fix organization subscription actions (cancel, upgrade, restore, and the billing portal) that could act on the wrong organization - **fixed** — Fix string default values not being properly escaped in the generated Drizzle schema ##### `better-auth` ###### Features - Added Yandex as a social OAuth provider ([#9138](https://github.com/better-auth/better-auth/pull/9138)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/9dfceee14021fc15a2fb93023f39635f25b0b5ba/packages/better-auth/CHANGELOG.md) ##### `@better-auth/drizzle-adapter` ###### Bug Fixes - Fixed affected row counting for D1 and postgres-js adapters ([#10257](https://github.com/better-auth/better-auth/pull/10257)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/9dfceee14021fc15a2fb93023f39635f25b0b5ba/packages/drizzle-adapter/CHANGELOG.md) ##### `@better-auth/stripe` ###### Bug Fixes - Fixed organization subscription actions (cancel, upgrade, restore, and the billing portal) that could act on the wrong organization. For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/9dfceee14021fc15a2fb93023f39635f25b0b5ba/packages/stripe/CHANGELOG.md) ##### `auth` ###### Bug Fixes - Fixed string default values not being properly escaped in the generated Drizzle schema ([#10259](https://github.com/better-auth/better-auth/pull/10259)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/9dfceee14021fc15a2fb93023f39635f25b0b5ba/packages/cli/CHANGELOG.md) ##### Contributors Thanks to everyone who contributed to this release: @bytaesu, @vladflotsky **Full changelog:** [`v1.6.22...v1.6.23`](https://github.com/better-auth/better-auth/compare/v1.6.22...v1.6.23) ### v1.7.0-rc.0 - Date: 2026-06-26 - Version: v1.7.0-rc.0 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.7.0-rc.0 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.7.0-rc.0 - Labels: Pre-release - **changed** — Support wildcard endpoint matching in captcha - **changed** — Ship MCP as its own package built on the OAuth provider, renaming route helper to requireMcpAuth and remote client to createMcpResourceClient - **changed** — Add OIDC back-channel logout to oauth-provider, notifying Relying Parties when a user's session ends and invalidating access tokens immediately - **changed** — Revoke refresh tokens without offline_access on session end while preserving offline_access refresh tokens for long-lived API access - **changed** — Add backchannel_logout_supported and backchannel_logout_session_supported to OIDC discovery endpoints when JWT plugin is enabled - **changed** — Model OAuth protected resources explicitly by removing validAudiences and moving resource identifiers to resources configuration - **changed** — Apply resource policy to RFC 8707 resource values in access-token issuance and narrow scopes to resource allowlists - **changed** — Add revoked date field to oauthAccessToken schema - **changed** — Add backchannelLogoutUri and backchannelLogoutSessionRequired fields to oauthClient schema - **changed** — Use shortest configured TTL across resources for access-token issuance - **changed** — Emit jti claim and keep repeated resource form parameters in OAuth access tokens - **changed** — Add support for per-resource signing key pins with signingKeyId and signingAlgorithm parameters to signJWT() - **changed** — Add nullable alg and crv columns to jwks table and support multiple algorithms in one keyring via keyPairConfigs - **changed** — Add oauthResource and oauthClientResource tables to schema - **changed** — Add optional header argument to signJWT for setting JWT media types like logout+jwt - **changed** — Require explicit resource option for @better-auth/mcp plugin - **changed** — Make jwt() plugin required for @better-auth/mcp token signing - **changed** — Rename oauthApplication to oauthClient and add oauthRefreshToken and oauthClientAssertion tables - **changed** — Accept method parameter in enableTwoFactor with values otp or totp, defaulting to totp, and return discriminated response with method field ##### `better-auth` ###### ❗ Breaking Changes - feat(captcha)!: support wildcard endpoint matching ([#10004](https://github.com/better-auth/better-auth/pull/10004)) - feat(mcp)!: ship MCP as its own package built on the OAuth provider ([#9992](https://github.com/better-auth/better-auth/pull/9992)) The route helper is renamed `requireMcpAuth` (was `withMcpAuth`), and the remote client is `createMcpResourceClient` (was `createMcpAuthClient`). `requireMcpAuth` verifies the bearer token against the published JWKS and passes the verified JWT claims to your handler. To migrate, install `@better-auth/mcp`, add the `jwt()` plugin (now required for token signing), and move options that were nested under `oidcConfig` to flat options on `mcp({ ... })`. The database models change: `oauthApplication` becomes `oauthClient`, with new `oauthRefreshToken` and `oauthClientAssertion` tables. Regenerate or migrate your schema with `npx auth migrate` or `npx auth generate`. - feat(oauth-provider)!: add OIDC back-channel logout ([#9304](https://github.com/better-auth/better-auth/pull/9304)) When a user's session ends at the OP (sign-out, `/oauth2/end-session`, admin revoke, ban), `@better-auth/oauth-provider` now notifies every Relying Party that holds tokens for that session. The user's API access is cut off right away, instead of access tokens staying usable until their own TTL. Each client opts in by registering a `backchannel_logout_uri` (and optionally `backchannel_logout_session_required`) via DCR or the admin client-create endpoint. The provider signs a `logout+jwt` Logout Token per client and POSTs it to that client in parallel, with a short per-RP timeout. **Breaking change.** Introspection of an opaque or JWT access token whose bound session has ended now returns `{ active: false }`, and `/oauth2/userinfo` rejects it with `invalid_token`. Previously the token stayed active until its own TTL. If you relied on access tokens outliving the user's session, that no longer holds. Refresh tokens without `offline_access` are revoked on session end; `offline_access` refresh tokens are preserved so long-lived API access can survive the browser session (OIDC Back-Channel Logout 1.0 §2.7). Access-token invalidation on session end is an additional OP hardening choice beyond §2.7, enforced by session liveness, so it holds even when the JWT plugin is disabled. Delivery runs through the host's background task handler when one is configured (Vercel `waitUntil`, Cloudflare `ctx.waitUntil`); without a handler it completes inline so notifications are not lost on request teardown. Configure `advanced.backgroundTasks.handler` on serverless runtimes to keep sign-out fast. Discovery at `/.well-known/openid-configuration` and `/.well-known/oauth-authorization-server` advertises `backchannel_logout_supported: true` and `backchannel_logout_session_supported: true` when the JWT plugin is enabled. Registering a `backchannel_logout_uri` rejects fragments, non-http(s) schemes, and non-HTTPS targets on confidential clients. Its SSRF host guard, which blocks private, reserved, tunneled, and cloud-metadata hosts, now also covers a `private_key_jwt` client's `jwks_uri`. Schema changes on `@better-auth/oauth-provider`: - `oauthClient.backchannelLogoutUri: string | null` - `oauthClient.backchannelLogoutSessionRequired: boolean` - `oauthAccessToken.revoked: Date | null` `better-auth`'s `signJWT` gains an optional `header` argument, forwarded to custom remote signers. JWT profiles that need an explicit media type, such as `typ: "logout+jwt"`, can now set it without reaching for the low-level signing primitives. - feat(oauth-provider)!: model OAuth protected resources explicitly ([#9648](https://github.com/better-auth/better-auth/pull/9648)) `validAudiences` is removed. Move each existing resource identifier into `resources`; link clients that should be limited to specific resources through `oauthClientResource` or Dynamic Client Registrati _[Truncated at 4000 characters — full notes: https://github.com/better-auth/better-auth/releases/tag/v1.7.0-rc.0]_ ### v1.7.0-beta.10 - Date: 2026-06-26 - Version: v1.7.0-beta.10 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.7.0-beta.10 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.7.0-beta.10 - Labels: Pre-release - **fixed** — Bundled dependencies were refreshed to their latest compatible releases, including jose, nanostores, the noble crypto packages, and SimpleWebAuthn - **fixed** — Rate limiting is now applied before plugin request handlers run - **fixed** — Unproven credentials are now revoked when signing in via magic link or email OTP - **fixed** — Account-linking logs are now routed through the configured logger - **fixed** — Admin authorization now uses authoritative session reads - **fixed** — TypeScript inference errors from inherited APIError properties have been resolved - **fixed** — Server-side OAuth requests no longer follow redirects - **fixed** — The schema option in device authorization is now optional under Zod v4 - **fixed** — Hosted-domain validation is now applied consistently across all Google sign-in flows - **fixed** — OAuth proxy now rejects profile callbacks when OAuth state is missing or expired - **fixed** — OAuth provider profiles now respect user input rules - **fixed** — PayPal userinfo subject is now bound to the verified ID token subject - **fixed** — Refresh cookie Max-Age is now capped at the configured expiresIn value - **fixed** — SIWE sign-in now rejects when the provided email already belongs to another account - **fixed** — TOTP and backup code verification now cap the number of allowed attempts - **fixed** — Username storage now only accepts valid displayUsername fallbacks - **fixed** — SSO provider deletion now also removes associated linked account rows - **fixed** — SSO provider domain verification now requires DNS proof for every listed domain - **fixed** — SAML SLO POST form action is now restricted to http and https schemes - **fixed** — SAML response binding is now validated against the Service Provider configuration ##### `better-auth` ###### Bug Fixes - Bundled dependencies were refreshed to their latest compatible releases, including jose, nanostores, the noble crypto packages, and SimpleWebAuthn. These updates are backward compatible and require no changes to existing projects. - Fixed rate limiting to be applied before plugin request handlers run ([#10191](https://github.com/better-auth/better-auth/pull/10191)) - Fixed unproven credentials to be revoked when signing in via magic link or email OTP ([#10239](https://github.com/better-auth/better-auth/pull/10239)) - Fixed account-linking logs to be routed through the configured logger ([#10121](https://github.com/better-auth/better-auth/pull/10121)) - Fixed admin authorization to use authoritative session reads ([#10187](https://github.com/better-auth/better-auth/pull/10187)) - Fixed TypeScript inference errors by declaring inherited `APIError` properties ([#8734](https://github.com/better-auth/better-auth/pull/8734)) - Fixed server-side OAuth requests to no longer follow redirects ([#10241](https://github.com/better-auth/better-auth/pull/10241)) - Fixed the `schema` option in device authorization to be optional under Zod v4 ([#9939](https://github.com/better-auth/better-auth/pull/9939)) - Fixed hosted-domain validation to be applied consistently across all Google sign-in flows ([#10197](https://github.com/better-auth/better-auth/pull/10197)) - Fixed OAuth proxy to reject profile callbacks when OAuth state is missing or expired ([#10183](https://github.com/better-auth/better-auth/pull/10183)) - Fixed OAuth provider profiles to respect user input rules ([#10196](https://github.com/better-auth/better-auth/pull/10196)) - Fixed PayPal userinfo subject to be bound to the verified ID token subject ([#10192](https://github.com/better-auth/better-auth/pull/10192)) - Fixed refresh cookie `Max-Age` to be capped at the configured `expiresIn` value ([#9621](https://github.com/better-auth/better-auth/pull/9621)) - Fixed SIWE sign-in to reject when the provided email already belongs to another account ([#10228](https://github.com/better-auth/better-auth/pull/10228)) - Fixed TOTP and backup code verification to cap the number of allowed attempts ([#10210](https://github.com/better-auth/better-auth/pull/10210)) - Fixed username storage to only accept valid `displayUsername` fallbacks ([#10182](https://github.com/better-auth/better-auth/pull/10182)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/ba52913eed6e7210808511752bf546981f6980f5/packages/better-auth/CHANGELOG.md) ##### `@better-auth/sso` ###### Bug Fixes - Fixed SSO provider deletion to also remove associated linked account rows ([#10224](https://github.com/better-auth/better-auth/pull/10224)) - Fixed SSO provider domain verification to require DNS proof for every listed domain ([#10227](https://github.com/better-auth/better-auth/pull/10227)) - Fixed SAML SLO POST form action to be restricted to `http` and `https` schemes ([#10225](https://github.com/better-auth/better-auth/pull/10225)) - Fixed SAML response binding to be validated against the Service Provider configuration ([#10226](https://github.com/better-auth/better-auth/pull/10226)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/ba52913eed6e7210808511752bf546981f6980f5/packages/sso/CHANGELOG.md) ##### `auth` ###### Bug Fixes - Fixed `disableMigration` to be honored for plugin schema tables ([#10198](https://github.com/better-auth/better-auth/pull/10198)) - Fixed generated `BETTER_AUTH_SECRET` to use 32 characters instead of 16 ([#10186](https://github.com/better-auth/better-auth/pull/10186)) - Fixed two-factor verification to enforce account-level lockout after repeated failed attempts ([#10240](https://github.com/better-auth/better-auth/pull/10240)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/ba52913eed6e7210808511752bf546981f6980f5/packages/cli/CHANGELOG. _[Truncated at 4000 characters — full notes: https://github.com/better-auth/better-auth/releases/tag/v1.7.0-beta.10]_ ### v1.6.22 - Date: 2026-06-26 - Version: v1.6.22 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.6.22 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.6.22 - **fixed** — Unproven credentials are now revoked during magic link and email OTP sign-in - **fixed** — Server-side OAuth requests now refuse redirect responses instead of following them - **fixed** — SCIM write-path operations are now properly scoped and correctly honor the active attribute - **fixed** — Organization subscription actions (cancel, upgrade, restore, and the billing portal) no longer act on the wrong organization - **added** — Account-level verification lockout for two-factor authentication ##### `better-auth` ###### Bug Fixes - Fixed unproven credentials not being revoked during magic link and email OTP sign-in ([#10239](https://github.com/better-auth/better-auth/pull/10239)) - Fixed server-side OAuth requests to refuse redirect responses instead of following them ([#10241](https://github.com/better-auth/better-auth/pull/10241)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/a90d061de7cdbd60e796230aadf5d1082add1fe2/packages/better-auth/CHANGELOG.md) ##### `@better-auth/scim` ###### Bug Fixes - Fixed SCIM write-path operations to be properly scoped and to correctly honor the `active` attribute ([#10242](https://github.com/better-auth/better-auth/pull/10242)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/a90d061de7cdbd60e796230aadf5d1082add1fe2/packages/scim/CHANGELOG.md) ##### `@better-auth/stripe` ###### Bug Fixes - Fixed organization subscription actions (cancel, upgrade, restore, and the billing portal) that could act on the wrong organization. For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/a90d061de7cdbd60e796230aadf5d1082add1fe2/packages/stripe/CHANGELOG.md) ##### `auth` ###### Bug Fixes - Added account-level verification lockout for two-factor authentication ([#10240](https://github.com/better-auth/better-auth/pull/10240)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/a90d061de7cdbd60e796230aadf5d1082add1fe2/packages/cli/CHANGELOG.md) ##### Contributors Thanks to everyone who contributed to this release: @gustavovalverde **Full changelog:** [`v1.6.21...v1.6.22`](https://github.com/better-auth/better-auth/compare/v1.6.21...v1.6.22) ### v1.6.21 - Date: 2026-06-26 - Version: v1.6.21 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.6.21 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.6.21 - **fixed** — Rate limits are now enforced before plugin request handlers run - **fixed** — Admin permission changes and bans now take effect immediately even when session cookie cache is enabled - **fixed** — deviceAuthorization() no longer throws a ZodError when called without a schema option under Zod v4 - **fixed** — Google hosted-domain validation now applies consistently across all sign-in flows including Google One Tap - **fixed** — OAuth proxy now rejects profile callbacks that do not match an issued OAuth state, preventing session creation with stale state - **fixed** — OAuth sign-up and account linking now ignore provider profile values for fields marked input: false - **fixed** — PayPal sign-in now validates user info against the verified ID token subject - **fixed** — SIWE sign-in now rejects emails that already belong to another account, preventing one email from being attached to two accounts - **fixed** — Two-factor verification now locks out after five wrong codes for TOTP and backup codes, returning TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE - **fixed** — Username plugin now only stores displayUsername fallbacks that pass username validation during email sign-up - **fixed** — SSO provider deletion now also removes linked accounts, preventing reuse by a later provider with the same ID - **fixed** — SSO domain verification now requires DNS proof for every domain listed on a provider - **fixed** — SAML single logout now rejects IdP SLO POST URLs that use non-http(s) schemes such as javascript: or data: - **fixed** — SAML SSO now rejects responses whose audience, recipient, or destination does not match the configured Service Provider - **fixed** — Client IP resolution now prevents X-Forwarded-For spoofing in multi-hop proxy chains - **fixed** — disableMigration: true is now respected on plugin schema tables during generation and runtime migration - **fixed** — CLI now generates BETTER_AUTH_SECRET values with 32 characters instead of 16 - **fixed** — adapter.update now returns null when no matching row is found - **fixed** — Organization subscription actions (cancel, upgrade, restore, and the billing portal) no longer act on the wrong organization ##### `better-auth` ###### Bug Fixes - Fixed rate limits to be enforced before plugin request handlers run ([#10191](https://github.com/better-auth/better-auth/pull/10191)) - Fixed admin permission changes and bans to take effect immediately, even when session cookie cache is enabled ([#10187](https://github.com/better-auth/better-auth/pull/10187)) - Fixed `deviceAuthorization()` throwing a `ZodError` when called without a `schema` option under Zod v4 ([#9939](https://github.com/better-auth/better-auth/pull/9939)) - Fixed Google hosted-domain validation to apply consistently across all sign-in flows, including Google One Tap ([#10197](https://github.com/better-auth/better-auth/pull/10197)) - Fixed OAuth proxy to reject profile callbacks that do not match an issued OAuth state, preventing session creation with stale state ([#10183](https://github.com/better-auth/better-auth/pull/10183)) - Fixed OAuth sign-up and account linking to ignore provider profile values for fields marked `input: false` ([#10196](https://github.com/better-auth/better-auth/pull/10196)) - Fixed PayPal sign-in to validate user info against the verified ID token subject ([#10192](https://github.com/better-auth/better-auth/pull/10192)) - Fixed SIWE sign-in to reject emails that already belong to another account, preventing one email from being attached to two accounts ([#10228](https://github.com/better-auth/better-auth/pull/10228)) - Fixed two-factor verification to lock out after five wrong codes for TOTP and backup codes, returning `TOO_MANY_ATTEMPTS_REQUEST_NEW_CODE` ([#10210](https://github.com/better-auth/better-auth/pull/10210)) - Fixed the username plugin to only store `displayUsername` fallbacks that pass username validation during email sign-up ([#10182](https://github.com/better-auth/better-auth/pull/10182)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/414169d95a88a6e1fac41688bc7011e96feb0d2a/packages/better-auth/CHANGELOG.md) ##### `@better-auth/sso` ###### Bug Fixes - Fixed SSO provider deletion to also remove linked accounts, preventing reuse by a later provider with the same ID ([#10224](https://github.com/better-auth/better-auth/pull/10224)) - Fixed SSO domain verification to require DNS proof for every domain listed on a provider ([#10227](https://github.com/better-auth/better-auth/pull/10227)) - Fixed SAML single logout to reject IdP SLO POST URLs that use non-http(s) schemes such as `javascript:` or `data:` ([#10225](https://github.com/better-auth/better-auth/pull/10225)) - Fixed SAML SSO to reject responses whose audience, recipient, or destination does not match the configured Service Provider ([#10226](https://github.com/better-auth/better-auth/pull/10226)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/414169d95a88a6e1fac41688bc7011e96feb0d2a/packages/sso/CHANGELOG.md) ##### `@better-auth/api-key` ###### Bug Fixes - Fixed client IP resolution to prevent `X-Forwarded-For` spoofing in multi-hop proxy chains ([#10203](https://github.com/better-auth/better-auth/pull/10203)) - Refactored request IP resolution into a centralized core resolver ([#10216](https://github.com/better-auth/better-auth/pull/10216)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/414169d95a88a6e1fac41688bc7011e96feb0d2a/packages/api-key/CHANGELOG.md) ##### `auth` ###### Bug Fixes - Fixed `disableMigration: true` to be respected on plugin schema tables during generation and runtime migration ([#10198](https://github.com/better-auth/better-auth/pull/10198)) - Fixed the CLI to generate `BETTER_AUTH_SECRET` values with 32 characters instead of 16 ([#10186](https://github.com/better-auth/better-auth/pull/10186)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/414169d95a88a6e1fac41688bc7011e96feb0d2a/packages/cli/CHANGELOG.md) ##### `@better-auth/kysely-adapter` ###### Bug Fixes - Fixed `adapter _[Truncated at 4000 characters — full notes: https://github.com/better-auth/better-auth/releases/tag/v1.6.21]_ ### v1.7.0-beta.9 - Date: 2026-06-20 - Version: v1.7.0-beta.9 - Original notes: https://github.com/better-auth/better-auth/releases/tag/v1.7.0-beta.9 - Permalink: https://whatsnew.fyi/product/better-auth/releases/v1.7.0-beta.9 - Labels: Pre-release - **removed** — Restricted customIdTokenClaims, extension ID-token claims, and per-issuance idTokenClaims from overriding protected OIDC/JWT protocol claims (iss, sub, aud, exp, nonce, auth_time, acr, amr, azp) - **added** — Added support for confidential DCR clients to complete authorization-code flows without PKCE when clientRegistrationRequirePKCE: false is set - **added** — Added support for the claims.userinfo authorization request parameter, allowing clients to request specific standard claims from the UserInfo endpoint - **fixed** — Fixed the UserInfo endpoint to accept bearer tokens in application/x-www-form-urlencoded POST request bodies - **fixed** — Fixed confidential clients that opted out of PKCE to successfully request offline_access when the authorization includes both openid scope and a nonce - **fixed** — Fixed the OIDC authorization endpoint to accept form-encoded POST requests and return proper errors for unsupported request and request_uri parameters - **fixed** — Fixed the UserInfo endpoint to correctly return profile and email scope claims, and added rejection of unsupported acr_values in authorization requests - **fixed** — Fixed the token endpoint to only require redirect_uri when the original authorization request included one, and to return invalid_grant on mismatches - **fixed** — Fixed Dynamic Client Registration to preserve client key metadata across updates - **fixed** — Fixed authorization requests missing response_type to redirect errors to the client redirect URI instead of the provider error page - **fixed** — Fixed authorization code replay to correctly return invalid_grant and revoke all tokens previously issued from the replayed code - **fixed** — Fixed refresh token validation to return invalid_grant when a client attempts to use a refresh token issued to a different client ##### `@better-auth/oauth-provider` ###### ❗ Breaking Changes - Restricted `customIdTokenClaims`, extension ID-token claims, and per-issuance `idTokenClaims` from overriding protected OIDC/JWT protocol claims ([#10140](https://github.com/better-auth/better-auth/pull/10140)) > **Migration:** Remove any `iss`, `sub`, `aud`, `exp`, `nonce`, `auth_time`, `acr`, `amr`, or `azp` fields from `customIdTokenClaims`, extension ID-token claims, and per-issuance `idTokenClaims`. Use namespaced custom claims (e.g., `"https://example.com/role"`) for application-specific data instead. ###### Features - Added support for confidential DCR clients to complete authorization-code flows without PKCE when `clientRegistrationRequirePKCE: false` is set ([#10146](https://github.com/better-auth/better-auth/pull/10146)) - Added support for the `claims.userinfo` authorization request parameter, allowing clients to request specific standard claims from the UserInfo endpoint ([#10156](https://github.com/better-auth/better-auth/pull/10156)) ###### Bug Fixes - Fixed the UserInfo endpoint to accept bearer tokens in `application/x-www-form-urlencoded` POST request bodies ([#10155](https://github.com/better-auth/better-auth/pull/10155)) - Fixed confidential clients that opted out of PKCE to successfully request `offline_access` when the authorization includes both `openid` scope and a `nonce` ([#10153](https://github.com/better-auth/better-auth/pull/10153)) - Fixed the OIDC authorization endpoint to accept form-encoded POST requests and return proper errors for unsupported `request` and `request_uri` parameters ([#10151](https://github.com/better-auth/better-auth/pull/10151)) - Fixed the UserInfo endpoint to correctly return `profile` and `email` scope claims, and added rejection of unsupported `acr_values` in authorization requests ([#10152](https://github.com/better-auth/better-auth/pull/10152)) - Fixed the token endpoint to only require `redirect_uri` when the original authorization request included one, and to return `invalid_grant` on mismatches ([#10159](https://github.com/better-auth/better-auth/pull/10159)) - Fixed Dynamic Client Registration to preserve client key metadata across updates ([#10144](https://github.com/better-auth/better-auth/pull/10144)) - Fixed authorization requests missing `response_type` to redirect errors to the client redirect URI instead of the provider error page ([#10149](https://github.com/better-auth/better-auth/pull/10149)) - Fixed authorization code replay to correctly return `invalid_grant` and revoke all tokens previously issued from the replayed code ([#10150](https://github.com/better-auth/better-auth/pull/10150)) - Fixed refresh token validation to return `invalid_grant` when a client attempts to use a refresh token issued to a different client ([#10154](https://github.com/better-auth/better-auth/pull/10154)) For detailed changes, see [`CHANGELOG`](https://github.com/better-auth/better-auth/blob/4218161c53f050733d1cb67c608a1e6156af7bbd/packages/oauth-provider/CHANGELOG.md) ##### Contributors Thanks to everyone who contributed to this release: @gustavovalverde **Full changelog:** [`v1.7.0-beta.8...v1.7.0-beta.9`](https://github.com/better-auth/better-auth/compare/v1.7.0-beta.8...v1.7.0-beta.9)