[PR #8730] fix: hashed verification identifiers for OAuth state #16422

Closed
opened 2026-04-13 10:31:04 -05:00 by GiteaMirror · 0 comments
Owner

Original Pull Request: https://github.com/better-auth/better-auth/pull/8730

State: closed
Merged: No


Summary

This fixes OAuth social sign-in when verification.storeIdentifier is set to "hashed" and OAuth state is stored in the database.

Previously, Better Auth stored the raw OAuth state in the signed cookie but returned the transformed verification identifier in the public state query param. When identifier hashing was enabled, that caused the callback to compare the raw cookie state against a hashed callback state and fail with state_security_mismatch.

Fixes: #8727

What changed

  • Store database-backed OAuth state in the verification table under an internal oauth-state:${state} identifier
  • Keep the public OAuth state value raw for the cookie and provider callback
  • Continue using the shared verification storage layer so verification.storeIdentifier.overrides can target OAuth state with the oauth-state: prefix
  • Document the behavior in the options reference, including that account.storeStateStrategy: "cookie" bypasses the verification table for OAuth state

Summary by cubic

Fixes OAuth sign-in when verification.storeIdentifier is hashed by storing database-backed OAuth state under an internal oauth-state: key while keeping the public state raw. Adds backward compatibility for legacy raw OAuth state and documents storeStateStrategy defaults.

  • Bug Fixes
    • Store DB-backed OAuth state as oauth-state:${state} and delete it after use.
    • Keep the cookie/provider state raw to avoid mismatches with hashed storage.
    • Add a shared lookup that reads oauth-state:${state} and legacy raw state in both callback and the oauth-proxy DB path.
    • Document storeStateStrategy (default "database" with a DB, otherwise "cookie") and that DB-backed state uses the shared verification layer and secondaryStorage; can be targeted via verification.storeIdentifier.overrides with the oauth-state: prefix.

Written for commit 04f0905b4b. Summary will update on new commits.

**Original Pull Request:** https://github.com/better-auth/better-auth/pull/8730 **State:** closed **Merged:** No --- ## Summary This fixes OAuth social sign-in when `verification.storeIdentifier` is set to `"hashed"` and OAuth state is stored in the database. Previously, Better Auth stored the raw OAuth state in the signed cookie but returned the transformed verification identifier in the public `state` query param. When identifier hashing was enabled, that caused the callback to compare the raw cookie state against a hashed callback state and fail with `state_security_mismatch`. ## Fixes: #8727 ## What changed - Store database-backed OAuth state in the verification table under an internal `oauth-state:${state}` identifier - Keep the public OAuth `state` value raw for the cookie and provider callback - Continue using the shared verification storage layer so `verification.storeIdentifier.overrides` can target OAuth state with the `oauth-state:` prefix - Document the behavior in the options reference, including that `account.storeStateStrategy: "cookie"` bypasses the verification table for OAuth state <!-- This is an auto-generated description by cubic. --> --- ## Summary by cubic Fixes OAuth sign-in when `verification.storeIdentifier` is `hashed` by storing database-backed OAuth state under an internal `oauth-state:` key while keeping the public `state` raw. Adds backward compatibility for legacy raw OAuth state and documents `storeStateStrategy` defaults. - **Bug Fixes** - Store DB-backed OAuth state as `oauth-state:${state}` and delete it after use. - Keep the cookie/provider `state` raw to avoid mismatches with hashed storage. - Add a shared lookup that reads `oauth-state:${state}` and legacy raw `state` in both callback and the `oauth-proxy` DB path. - Document `storeStateStrategy` (default `"database"` with a DB, otherwise `"cookie"`) and that DB-backed state uses the shared verification layer and `secondaryStorage`; can be targeted via `verification.storeIdentifier.overrides` with the `oauth-state:` prefix. <sup>Written for commit 04f0905b4bc4b80465ce65a06779f4cbdb3be5eb. Summary will update on new commits.</sup> <!-- End of auto-generated description by cubic. -->
GiteaMirror added the pull-request label 2026-04-13 10:31:04 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#16422