diff --git a/.changeset/atomic-consume-one-primitive.md b/.changeset/atomic-consume-one-primitive.md deleted file mode 100644 index 8597d3a39f..0000000000 --- a/.changeset/atomic-consume-one-primitive.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@better-auth/core": patch -"@better-auth/drizzle-adapter": patch -"@better-auth/kysely-adapter": patch -"@better-auth/memory-adapter": patch -"@better-auth/mongo-adapter": patch -"@better-auth/prisma-adapter": patch -"@better-auth/redis-storage": patch -"better-auth": patch ---- - -Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. diff --git a/.changeset/chatty-streets-play.md b/.changeset/chatty-streets-play.md deleted file mode 100644 index 58a470e143..0000000000 --- a/.changeset/chatty-streets-play.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"better-auth": patch -"@better-auth/scim": patch ---- - -fix: cleanup sessions when admin, anonymous, or SCIM deletes a user diff --git a/.changeset/device-auth-claim-at-verify.md b/.changeset/device-auth-claim-at-verify.md deleted file mode 100644 index e6280cf5fa..0000000000 --- a/.changeset/device-auth-claim-at-verify.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -"better-auth": patch ---- - -fix(device-authorization): require verify-time ownership claim for approve/deny - -Pending device codes were not bound to the user who entered the code on the verification page until approval, leaving a window where any authenticated user could approve or deny another user's pending code by knowing the `user_code`. `GET /device` now claims the pending row for the calling session, and `POST /device/approve` and `POST /device/deny` require the calling session to match the claimed owner. Custom verification pages must be served to an authenticated session for the flow to succeed. diff --git a/.changeset/fancy-views-notice.md b/.changeset/fancy-views-notice.md deleted file mode 100644 index 0ceb08cc1a..0000000000 --- a/.changeset/fancy-views-notice.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"better-auth": patch ---- - -fix: add error code to change-email-disabled diff --git a/.changeset/fix-api-key-rate-limit-status-429.md b/.changeset/fix-api-key-rate-limit-status-429.md deleted file mode 100644 index 9219212e09..0000000000 --- a/.changeset/fix-api-key-rate-limit-status-429.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@better-auth/api-key": patch ---- - -API key requests that exceed the configured rate limit now return HTTP 429 (Too Many Requests) instead of HTTP 401 (Unauthorized), so clients can distinguish throttling from authentication failures. diff --git a/.changeset/fix-magic-link-atomic-consume.md b/.changeset/fix-magic-link-atomic-consume.md deleted file mode 100644 index e1ff47c4da..0000000000 --- a/.changeset/fix-magic-link-atomic-consume.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"better-auth": patch ---- - -Fix race condition in the `magic-link` plugin's verify handler that allowed two concurrent requests to mint two sessions from the same single-use token. The handler now consumes the verification row atomically via `internalAdapter.consumeVerificationValue`, so a given magic link mints at most one session regardless of concurrency. The `allowedAttempts` option is retained for backward compatibility but no longer multiplies successful redemptions; tokens are single-use. The second-redeem error code changes from `ATTEMPTS_EXCEEDED` to `INVALID_TOKEN` (the token no longer exists after consumption). diff --git a/.changeset/fix-oauth-authcode-atomic-consume.md b/.changeset/fix-oauth-authcode-atomic-consume.md deleted file mode 100644 index 5fa6b94a66..0000000000 --- a/.changeset/fix-oauth-authcode-atomic-consume.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -"@better-auth/oauth-provider": patch -"better-auth": patch ---- - -Fix race condition in the OAuth authorization-code grant: two concurrent token-exchange requests sharing the same `code` could both pass the find step before either delete completed and each mint an independent access/refresh/id token set. The `authorization_code` handler in `@better-auth/oauth-provider`, plus the legacy `oidc-provider` and `mcp` plugins in `better-auth`, now consume the verification row atomically via `internalAdapter.consumeVerificationValue`. The first caller mints tokens; concurrent racers receive `invalid_grant` (RFC 6749 §5.2). Malformed-verification-value branches in `@better-auth/oauth-provider` previously returned a project-specific `invalid_verification` code; those are now `invalid_grant` so spec-compliant clients can branch on the standard code. diff --git a/.changeset/fix-oauth-refresh-token-cas.md b/.changeset/fix-oauth-refresh-token-cas.md deleted file mode 100644 index 083f3d0dc9..0000000000 --- a/.changeset/fix-oauth-refresh-token-cas.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"@better-auth/oauth-provider": patch -"@better-auth/memory-adapter": patch ---- - -Fix race condition in the OAuth refresh-token grant rotation: two concurrent requests presenting the same refresh token both passed the `revoked` check before either revocation write completed, so each minted a fresh refresh token (forked family). `createRefreshToken` now performs an atomic compare-and-swap on the parent row (`UPDATE ... WHERE id = ? AND revoked IS NULL`) before issuing the new token, and `revokeRefreshToken` uses the same CAS. The loser of a concurrent rotation receives `invalid_grant`; the parent row's `revoked` flag is set, so any subsequent replay trips the existing family-invalidation guard. The `oauthRefreshToken.token` column gains a `unique` constraint for parity with `oauthAccessToken.token`. - -`@better-auth/memory-adapter` now treats `undefined` and `null` as equivalent under an `eq null` `where` clause, mirroring SQL `IS NULL` and Mongo's missing-or-null semantics. The adapter factory's `transformInput` skips writing optional fields whose value is `undefined`, so a CAS predicate like `WHERE revoked IS NULL` against a freshly created row (where the field is absent) used to fail-closed on every call. Without this change the refresh-token rotation above is broken for any deployment using the in-memory adapter. - -**Migration note:** the better-auth migration generator only emits `UNIQUE` for newly-created columns. Existing installs will not get the new `oauthRefreshToken.token` unique constraint via `migrate`/`generate`; add it manually if your operational tooling relies on it (e.g. `CREATE UNIQUE INDEX oauth_refresh_token_token_uniq ON "oauthRefreshToken" (token);`). The CAS fix above does not depend on the database-level constraint to be correct; the constraint is defense-in-depth so collisions from buggy custom `generateRefreshToken` callbacks fail loudly. - -Strict family invalidation on contested rotations (per RFC 9700 §4.14) is deferred to a follow-up minor; closing it cleanly requires opt-in transactional rotation in the adapter contract so the family-delete cannot interleave with the winner's in-flight access-token insert. diff --git a/.changeset/fix-oauth2-implicit-link-require-local-emailverified.md b/.changeset/fix-oauth2-implicit-link-require-local-emailverified.md deleted file mode 100644 index a345f781b8..0000000000 --- a/.changeset/fix-oauth2-implicit-link-require-local-emailverified.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -"better-auth": patch -"@better-auth/core": patch ---- - -`handleOAuthUserInfo` (used by every social provider, generic-oauth, oauth-proxy, SSO OIDC and SAML, and idToken sign-in) implicitly linked a returning OAuth identity into a local user row whenever the IdP's `email_verified` claim was true or the provider was trusted. The local row's own `emailVerified` flag was read only to flip it after linking, never as a precondition. `POST /sign-up/email` creates rows with `emailVerified: false` for any caller, so an attacker who pre-registered a victim's email at the application could wait for the legitimate user's first OAuth sign-in: the IdP's verified claim was treated as ownership proof, and the victim's IdP identity was linked into the attacker-owned row. - -The implicit-link gate now requires `dbUser.user.emailVerified === true` in addition to the provider trust check by default. A new `account.accountLinking.requireLocalEmailVerified` option (default `true`) is the public surface for this gate. Apps whose users sign up via OAuth without verifying their email locally can opt back into the legacy behavior with `account: { accountLinking: { requireLocalEmailVerified: false } }`; understand the takeover risk before doing so. The option is `@deprecated`; a FIXME at each gate site points at the next-minor follow-up on `next` that drops the option and makes the gate unconditional. - -The `one-tap` plugin honored its own copy of the gate and was updated identically: `requireLocalEmailVerified` and `accountLinking.disableImplicitLinking` both apply on `/one-tap/callback`. The `email_verified` claim from the Google ID token is now normalized via `toBoolean` so a string `"false"` is treated as falsy. - -Test fixtures across `admin`, `oidc-provider`, `mcp`, `generic-oauth`, `last-login-method`, and `oauth-provider` suites now mark users `emailVerified: true` via a `databaseHooks.user.create.before` hook (or the `disableTestUser` opt-in on the oauth-provider RP) so the suites continue to exercise their role/flow logic rather than the new gate. diff --git a/.changeset/fix-org-role-statement-types.md b/.changeset/fix-org-role-statement-types.md deleted file mode 100644 index b384ccb647..0000000000 --- a/.changeset/fix-org-role-statement-types.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"better-auth": patch ---- - -Preserve exact access-control role statement types so predefined organization roles expose only their configured permissions in TypeScript. diff --git a/.changeset/fix-organization-invitation-email-verified-gate.md b/.changeset/fix-organization-invitation-email-verified-gate.md deleted file mode 100644 index 2b466d63f1..0000000000 --- a/.changeset/fix-organization-invitation-email-verified-gate.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"better-auth": patch ---- - -The organization plugin's invitation recipient endpoints (`acceptInvitation`, `rejectInvitation`, `getInvitation`, `listUserInvitations`) treated `invitation.email.toLowerCase() === session.user.email.toLowerCase()` as proof that the calling user owned the invited address. A session-authenticated user whose email matched but was never verified passed the gate, so anyone who could pre-register an unverified account at a victim's email could accept invitations addressed to that email. The `requireEmailVerificationOnInvitation` opt-in option closed the gap only when explicitly enabled and did not protect `getInvitation` or `listUserInvitations` at all. - -The gate is now applied on all four recipient endpoints and the `requireEmailVerificationOnInvitation` option default flips from `false` to `true` so existing apps are secure by default. Apps that intentionally accept invitations from unverified accounts can keep the legacy permissive behavior with `organization({ requireEmailVerificationOnInvitation: false })`, but they should understand the takeover risk before doing so. Server-side calls to `listUserInvitations` with `ctx.query.email` and no session continue to bypass the gate (the caller is trusted). - -The option is `@deprecated`. The next-minor release on `next` removes it entirely and makes the gate unconditional. diff --git a/.changeset/fix-scim-provider-ownership-default-on.md b/.changeset/fix-scim-provider-ownership-default-on.md deleted file mode 100644 index 7f72ca16a1..0000000000 --- a/.changeset/fix-scim-provider-ownership-default-on.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"@better-auth/scim": patch ---- - -`POST /scim/generate-token` accepted a `providerId` that collided with a built-in `account.providerId` value (`credential`, `email-otp`, `magic-link`, `phone-number`, `anonymous`, `siwe`, or any configured social provider key), so a SCIM caller could mint a token that authenticated against accounts it never provisioned. - -`generateSCIMToken` now rejects `providerId` values that collide with the built-in account provider list, returning `BAD_REQUEST` at issuance. The configured-social-provider check reads from `options.socialProviders` rather than the resolved provider list so that providers disabled with `enabled: false` are still rejected: their account rows can persist from when the provider was enabled. - -`providerOwnership.enabled` stays default `false` on this patch release so existing SQL deployments do not need a schema migration mid-upgrade. The follow-up on `next` flips the default to `true` and ships the corresponding `scimProvider.userId` schema column so non-organization SCIM tokens are owner-locked by default. Operators who need owner-locking immediately can opt in today with `scim({ providerOwnership: { enabled: true } })` and add the `userId` column manually. diff --git a/.changeset/fix-sso-register-role-check.md b/.changeset/fix-sso-register-role-check.md deleted file mode 100644 index b0a1bbf657..0000000000 --- a/.changeset/fix-sso-register-role-check.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -"@better-auth/sso": patch ---- - -fix(sso): require org admin role to register SSO providers - -`POST /sso/register` previously allowed any organization member to register an -SSO provider for the organization when `organizationId` was supplied, only -checking membership and not role. This brings it in line with the other -provider endpoints (`get`/`update`/`delete`), which go through -`checkProviderAccess` → `isOrgAdmin` and restrict access to `owner` or `admin` -roles. - -Closes #9133. diff --git a/.changeset/fix-sso-skip-discovery-ssrf.md b/.changeset/fix-sso-skip-discovery-ssrf.md deleted file mode 100644 index 79e9d9b014..0000000000 --- a/.changeset/fix-sso-skip-discovery-ssrf.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -"@better-auth/sso": patch ---- - -fix(sso): validate user-supplied OIDC endpoint URLs at provider registration and update - -When `skipDiscovery: true` was passed to `POST /sso/register`, or any -`oidcConfig` URL was passed to `POST /sso/update-provider`, the supplied -`authorizationEndpoint`, `tokenEndpoint`, `userInfoEndpoint`, `jwksEndpoint`, -and `discoveryEndpoint` values were persisted on the provider row without -origin validation, then fetched server-side at OIDC callback time. An -authenticated user could register or update an SSO provider with internal -URLs (RFC 1918, link-local, cloud-metadata FQDNs like `169.254.169.254`, -loopback) and use the callback handler to coerce the server into making -requests to those hosts. - -Both endpoints now run user-supplied OIDC URLs through a layered gate: - -1. URL parsing + `http(s)` scheme requirement -2. `isPublicRoutableHost` from `@better-auth/core/utils/host` (rejects - loopback, RFC 1918, link-local, ULA, cloud-metadata FQDNs, multicast, - broadcast, and reserved ranges per RFC 6890) -3. `trustedOrigins` allowlist as the documented escape hatch for customers - running internal IdPs on private networks - -A request that fails the gate is rejected with `BAD_REQUEST` and the new -`discovery_private_host` error code (or `discovery_invalid_url` for -malformed URLs / non-`http(s)` schemes). diff --git a/.changeset/large-chairs-shout.md b/.changeset/large-chairs-shout.md deleted file mode 100644 index 388e2f8146..0000000000 --- a/.changeset/large-chairs-shout.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"better-auth": patch ---- - -anonymous plugin now correctly calls onLinkAccount when email verification triggers auto sign-in diff --git a/.changeset/legacy-oauth-refresh-client-auth.md b/.changeset/legacy-oauth-refresh-client-auth.md deleted file mode 100644 index 237f17d36c..0000000000 --- a/.changeset/legacy-oauth-refresh-client-auth.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -"better-auth": patch ---- - -fix(oidc-provider, mcp): authenticate confidential clients on refresh_token grant and harden secret comparison - -Refresh-token grants on the legacy `oidc-provider` and `mcp` plugins now require the registered `client_secret` from confidential clients, matching the `authorization_code` path. Public clients (where `code_verifier` substitutes for the secret on the auth-code grant) continue to skip secret validation. Secret comparisons across both plugins now use constant-time equality. The `/mcp/token` endpoint no longer emits a wildcard CORS `Access-Control-Allow-Origin: *` header. - -These plugins are deprecated in favor of `@better-auth/oauth-provider`, which is unaffected. New deployments should adopt the replacement; this patch keeps existing deployments protected while migrating. diff --git a/.changeset/lemon-dryers-show.md b/.changeset/lemon-dryers-show.md deleted file mode 100644 index f4da486d37..0000000000 --- a/.changeset/lemon-dryers-show.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@better-auth/core": patch ---- - -fix: invalid instrumentation import list diff --git a/.changeset/oidc-pkce-and-alg-none-hardening.md b/.changeset/oidc-pkce-and-alg-none-hardening.md deleted file mode 100644 index 8173eff8de..0000000000 --- a/.changeset/oidc-pkce-and-alg-none-hardening.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -"better-auth": patch ---- - -fix(oidc-provider, mcp): drop `"none"` from advertised signing algorithms, default `allowPlainCodeChallengeMethod` to `false`, and reject missing PKCE method - -The legacy `oidc-provider` and `mcp` plugins now follow OAuth 2.1 (RFC 9700) on three protocol gates: - -- `id_token_signing_alg_values_supported` (oidc-provider, mcp) and `resource_signing_alg_values_supported` (mcp) no longer include `"none"`. Relying parties that negotiate from this list will no longer be steered toward unsigned tokens. -- `allowPlainCodeChallengeMethod` defaults to `false`. Callers who need `plain` PKCE must opt in explicitly. -- Under the secure default the authorize endpoint no longer silently rewrites a missing `code_challenge_method` to `"plain"` before the allowlist check. A request that provides `code_challenge` without `code_challenge_method` is now rejected with `invalid_request`; the inverse case (`code_challenge_method` without `code_challenge`) is also rejected so no inconsistent PKCE state is persisted on the authorization code record. - -Non-breaking for callers who never relied on `"none"` advertisement or the plain default. Callers who explicitly set `allowPlainCodeChallengeMethod: true` keep `plain` on the allowlist **and** retain the legacy "missing method defaults to plain" behavior for backward compatibility, so existing integrations that opted into plain PKCE continue to work. The next-minor on `next` will drop both the `plain` allowlist entry and this fallback; until then, the option is the single explicit knob for legacy behavior. Migrate to `@better-auth/oauth-provider` for the canonical, spec-aligned implementation. diff --git a/.changeset/widen-ipv6-subnet-type.md b/.changeset/widen-ipv6-subnet-type.md deleted file mode 100644 index 0ac4e9ca8c..0000000000 --- a/.changeset/widen-ipv6-subnet-type.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@better-auth/core": patch ---- - -Widen `advanced.ipAddress.ipv6Subnet` to accept any integer prefix length from 0 to 128, not just `32 | 48 | 64 | 128`. The runtime mask code already handled any value in range; the type union was unnecessarily narrow and rejected valid prefix lengths like `/56` (residential ISP allocations) and `/40` (common cloud allocations). Existing values continue to work unchanged. diff --git a/packages/api-key/CHANGELOG.md b/packages/api-key/CHANGELOG.md index 2198ae6030..c81f1fb9b7 100644 --- a/packages/api-key/CHANGELOG.md +++ b/packages/api-key/CHANGELOG.md @@ -1,5 +1,15 @@ # @better-auth/api-key +## 1.6.11 + +### Patch Changes + +- [#9505](https://github.com/better-auth/better-auth/pull/9505) [`b039985`](https://github.com/better-auth/better-auth/commit/b03998586af6c47b2c9b6cdd556d36416bc71711) Thanks [@Kvizas](https://github.com/Kvizas)! - API key requests that exceed the configured rate limit now return HTTP 429 (Too Many Requests) instead of HTTP 401 (Unauthorized), so clients can distinguish throttling from authentication failures. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/api-key/package.json b/packages/api-key/package.json index 2c31a3e79f..37d837ea65 100644 --- a/packages/api-key/package.json +++ b/packages/api-key/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/api-key", - "version": "1.6.10", + "version": "1.6.11", "description": "API Key plugin for Better Auth.", "type": "module", "license": "MIT", diff --git a/packages/better-auth/CHANGELOG.md b/packages/better-auth/CHANGELOG.md index ac0687fb6e..9c471c87e7 100644 --- a/packages/better-auth/CHANGELOG.md +++ b/packages/better-auth/CHANGELOG.md @@ -1,5 +1,65 @@ # better-auth +## 1.6.11 + +### Patch Changes + +- [#9568](https://github.com/better-auth/better-auth/pull/9568) [`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. + +- [#9162](https://github.com/better-auth/better-auth/pull/9162) [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70) Thanks [@ping-maxwell](https://github.com/ping-maxwell)! - fix: cleanup sessions when admin, anonymous, or SCIM deletes a user + +- [#9573](https://github.com/better-auth/better-auth/pull/9573) [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - fix(device-authorization): require verify-time ownership claim for approve/deny + + Pending device codes were not bound to the user who entered the code on the verification page until approval, leaving a window where any authenticated user could approve or deny another user's pending code by knowing the `user_code`. `GET /device` now claims the pending row for the calling session, and `POST /device/approve` and `POST /device/deny` require the calling session to match the claimed owner. Custom verification pages must be served to an authenticated session for the flow to succeed. + +- [#8948](https://github.com/better-auth/better-auth/pull/8948) [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83) Thanks [@ping-maxwell](https://github.com/ping-maxwell)! - fix: add error code to change-email-disabled + +- [#9572](https://github.com/better-auth/better-auth/pull/9572) [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Fix race condition in the `magic-link` plugin's verify handler that allowed two concurrent requests to mint two sessions from the same single-use token. The handler now consumes the verification row atomically via `internalAdapter.consumeVerificationValue`, so a given magic link mints at most one session regardless of concurrency. The `allowedAttempts` option is retained for backward compatibility but no longer multiplies successful redemptions; tokens are single-use. The second-redeem error code changes from `ATTEMPTS_EXCEEDED` to `INVALID_TOKEN` (the token no longer exists after consumption). + +- [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Fix race condition in the OAuth authorization-code grant: two concurrent token-exchange requests sharing the same `code` could both pass the find step before either delete completed and each mint an independent access/refresh/id token set. The `authorization_code` handler in `@better-auth/oauth-provider`, plus the legacy `oidc-provider` and `mcp` plugins in `better-auth`, now consume the verification row atomically via `internalAdapter.consumeVerificationValue`. The first caller mints tokens; concurrent racers receive `invalid_grant` (RFC 6749 §5.2). Malformed-verification-value branches in `@better-auth/oauth-provider` previously returned a project-specific `invalid_verification` code; those are now `invalid_grant` so spec-compliant clients can branch on the standard code. + +- [#9578](https://github.com/better-auth/better-auth/pull/9578) [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - `handleOAuthUserInfo` (used by every social provider, generic-oauth, oauth-proxy, SSO OIDC and SAML, and idToken sign-in) implicitly linked a returning OAuth identity into a local user row whenever the IdP's `email_verified` claim was true or the provider was trusted. The local row's own `emailVerified` flag was read only to flip it after linking, never as a precondition. `POST /sign-up/email` creates rows with `emailVerified: false` for any caller, so an attacker who pre-registered a victim's email at the application could wait for the legitimate user's first OAuth sign-in: the IdP's verified claim was treated as ownership proof, and the victim's IdP identity was linked into the attacker-owned row. + + The implicit-link gate now requires `dbUser.user.emailVerified === true` in addition to the provider trust check by default. A new `account.accountLinking.requireLocalEmailVerified` option (default `true`) is the public surface for this gate. Apps whose users sign up via OAuth without verifying their email locally can opt back into the legacy behavior with `account: { accountLinking: { requireLocalEmailVerified: false } }`; understand the takeover risk before doing so. The option is `@deprecated`; a FIXME at each gate site points at the next-minor follow-up on `next` that drops the option and makes the gate unconditional. + + The `one-tap` plugin honored its own copy of the gate and was updated identically: `requireLocalEmailVerified` and `accountLinking.disableImplicitLinking` both apply on `/one-tap/callback`. The `email_verified` claim from the Google ID token is now normalized via `toBoolean` so a string `"false"` is treated as falsy. + + Test fixtures across `admin`, `oidc-provider`, `mcp`, `generic-oauth`, `last-login-method`, and `oauth-provider` suites now mark users `emailVerified: true` via a `databaseHooks.user.create.before` hook (or the `disableTestUser` opt-in on the oauth-provider RP) so the suites continue to exercise their role/flow logic rather than the new gate. + +- [#9507](https://github.com/better-auth/better-auth/pull/9507) [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816) Thanks [@GautamBytes](https://github.com/GautamBytes)! - Preserve exact access-control role statement types so predefined organization roles expose only their configured permissions in TypeScript. + +- [#9577](https://github.com/better-auth/better-auth/pull/9577) [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - The organization plugin's invitation recipient endpoints (`acceptInvitation`, `rejectInvitation`, `getInvitation`, `listUserInvitations`) treated `invitation.email.toLowerCase() === session.user.email.toLowerCase()` as proof that the calling user owned the invited address. A session-authenticated user whose email matched but was never verified passed the gate, so anyone who could pre-register an unverified account at a victim's email could accept invitations addressed to that email. The `requireEmailVerificationOnInvitation` opt-in option closed the gap only when explicitly enabled and did not protect `getInvitation` or `listUserInvitations` at all. + + The gate is now applied on all four recipient endpoints and the `requireEmailVerificationOnInvitation` option default flips from `false` to `true` so existing apps are secure by default. Apps that intentionally accept invitations from unverified accounts can keep the legacy permissive behavior with `organization({ requireEmailVerificationOnInvitation: false })`, but they should understand the takeover risk before doing so. Server-side calls to `listUserInvitations` with `ctx.query.email` and no session continue to bypass the gate (the caller is trusted). + + The option is `@deprecated`. The next-minor release on `next` removes it entirely and makes the gate unconditional. + +- [#9548](https://github.com/better-auth/better-auth/pull/9548) [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d) Thanks [@dipan-ck](https://github.com/dipan-ck)! - anonymous plugin now correctly calls onLinkAccount when email verification triggers auto sign-in + +- [#9576](https://github.com/better-auth/better-auth/pull/9576) [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - fix(oidc-provider, mcp): authenticate confidential clients on refresh_token grant and harden secret comparison + + Refresh-token grants on the legacy `oidc-provider` and `mcp` plugins now require the registered `client_secret` from confidential clients, matching the `authorization_code` path. Public clients (where `code_verifier` substitutes for the secret on the auth-code grant) continue to skip secret validation. Secret comparisons across both plugins now use constant-time equality. The `/mcp/token` endpoint no longer emits a wildcard CORS `Access-Control-Allow-Origin: *` header. + + These plugins are deprecated in favor of `@better-auth/oauth-provider`, which is unaffected. New deployments should adopt the replacement; this patch keeps existing deployments protected while migrating. + +- [#9575](https://github.com/better-auth/better-auth/pull/9575) [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - fix(oidc-provider, mcp): drop `"none"` from advertised signing algorithms, default `allowPlainCodeChallengeMethod` to `false`, and reject missing PKCE method + + The legacy `oidc-provider` and `mcp` plugins now follow OAuth 2.1 (RFC 9700) on three protocol gates: + - `id_token_signing_alg_values_supported` (oidc-provider, mcp) and `resource_signing_alg_values_supported` (mcp) no longer include `"none"`. Relying parties that negotiate from this list will no longer be steered toward unsigned tokens. + - `allowPlainCodeChallengeMethod` defaults to `false`. Callers who need `plain` PKCE must opt in explicitly. + - Under the secure default the authorize endpoint no longer silently rewrites a missing `code_challenge_method` to `"plain"` before the allowlist check. A request that provides `code_challenge` without `code_challenge_method` is now rejected with `invalid_request`; the inverse case (`code_challenge_method` without `code_challenge`) is also rejected so no inconsistent PKCE state is persisted on the authorization code record. + + Non-breaking for callers who never relied on `"none"` advertisement or the plain default. Callers who explicitly set `allowPlainCodeChallengeMethod: true` keep `plain` on the allowlist **and** retain the legacy "missing method defaults to plain" behavior for backward compatibility, so existing integrations that opted into plain PKCE continue to work. The next-minor on `next` will drop both the `plain` allowlist entry and this fallback; until then, the option is the single explicit knob for legacy behavior. Migrate to `@better-auth/oauth-provider` for the canonical, spec-aligned implementation. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`c6918ec`](https://github.com/better-auth/better-auth/commit/c6918ecc9e3a75892169415d7f6c95b591b6a52d), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - @better-auth/drizzle-adapter@1.6.11 + - @better-auth/kysely-adapter@1.6.11 + - @better-auth/memory-adapter@1.6.11 + - @better-auth/mongo-adapter@1.6.11 + - @better-auth/prisma-adapter@1.6.11 + - @better-auth/telemetry@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/better-auth/package.json b/packages/better-auth/package.json index 1cc90c7822..8583618811 100644 --- a/packages/better-auth/package.json +++ b/packages/better-auth/package.json @@ -1,6 +1,6 @@ { "name": "better-auth", - "version": "1.6.10", + "version": "1.6.11", "description": "The most comprehensive authentication framework for TypeScript.", "type": "module", "license": "MIT", diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md index 77cf29972e..927543a81f 100644 --- a/packages/cli/CHANGELOG.md +++ b/packages/cli/CHANGELOG.md @@ -1,5 +1,14 @@ # auth +## 1.6.11 + +### Patch Changes + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + - @better-auth/telemetry@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/cli/package.json b/packages/cli/package.json index c608ed85b0..539192bcb3 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "auth", - "version": "1.6.10", + "version": "1.6.11", "description": "The CLI for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 42cce81338..5f56100736 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,23 @@ # @better-auth/core +## 1.6.11 + +### Patch Changes + +- [#9568](https://github.com/better-auth/better-auth/pull/9568) [`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. + +- [#9578](https://github.com/better-auth/better-auth/pull/9578) [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - `handleOAuthUserInfo` (used by every social provider, generic-oauth, oauth-proxy, SSO OIDC and SAML, and idToken sign-in) implicitly linked a returning OAuth identity into a local user row whenever the IdP's `email_verified` claim was true or the provider was trusted. The local row's own `emailVerified` flag was read only to flip it after linking, never as a precondition. `POST /sign-up/email` creates rows with `emailVerified: false` for any caller, so an attacker who pre-registered a victim's email at the application could wait for the legitimate user's first OAuth sign-in: the IdP's verified claim was treated as ownership proof, and the victim's IdP identity was linked into the attacker-owned row. + + The implicit-link gate now requires `dbUser.user.emailVerified === true` in addition to the provider trust check by default. A new `account.accountLinking.requireLocalEmailVerified` option (default `true`) is the public surface for this gate. Apps whose users sign up via OAuth without verifying their email locally can opt back into the legacy behavior with `account: { accountLinking: { requireLocalEmailVerified: false } }`; understand the takeover risk before doing so. The option is `@deprecated`; a FIXME at each gate site points at the next-minor follow-up on `next` that drops the option and makes the gate unconditional. + + The `one-tap` plugin honored its own copy of the gate and was updated identically: `requireLocalEmailVerified` and `accountLinking.disableImplicitLinking` both apply on `/one-tap/callback`. The `email_verified` claim from the Google ID token is now normalized via `toBoolean` so a string `"false"` is treated as falsy. + + Test fixtures across `admin`, `oidc-provider`, `mcp`, `generic-oauth`, `last-login-method`, and `oauth-provider` suites now mark users `emailVerified: true` via a `databaseHooks.user.create.before` hook (or the `disableTestUser` opt-in on the oauth-provider RP) so the suites continue to exercise their role/flow logic rather than the new gate. + +- [#9582](https://github.com/better-auth/better-auth/pull/9582) [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10) Thanks [@ping-maxwell](https://github.com/ping-maxwell)! - fix: invalid instrumentation import list + +- [#9545](https://github.com/better-auth/better-auth/pull/9545) [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Widen `advanced.ipAddress.ipv6Subnet` to accept any integer prefix length from 0 to 128, not just `32 | 48 | 64 | 128`. The runtime mask code already handled any value in range; the type union was unnecessarily narrow and rejected valid prefix lengths like `/56` (residential ISP allocations) and `/40` (common cloud allocations). Existing values continue to work unchanged. + ## 1.6.10 ### Patch Changes diff --git a/packages/core/package.json b/packages/core/package.json index 999b717242..b430a13634 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/core", - "version": "1.6.10", + "version": "1.6.11", "description": "The most comprehensive authentication framework for TypeScript.", "type": "module", "license": "MIT", diff --git a/packages/drizzle-adapter/CHANGELOG.md b/packages/drizzle-adapter/CHANGELOG.md index 79d4b301ee..50a7ab7f4c 100644 --- a/packages/drizzle-adapter/CHANGELOG.md +++ b/packages/drizzle-adapter/CHANGELOG.md @@ -1,5 +1,14 @@ # @better-auth/drizzle-adapter +## 1.6.11 + +### Patch Changes + +- [#9568](https://github.com/better-auth/better-auth/pull/9568) [`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/drizzle-adapter/package.json b/packages/drizzle-adapter/package.json index 7b051181f0..710eb5a4ea 100644 --- a/packages/drizzle-adapter/package.json +++ b/packages/drizzle-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/drizzle-adapter", - "version": "1.6.10", + "version": "1.6.11", "description": "Drizzle adapter for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/electron/CHANGELOG.md b/packages/electron/CHANGELOG.md index 3c2eb47509..4d47a4a128 100644 --- a/packages/electron/CHANGELOG.md +++ b/packages/electron/CHANGELOG.md @@ -1,5 +1,13 @@ # @better-auth/electron +## 1.6.11 + +### Patch Changes + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/electron/package.json b/packages/electron/package.json index 603bcfba54..fb97c7d5fa 100644 --- a/packages/electron/package.json +++ b/packages/electron/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/electron", - "version": "1.6.10", + "version": "1.6.11", "description": "Better Auth integration for Electron applications.", "type": "module", "license": "MIT", diff --git a/packages/expo/CHANGELOG.md b/packages/expo/CHANGELOG.md index 4b090a44f9..7bf79777a5 100644 --- a/packages/expo/CHANGELOG.md +++ b/packages/expo/CHANGELOG.md @@ -1,5 +1,13 @@ # @better-auth/expo +## 1.6.11 + +### Patch Changes + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/expo/package.json b/packages/expo/package.json index 2955445a04..82708f0c7b 100644 --- a/packages/expo/package.json +++ b/packages/expo/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/expo", - "version": "1.6.10", + "version": "1.6.11", "description": "Better Auth integration for Expo and React Native applications.", "type": "module", "license": "MIT", diff --git a/packages/i18n/CHANGELOG.md b/packages/i18n/CHANGELOG.md index bb525be4b5..8ef826d6ed 100644 --- a/packages/i18n/CHANGELOG.md +++ b/packages/i18n/CHANGELOG.md @@ -1,5 +1,13 @@ # @better-auth/i18n +## 1.6.11 + +### Patch Changes + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/i18n/package.json b/packages/i18n/package.json index 0b18db280d..0b34f6e4b8 100644 --- a/packages/i18n/package.json +++ b/packages/i18n/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/i18n", - "version": "1.6.10", + "version": "1.6.11", "description": "i18n plugin for Better Auth - translate error messages", "type": "module", "license": "MIT", diff --git a/packages/kysely-adapter/CHANGELOG.md b/packages/kysely-adapter/CHANGELOG.md index 3ce551ac15..6db7cfd48e 100644 --- a/packages/kysely-adapter/CHANGELOG.md +++ b/packages/kysely-adapter/CHANGELOG.md @@ -1,5 +1,14 @@ # @better-auth/kysely-adapter +## 1.6.11 + +### Patch Changes + +- [#9568](https://github.com/better-auth/better-auth/pull/9568) [`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/kysely-adapter/package.json b/packages/kysely-adapter/package.json index 17eb301355..ab12a15585 100644 --- a/packages/kysely-adapter/package.json +++ b/packages/kysely-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/kysely-adapter", - "version": "1.6.10", + "version": "1.6.11", "description": "Kysely adapter for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/memory-adapter/CHANGELOG.md b/packages/memory-adapter/CHANGELOG.md index 80ba1fffba..ac9dfbbcc1 100644 --- a/packages/memory-adapter/CHANGELOG.md +++ b/packages/memory-adapter/CHANGELOG.md @@ -1,5 +1,22 @@ # @better-auth/memory-adapter +## 1.6.11 + +### Patch Changes + +- [#9568](https://github.com/better-auth/better-auth/pull/9568) [`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. + +- [`c6918ec`](https://github.com/better-auth/better-auth/commit/c6918ecc9e3a75892169415d7f6c95b591b6a52d) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Fix race condition in the OAuth refresh-token grant rotation: two concurrent requests presenting the same refresh token both passed the `revoked` check before either revocation write completed, so each minted a fresh refresh token (forked family). `createRefreshToken` now performs an atomic compare-and-swap on the parent row (`UPDATE ... WHERE id = ? AND revoked IS NULL`) before issuing the new token, and `revokeRefreshToken` uses the same CAS. The loser of a concurrent rotation receives `invalid_grant`; the parent row's `revoked` flag is set, so any subsequent replay trips the existing family-invalidation guard. The `oauthRefreshToken.token` column gains a `unique` constraint for parity with `oauthAccessToken.token`. + + `@better-auth/memory-adapter` now treats `undefined` and `null` as equivalent under an `eq null` `where` clause, mirroring SQL `IS NULL` and Mongo's missing-or-null semantics. The adapter factory's `transformInput` skips writing optional fields whose value is `undefined`, so a CAS predicate like `WHERE revoked IS NULL` against a freshly created row (where the field is absent) used to fail-closed on every call. Without this change the refresh-token rotation above is broken for any deployment using the in-memory adapter. + + **Migration note:** the better-auth migration generator only emits `UNIQUE` for newly-created columns. Existing installs will not get the new `oauthRefreshToken.token` unique constraint via `migrate`/`generate`; add it manually if your operational tooling relies on it (e.g. `CREATE UNIQUE INDEX oauth_refresh_token_token_uniq ON "oauthRefreshToken" (token);`). The CAS fix above does not depend on the database-level constraint to be correct; the constraint is defense-in-depth so collisions from buggy custom `generateRefreshToken` callbacks fail loudly. + + Strict family invalidation on contested rotations (per RFC 9700 §4.14) is deferred to a follow-up minor; closing it cleanly requires opt-in transactional rotation in the adapter contract so the family-delete cannot interleave with the winner's in-flight access-token insert. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/memory-adapter/package.json b/packages/memory-adapter/package.json index a90b7d29db..1a60effae5 100644 --- a/packages/memory-adapter/package.json +++ b/packages/memory-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/memory-adapter", - "version": "1.6.10", + "version": "1.6.11", "description": "Memory adapter for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/mongo-adapter/CHANGELOG.md b/packages/mongo-adapter/CHANGELOG.md index b7636a6598..df92aa01d8 100644 --- a/packages/mongo-adapter/CHANGELOG.md +++ b/packages/mongo-adapter/CHANGELOG.md @@ -1,5 +1,14 @@ # @better-auth/mongo-adapter +## 1.6.11 + +### Patch Changes + +- [#9568](https://github.com/better-auth/better-auth/pull/9568) [`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/mongo-adapter/package.json b/packages/mongo-adapter/package.json index c9bfa025bd..495b1ce6cb 100644 --- a/packages/mongo-adapter/package.json +++ b/packages/mongo-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/mongo-adapter", - "version": "1.6.10", + "version": "1.6.11", "description": "Mongo adapter for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/oauth-provider/CHANGELOG.md b/packages/oauth-provider/CHANGELOG.md index ad5817b191..fc7ccc85d4 100644 --- a/packages/oauth-provider/CHANGELOG.md +++ b/packages/oauth-provider/CHANGELOG.md @@ -1,5 +1,23 @@ # @better-auth/oauth-provider +## 1.6.11 + +### Patch Changes + +- [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Fix race condition in the OAuth authorization-code grant: two concurrent token-exchange requests sharing the same `code` could both pass the find step before either delete completed and each mint an independent access/refresh/id token set. The `authorization_code` handler in `@better-auth/oauth-provider`, plus the legacy `oidc-provider` and `mcp` plugins in `better-auth`, now consume the verification row atomically via `internalAdapter.consumeVerificationValue`. The first caller mints tokens; concurrent racers receive `invalid_grant` (RFC 6749 §5.2). Malformed-verification-value branches in `@better-auth/oauth-provider` previously returned a project-specific `invalid_verification` code; those are now `invalid_grant` so spec-compliant clients can branch on the standard code. + +- [`c6918ec`](https://github.com/better-auth/better-auth/commit/c6918ecc9e3a75892169415d7f6c95b591b6a52d) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Fix race condition in the OAuth refresh-token grant rotation: two concurrent requests presenting the same refresh token both passed the `revoked` check before either revocation write completed, so each minted a fresh refresh token (forked family). `createRefreshToken` now performs an atomic compare-and-swap on the parent row (`UPDATE ... WHERE id = ? AND revoked IS NULL`) before issuing the new token, and `revokeRefreshToken` uses the same CAS. The loser of a concurrent rotation receives `invalid_grant`; the parent row's `revoked` flag is set, so any subsequent replay trips the existing family-invalidation guard. The `oauthRefreshToken.token` column gains a `unique` constraint for parity with `oauthAccessToken.token`. + + `@better-auth/memory-adapter` now treats `undefined` and `null` as equivalent under an `eq null` `where` clause, mirroring SQL `IS NULL` and Mongo's missing-or-null semantics. The adapter factory's `transformInput` skips writing optional fields whose value is `undefined`, so a CAS predicate like `WHERE revoked IS NULL` against a freshly created row (where the field is absent) used to fail-closed on every call. Without this change the refresh-token rotation above is broken for any deployment using the in-memory adapter. + + **Migration note:** the better-auth migration generator only emits `UNIQUE` for newly-created columns. Existing installs will not get the new `oauthRefreshToken.token` unique constraint via `migrate`/`generate`; add it manually if your operational tooling relies on it (e.g. `CREATE UNIQUE INDEX oauth_refresh_token_token_uniq ON "oauthRefreshToken" (token);`). The CAS fix above does not depend on the database-level constraint to be correct; the constraint is defense-in-depth so collisions from buggy custom `generateRefreshToken` callbacks fail loudly. + + Strict family invalidation on contested rotations (per RFC 9700 §4.14) is deferred to a follow-up minor; closing it cleanly requires opt-in transactional rotation in the adapter contract so the family-delete cannot interleave with the winner's in-flight access-token insert. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/oauth-provider/package.json b/packages/oauth-provider/package.json index 402026f420..04567d07ae 100644 --- a/packages/oauth-provider/package.json +++ b/packages/oauth-provider/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/oauth-provider", - "version": "1.6.10", + "version": "1.6.11", "description": "An oauth provider plugin for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/passkey/CHANGELOG.md b/packages/passkey/CHANGELOG.md index 9a9cabead4..60a7e41eb2 100644 --- a/packages/passkey/CHANGELOG.md +++ b/packages/passkey/CHANGELOG.md @@ -1,5 +1,13 @@ # @better-auth/passkey +## 1.6.11 + +### Patch Changes + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/passkey/package.json b/packages/passkey/package.json index d13be39af8..4676948703 100644 --- a/packages/passkey/package.json +++ b/packages/passkey/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/passkey", - "version": "1.6.10", + "version": "1.6.11", "description": "Passkey plugin for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/prisma-adapter/CHANGELOG.md b/packages/prisma-adapter/CHANGELOG.md index aebdb82fa8..59f09f2f75 100644 --- a/packages/prisma-adapter/CHANGELOG.md +++ b/packages/prisma-adapter/CHANGELOG.md @@ -1,5 +1,14 @@ # @better-auth/prisma-adapter +## 1.6.11 + +### Patch Changes + +- [#9568](https://github.com/better-auth/better-auth/pull/9568) [`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/prisma-adapter/package.json b/packages/prisma-adapter/package.json index badb644f5d..50ff2595bf 100644 --- a/packages/prisma-adapter/package.json +++ b/packages/prisma-adapter/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/prisma-adapter", - "version": "1.6.10", + "version": "1.6.11", "description": "Prisma adapter for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/redis-storage/CHANGELOG.md b/packages/redis-storage/CHANGELOG.md index cf3ddafb92..ef65ce7ef9 100644 --- a/packages/redis-storage/CHANGELOG.md +++ b/packages/redis-storage/CHANGELOG.md @@ -1,5 +1,14 @@ # @better-auth/redis-storage +## 1.6.11 + +### Patch Changes + +- [#9568](https://github.com/better-auth/better-auth/pull/9568) [`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - Add `internalAdapter.consumeVerificationValue(identifier)`: atomically consume a verification row keyed by identifier. The first concurrent caller receives the row; later racers receive `null`. Backed by a new `DBAdapter.consumeOne` primitive implemented natively per adapter (memory, mongo, drizzle, kysely, prisma), with a `transaction(findMany + delete)` factory fallback. `SecondaryStorage.getAndDelete` is added as an optional companion; Redis ships it via an atomic Lua get-and-delete operation for compatibility with Redis versions before 6.2. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/redis-storage/package.json b/packages/redis-storage/package.json index 3418bcc02f..18da11b864 100644 --- a/packages/redis-storage/package.json +++ b/packages/redis-storage/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/redis-storage", - "version": "1.6.10", + "version": "1.6.11", "description": "Redis storage for Better Auth secondary storage", "type": "module", "license": "MIT", diff --git a/packages/scim/CHANGELOG.md b/packages/scim/CHANGELOG.md index 44b081faa8..6fe799e0d7 100644 --- a/packages/scim/CHANGELOG.md +++ b/packages/scim/CHANGELOG.md @@ -1,5 +1,21 @@ # @better-auth/scim +## 1.6.11 + +### Patch Changes + +- [#9162](https://github.com/better-auth/better-auth/pull/9162) [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70) Thanks [@ping-maxwell](https://github.com/ping-maxwell)! - fix: cleanup sessions when admin, anonymous, or SCIM deletes a user + +- [#9579](https://github.com/better-auth/better-auth/pull/9579) [`2f5d91c`](https://github.com/better-auth/better-auth/commit/2f5d91c5bb7d0e22f07533b40c9905ef97e3a9e9) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - `POST /scim/generate-token` accepted a `providerId` that collided with a built-in `account.providerId` value (`credential`, `email-otp`, `magic-link`, `phone-number`, `anonymous`, `siwe`, or any configured social provider key), so a SCIM caller could mint a token that authenticated against accounts it never provisioned. + + `generateSCIMToken` now rejects `providerId` values that collide with the built-in account provider list, returning `BAD_REQUEST` at issuance. The configured-social-provider check reads from `options.socialProviders` rather than the resolved provider list so that providers disabled with `enabled: false` are still rejected: their account rows can persist from when the provider was enabled. + + `providerOwnership.enabled` stays default `false` on this patch release so existing SQL deployments do not need a schema migration mid-upgrade. The follow-up on `next` flips the default to `true` and ships the corresponding `scimProvider.userId` schema column so non-organization SCIM tokens are owner-locked by default. Operators who need owner-locking immediately can opt in today with `scim({ providerOwnership: { enabled: true } })` and add the `userId` column manually. + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/scim/package.json b/packages/scim/package.json index 03a4c6272f..57ab1a7d7b 100644 --- a/packages/scim/package.json +++ b/packages/scim/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/scim", - "version": "1.6.10", + "version": "1.6.11", "description": "SCIM plugin for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/sso/CHANGELOG.md b/packages/sso/CHANGELOG.md index 8a67debaf1..1de31247a2 100644 --- a/packages/sso/CHANGELOG.md +++ b/packages/sso/CHANGELOG.md @@ -1,5 +1,48 @@ # @better-auth/sso +## 1.6.11 + +### Patch Changes + +- [#9220](https://github.com/better-auth/better-auth/pull/9220) [`86765f1`](https://github.com/better-auth/better-auth/commit/86765f1597378f5c3deed1b80ca91faac0a6bf00) Thanks [@stewartjarod](https://github.com/stewartjarod)! - fix(sso): require org admin role to register SSO providers + + `POST /sso/register` previously allowed any organization member to register an + SSO provider for the organization when `organizationId` was supplied, only + checking membership and not role. This brings it in line with the other + provider endpoints (`get`/`update`/`delete`), which go through + `checkProviderAccess` → `isOrgAdmin` and restrict access to `owner` or `admin` + roles. + + Closes [#9133](https://github.com/better-auth/better-auth/issues/9133). + +- [#9574](https://github.com/better-auth/better-auth/pull/9574) [`37f60cb`](https://github.com/better-auth/better-auth/commit/37f60cb176cb53147da7dfd5ec15afa5b486e81e) Thanks [@gustavovalverde](https://github.com/gustavovalverde)! - fix(sso): validate user-supplied OIDC endpoint URLs at provider registration and update + + When `skipDiscovery: true` was passed to `POST /sso/register`, or any + `oidcConfig` URL was passed to `POST /sso/update-provider`, the supplied + `authorizationEndpoint`, `tokenEndpoint`, `userInfoEndpoint`, `jwksEndpoint`, + and `discoveryEndpoint` values were persisted on the provider row without + origin validation, then fetched server-side at OIDC callback time. An + authenticated user could register or update an SSO provider with internal + URLs (RFC 1918, link-local, cloud-metadata FQDNs like `169.254.169.254`, + loopback) and use the callback handler to coerce the server into making + requests to those hosts. + + Both endpoints now run user-supplied OIDC URLs through a layered gate: + 1. URL parsing + `http(s)` scheme requirement + 2. `isPublicRoutableHost` from `@better-auth/core/utils/host` (rejects + loopback, RFC 1918, link-local, ULA, cloud-metadata FQDNs, multicast, + broadcast, and reserved ranges per RFC 6890) + 3. `trustedOrigins` allowlist as the documented escape hatch for customers + running internal IdPs on private networks + + A request that fails the gate is rejected with `BAD_REQUEST` and the new + `discovery_private_host` error code (or `discovery_invalid_url` for + malformed URLs / non-`http(s)` schemes). + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/sso/package.json b/packages/sso/package.json index f3cbfe8995..a9b5d2724e 100644 --- a/packages/sso/package.json +++ b/packages/sso/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/sso", - "version": "1.6.10", + "version": "1.6.11", "description": "SSO plugin for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/stripe/CHANGELOG.md b/packages/stripe/CHANGELOG.md index 8589deeb23..9fa5a76418 100644 --- a/packages/stripe/CHANGELOG.md +++ b/packages/stripe/CHANGELOG.md @@ -1,5 +1,13 @@ # @better-auth/stripe +## 1.6.11 + +### Patch Changes + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/stripe/package.json b/packages/stripe/package.json index 96524ff095..fb45f2b900 100644 --- a/packages/stripe/package.json +++ b/packages/stripe/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/stripe", - "version": "1.6.10", + "version": "1.6.11", "description": "Stripe plugin for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/telemetry/CHANGELOG.md b/packages/telemetry/CHANGELOG.md index da8efcbd54..a71e00e06d 100644 --- a/packages/telemetry/CHANGELOG.md +++ b/packages/telemetry/CHANGELOG.md @@ -1,5 +1,12 @@ # @better-auth/telemetry +## 1.6.11 + +### Patch Changes + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/telemetry/package.json b/packages/telemetry/package.json index 6b9da600df..f2a215d312 100644 --- a/packages/telemetry/package.json +++ b/packages/telemetry/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/telemetry", - "version": "1.6.10", + "version": "1.6.11", "description": "Telemetry package for Better Auth", "type": "module", "license": "MIT", diff --git a/packages/test-utils/CHANGELOG.md b/packages/test-utils/CHANGELOG.md index c8d707fc25..218a94328c 100644 --- a/packages/test-utils/CHANGELOG.md +++ b/packages/test-utils/CHANGELOG.md @@ -1,5 +1,13 @@ # @better-auth/test-utils +## 1.6.11 + +### Patch Changes + +- Updated dependencies [[`0cbddb8`](https://github.com/better-auth/better-auth/commit/0cbddb8fa4eb19fbca75e9822134f89b3604286a), [`a26333b`](https://github.com/better-auth/better-auth/commit/a26333b5fb1a044e76c18385441d3ecc2240ab70), [`99a254a`](https://github.com/better-auth/better-auth/commit/99a254a79b59d5a3f5ca2123260118cddb5beed7), [`ee93485`](https://github.com/better-auth/better-auth/commit/ee934854999390ee5ca73592fe205a470a810b83), [`5f09d56`](https://github.com/better-auth/better-auth/commit/5f09d566a64ac9a0499d9664ce700edbf0630cea), [`b4bc65a`](https://github.com/better-auth/better-auth/commit/b4bc65a007784b2eb0efb459e5fa6fd8055d3ec9), [`da7e50b`](https://github.com/better-auth/better-auth/commit/da7e50beee849c59a2ed1ec6b3a38cc6ab9fb563), [`a1c9f3c`](https://github.com/better-auth/better-auth/commit/a1c9f3c08e7398e900e099839aa6dcc8d1d0b816), [`23094a6`](https://github.com/better-auth/better-auth/commit/23094a628f007f801be6d26e5b15dc5fc6fc4eb8), [`142b86c`](https://github.com/better-auth/better-auth/commit/142b86c43d2e6b258236a298a31237e97f87d64d), [`1f2ff42`](https://github.com/better-auth/better-auth/commit/1f2ff4215c4affff0b140b0c0a712c0dde35659c), [`b0ef96f`](https://github.com/better-auth/better-auth/commit/b0ef96fd8ec08ebb4d6ad0c0557d4b7855703f10), [`699b09a`](https://github.com/better-auth/better-auth/commit/699b09a2064dcb7d37046b5a90626c0b6f57af90), [`e21d744`](https://github.com/better-auth/better-auth/commit/e21d744987476c20a934c79ef226fe6a5f468e22)]: + - @better-auth/core@1.6.11 + - better-auth@1.6.11 + ## 1.6.10 ### Patch Changes diff --git a/packages/test-utils/package.json b/packages/test-utils/package.json index 1cc38d9844..32c66bedc0 100644 --- a/packages/test-utils/package.json +++ b/packages/test-utils/package.json @@ -1,6 +1,6 @@ { "name": "@better-auth/test-utils", - "version": "1.6.10", + "version": "1.6.11", "description": "Testing utilities for Better Auth adapter development", "type": "module", "license": "MIT",