Brings the v1.6.13 stable fixes into next: redirect_uri scheme validation in oidc-provider and mcp (#9838), clientPrivileges enforcement on dynamic client registration (#9837), null organization logo support (#9842), the consumeOne non-numeric deleteMany guard (#9831), and the db-adapter guide alignment (#9830).
Conflicts were limited to release version bumps and CHANGELOG entries; resolved by keeping next's 1.7.0-beta.3 line. The ten changesets consumed by the v1.6.13 release are accepted as deleted, and no external dependencies changed.
These test files auto-merged main's additions onto next's refactored test
surface, producing runtime failures tsc could not catch:
- token.test.ts called main's sync createRefreshAccessTokenRequest, which next
renamed to the async refreshAccessTokenRequest; the calls now await it and
the concurrent-rotation helper is async.
- private-key-jwt-e2e.test.ts hit the merged-in #9578 gate: both the provider
and RP test instances create the same default user, so the OAuth sign-in
links to the RP's unverified local user and is blocked. The RP sets
requireLocalEmailVerified: false so the test exercises private_key_jwt
rather than the (separately covered) email-verification gate.
- utils/basic-auth.test.ts is removed: next made basicToClientCredentials
private, and its colon-preservation coverage now lives in core's
basic-credentials.test.ts.
Full oauth-provider suite green (24 files, 378 tests).
Re-applies two main fixes onto next's refactored metadata layer.
- #9448: registration_endpoint is now advertised only when dynamic client
registration is enabled. With DCR off, the field was still advertised in
authorization-server and OpenID metadata while the endpoint itself was
disabled, so clients attempted a registration that failed.
- #9668: the authorization-server and OpenID discovery documents are served
again at their path-prefixed (RFC 8414 path-insertion and issuer-appended)
aliases via an onRequest handler, with HEAD support and a 405 for
non-GET/HEAD. next's refactor kept the server-only metadata endpoints but
dropped the request handler that exposes them over HTTP. The handler is
adapted to next's metadata (CIMD-aware public-client flag and merged
discovery metadata) and metadataResponse is exported for it.
#9601 (preserve colons in Basic Auth secret) is already covered: next routes
Basic parsing through @better-auth/core decodeBasicCredentials, which splits
on the first colon, so no change to utils/index.ts.
The merged metadata test suite (union of next and main, including the
DCR-conditional and alias cases) passes.
(cherry picked from commit 66a7b0b62d76e36474ebdca189f59200daa3ec76)
Sync main (through #9821/#9820/#9822/#9768) into next. Conflicting
package.json files keep next's version and intentional divergences (for
example the cli's c12 v4) while taking main's dependency updates, including
the samlify 2.13.1 and fast-xml-parser security bumps; the lockfile is
regenerated from the reconciled set. The 13 source/doc/test conflicts take
next's refactored architecture as the baseline; main's colliding fixes are
re-applied on top in the following per-domain commits.
Clean main fixes land via this merge, including the auto-restored
account-takeover defenses #9578 and #9577.
The `authorization_code` grant's verification step was a `findOne` + `deleteOne` pair, so two concurrent `POST /oauth2/token` requests sharing the same `code` both pass the find, both delete, and both mint independent access/refresh/id token sets: a CAS gap that lets an authorization code be redeemed twice. The legacy `oidc-provider` and `mcp` plugins in `better-auth` share the same primitive on their `authorization_code` paths and have the same gap.
All three call sites now use `internalAdapter.consumeVerificationValue` (the atomic primitive added in better-auth#9560 and renamed in better-auth#9568): the first concurrent caller receives the row and mints tokens, subsequent racers receive `null`. The consumed and expired paths return RFC 6749 §5.2 `invalid_grant` instead of the better-auth-internal `invalid_verification`, so spec-compliant clients can branch on the standard code. The redundant second `deleteVerificationByIdentifier` call after PKCE validation in the legacy paths is removed.
Closes GHSA-7w99-5wm4-3g79.
Co-authored-by: chdanielmueller <4051999+chdanielmueller@users.noreply.github.com>
The `authorization_code`-grant rotation in `createRefreshToken` and the explicit `revokeRefreshToken` path both updated the parent `oauthRefreshToken` row using an `id`-only predicate, so two concurrent rotations (or a rotation racing a revoke) both pass the `revoked` check and last-write-wins. Each surviving request mints a fresh refresh token, producing a forked family from one parent.
Both call sites now perform a compare-and-swap (`UPDATE ... WHERE id = ? AND revoked IS NULL`) and short-circuit with `invalid_grant` when the row was already consumed. The parent stays marked revoked, so any subsequent replay trips the existing family-invalidation guard in `handleRefreshTokenGrant`. The shared family-delete is centralized in `invalidateRefreshFamily`, which clears child access tokens before refresh rows to honor the schema's foreign-key direction; the `oauthRefreshToken.token` column also gains a `unique` constraint for parity with `oauthAccessToken.token`. Strict family invalidation on contested rotations (RFC 9700 §4.14) is tracked in a FIXME for a follow-up minor that opts into transactional rotation in the adapter contract.
Closes GHSA-392p-2q2v-4372.
Co-authored-by: chdanielmueller <4051999+chdanielmueller@users.noreply.github.com>
- keep next package versions at 1.7.0-beta.1
- keep both changelog streams by inserting the stable 1.6.5, 1.6.6, and 1.6.7 sections below the 1.7.0-beta entries
- keep the cimd and dash deps on demo/nextjs (next-only); regenerate pnpm-lock.yaml
- resolve TODO(sync-from-main-9226) in oauth-provider authorize.ts: findRegisteredRedirectUri now uses isLoopbackIP from @better-auth/core/utils/host to cover the full 127.0.0.0/8 range per RFC 8252 §7.3
- drop the unused saml import that main's #9262 added to sso/src/routes/sso.ts; next already migrated to saml-pipeline