Important
Action required
-
If you set an
Authorizationentry inauthorizationHeadersor passauthorizationinheadersto the@better-auth/core/oauth2token request functions, remove it and set the header fromcustomizeRequestwithtokenEndpointAuthmethodcustom, which must also set every credential the provider requires. (#12416) -
feat(oauth)!: bind client-submitted ID tokens to a server-issued nonce (#11823)
Apps where clients sign in or link accounts with a provider ID token (for example from a native Google or Apple SDK) can now bind each token to one request. Set
requireIssuedIdTokenNonce: trueon a social provider. Clients then fetch a single-use nonce withauthClient.idToken.nonce({ provider }), pass it to the provider's SDK, and send it with the ID token tosignIn.socialorlinkSocial. A request without an issued nonce, or reusing one, is rejected with400 INVALID_ID_TOKEN_NONCE. The option is off by default, and providers without it behave as before.One change applies to every provider that uses built-in verification: an opaque (non-JWT) token, such as a Facebook Graph access token, is now rejected when the request also sends a
nonce, because the token cannot carry one. A customverifyIdTokenmust compare the nonce to the token's claim itself. Opaque tokens sent without a nonce are still accepted.Expired verification rows are now also deleted when a single-use value, such as a magic link, an OTP, or an issued nonce, is used. Before, cleanup ran only when a value was looked up.
verification.disableCleanupturns off both. -
If you call
/one-tap/callbackorauth.api.oneTapCallbackyourself, callPOST /one-tap/noncefirst, pass the nonce togoogle.accounts.id.initialize({ nonce }), and send it asnoncein the callback body; if you set the clientnonceoption or anonceinadditionalOptions, remove it. (#11823) -
If you use the built-in Kysely adapter, run
npx auth@latest migrate; if you use Prisma or Drizzle, runnpx auth@latest generateand apply the migration before deploying, to add theexpiresAtcolumn tooauthClient. MongoDB needs no migration. (#11802)
better-auth
❗ Breaking Changes
- Changed generic OAuth to fail at startup when
authorizationHeaderscontains anAuthorizationentry, and madevalidateAuthorizationCode,authorizationCodeRequest,refreshAccessToken, andrefreshAccessTokenRequestthrow when passedauthorizationinheaders(#12416) - feat(oauth)!: bind client-submitted ID tokens to a server-issued nonce (#11823)
- Changed
/one-tap/callbackto require a single-use nonce from the newPOST /one-tap/nonceendpoint so each Google ID token signs in only once (#11823)
For detailed changes, see CHANGELOG
@better-auth/core
❗ Breaking Changes
- Changed generic OAuth to fail at startup when
authorizationHeaderscontains anAuthorizationentry, and madevalidateAuthorizationCode,authorizationCodeRequest,refreshAccessToken, andrefreshAccessTokenRequestthrow when passedauthorizationinheaders(#12416) - feat(oauth)!: bind client-submitted ID tokens to a server-issued nonce (#11823)
Features
- Added support for server-provided DPoP nonces in the OAuth provider through
dpop: { nonce: { required: true } }, plus resource server support withverifyAccessTokenRequest,createResourceServerChallenge, andcreateDpopNonce(#12376)
For detailed changes, see CHANGELOG
@better-auth/oauth-provider
Features
- Added support for server-provided DPoP nonces in the OAuth provider through
dpop: { nonce: { required: true } }, plus resource server support withverifyAccessTokenRequest,createResourceServerChallenge, andcreateDpopNonce(#12376)
Bug Fixes
- Fixed OAuth provider client secret expiry so it is saved, returned as
client_secret_expires_at, and enforced withinvalid_clientat the token, introspection, and revocation endpoints (#11802)
For detailed changes, see CHANGELOG
@better-auth/mcp
Features
- Added support for server-provided DPoP nonces in the OAuth provider through
dpop: { nonce: { required: true } }, plus resource server support withverifyAccessTokenRequest,createResourceServerChallenge, andcreateDpopNonce(#12376)
For detailed changes, see CHANGELOG
Contributors
Thanks to everyone who contributed to this release:
Full changelog: v1.8.0-beta.7...v1.8.0-beta.8