flashman
← All guides

OAuth PKCE verifier generation, storage, and validation

Implement OAuth PKCE safely with high-entropy verifiers, exact S256 encoding, transaction-bound storage, one-time callbacks, and production test fixtures.

2026-09-09 · 8 min read

  • oauth
  • pkce
  • authentication

Proof Key for Code Exchange binds an OAuth authorization code to a secret created by the client for one authorization transaction. It protects a stolen code from being redeemed by a party that does not possess the original verifier.

PKCE complements redirect URI validation, state correlation, client authentication where applicable, and token validation. It does not turn an unsafe redirect or untrusted authorization server into a secure flow.

Generate an interoperable verifier

Create the verifier with a cryptographically secure random generator and encode it using only the unreserved characters allowed by the PKCE specification. Keep enough entropy even if the textual representation has the maximum permitted length.

  • Use a maintained OAuth library when available.
  • Prefer S256 and reject an unexpected downgrade to plain.
  • Do not derive the verifier from a user password or timestamp.
  • Never reuse one verifier across authorization requests.

Compute the challenge exactly

For S256, SHA-256 hashes the ASCII verifier bytes. Base64url then encodes the 32-byte digest using hyphen and underscore instead of plus and slash, with trailing equals padding omitted.

Do not hash a decoded Base64 value, a quoted string, a normalized Unicode string, or the challenge itself. Compare against published test vectors before diagnosing an authorization server.

Bind storage to one transaction

Store the verifier in a protected, short-lived transaction record associated with state and the exact callback flow. Consume it once when exchanging the code, then remove it whether the exchange succeeds or reaches a terminal failure.

  • Support concurrent tabs without overwriting another verifier.
  • Share transaction storage safely across application instances.
  • Keep verifiers out of URLs, logs, analytics, and error pages.
  • Expire abandoned records and bound their total count.

Test the complete browser round trip

Use Flashman's hash and Base64 tools with public PKCE fixtures, URL tool for redacted authorization parameters, diff for transformation evidence, and password generator only to explore safe random-character sets. Use production libraries for the actual protocol.

Test concurrent attempts, cancellation, back navigation, duplicate callbacks, stale state, process restarts, verifier boundaries, wrong redirect URIs, authorization-code replay, token endpoint errors, and browser privacy restrictions.

Try these tools