Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

An OAuth client should accept a valid state value at its redirect endpoint only once. Bind it to the browser’s pending authorization transaction, validate the callback against that transaction, and atomically mark the value consumed when it succeeds. A later callback that reuses the same value should fail. This replay boundary does not protect a value stolen before the legitimate callback arrives.

What the replay boundary protects

OAuth clients must protect their redirect endpoints against cross-site request forgery (CSRF). RFC 6749 describes state as a non-guessable value that binds the authorization response to the user agent’s authenticated state, and requires CSRF protection for the redirect URI: RFC 6749.

RFC 9700, the OAuth 2.0 Security Best Current Practice published in January 2025, says that when state is used for CSRF protection, it must be one-time-use and securely bound to the user agent. It says the client should invalidate the value after its first use at the redirection endpoint: RFC 9700.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

In practical terms, the first valid callback consumes the marker. A duplicate or delayed callback carrying that same marker must not be accepted as a new authorization transaction.

How to validate and consume state

  1. Create a transaction-specific value. Generate a non-guessable state value for the authorization attempt. Associate it with the initiating user agent and the client’s pending transaction.
  2. Keep the pending transaction available to the callback. Store enough information to compare the returned value with the value expected for that user agent and authorization attempt.
  3. Validate before processing the response. At the redirect endpoint, check that the returned state matches the pending transaction and that it has not already been used. Reject missing, mismatched, or consumed values.
  4. Consume it as part of successful validation. Record the value as used so the same callback cannot succeed again. The check and consume operation should be atomic: if two requests arrive concurrently, only one should be able to pass. Atomic consumption is an implementation consequence of the single-use requirement; RFC 9700 does not prescribe a storage system or concurrency primitive.

Where the boundary stops

Single-use enforcement rejects reuse after the client has accepted a callback. It does not protect a marker that an attacker obtains before the legitimate response reaches the client. In that case the client has not consumed the marker yet, and RFC 9700 warns that learning state can defeat the CSRF protection it provides.

Assess how authorization requests and responses might be exposed before callback validation, including exposure through URLs, third-party content, or referrer behavior. A one-time marker is not a substitute for reducing leakage or securely binding the authorization transaction to the user agent.

When PKCE or OpenID Connect nonce is involved

RFC 9700 allows clients to rely on PKCE for CSRF protection only when they have ensured that the authorization server supports PKCE. If that support is not established, use state or an OpenID Connect nonce for CSRF protection. PKCE challenges and OIDC nonces must be specific to the transaction and securely bound to the client and user agent.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Protect application data carried in state

Some clients use state to carry application data as well as a transaction marker. Single-use validation alone does not protect that payload from tampering or swapping. If the data’s integrity matters, bind it to the browser session, sign or encrypt it, or use suitable combinations of those measures, as RFC 9700 describes.

Review an implementation against these checks

  • Transaction binding: Is the value tied to both the initiating user agent and the client’s pending authorization attempt?
  • One-time enforcement: Does successful validation consume the value, including under concurrent callback requests?
  • Leakage exposure: Could the request or response URL become visible through third-party content or referrer behavior before the client consumes the value?
  • Payload integrity: If application data is embedded, can it be tampered with or swapped, and is it session-bound or cryptographically protected?
  • Alternative CSRF protection: Is authorization-server support for PKCE actually established, or must the client use state or OIDC nonce?

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.