PKCE Generator
Single-page apps and mobile clients cannot hide an OAuth client secret, so RFC 7636 replaces that secret with a per-request random verifier. This generator produces the three values every authorization request needs: a compliant code_verifier, its Base64url SHA-256 code_challenge, and a state token for CSRF protection on the redirect.
Generate a fresh pair, paste your authorize endpoint and client ID to assemble the full redirect URL, and use the built-in checker to confirm an existing verifier matches a challenge you already deployed. SHA-256 runs through the Web Crypto API locally; nothing is sent anywhere.
Assemble a full authorize URL (optional)
How the PKCE handshake actually runs
Before any redirect happens, the client generates the verifier (random unreserved characters, 43 to 128 long) and computes the challenge as Base64url of the SHA-256 digest of the verifier bytes, with no trailing equals signs. The authorize request carries the challenge and the fixed method string S256, plus state, client_id, redirect_uri, scope, and response_type=code.
After authentication, the provider redirects back with a short-lived authorization code and the original state. The client confirms state matches, then POSTs grant_type=authorization_code, the code, the redirect_uri again, and the stored verifier to the token endpoint. The provider hashes the incoming verifier, compares it against the challenge it stored for that code, and mints tokens only on a match.
Because the challenge is one-way, an intercepted authorize URL or a leaked authorization code cannot be redeemed without the verifier, which never appears in browser history, referrer headers, or server logs of the redirect hop. This is what closes the interception hole that the original OAuth 2.0 code flow left open for public clients.
Before and after: values in a real authorization request
Input — a freshly generated pair at 64 characters:
code_verifier: a1B2c3D4...(64 unreserved chars)
method: S256
client_id: my-spa-client
redirect_uri: https://app.example.com/callback Output — the authorize URL and the token request the client sends:
GET /oauth2/authorize?response_type=code
&client_id=my-spa-client
&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback
&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
&code_challenge_method=S256
&state=x7Kq9...
POST /oauth2/token
grant_type=authorization_code
&code= SplMXK...
&redirect_uri=https://app.example.com/callback
&code_verifier=a1B2c3D4... Who generates PKCE values
Developers
- Wire a new single-page app against Auth0, Okta, Cognito, or Entra ID without copying a half-working example that reuses one verifier forever.
- Verify that your implementation of the S256 digest produces the same challenge as this generator before blaming the identity provider for token endpoint errors.
- Assemble a complete authorize URL by hand to reproduce a redirect bug in an incognito window where your app state is clean.
Production
- Smoke-test a newly registered OAuth client from a clean profile before enabling it for real user traffic.
- Audit whether an existing mobile app stores the verifier correctly by comparing session values against freshly generated pairs.
- Confirm provider-side PKCE enforcement by attempting the token exchange with a deliberately wrong verifier and expecting a rejection.
Workflow
- Paste the checker values during a security review to prove a stored challenge corresponds to the verifier the app actually keeps.
- Generate deterministic fixtures for integration tests by running the generator once and freezing the pair in the test data file.
- Hand the full authorize URL to a support engineer so they can walk a customer through consent without sharing your dashboard session.
Common mistakes when implementing PKCE
- Reusing one verifier across logins. The provider binds the challenge to a single authorization request. A pair that works twice in a row will eventually fail in production under concurrent sessions, and some providers reject repeats immediately. Generate per attempt.
- Base64-encoding with standard padding and alphabet. The challenge must be Base64url: hyphens and underscores instead of plus and slash, and equals signs stripped. Sending standard Base64 produces a digest mismatch error at the token endpoint that looks like a provider bug.
- Forgetting code_challenge_method=S256. Omitting the parameter often defaults the provider to the plain method, which then fails because your challenge is a hash, not the verifier itself. Always send the method explicitly.
- Dropping state because PKCE exists. PKCE defends the code exchange, state defends the redirect leg against login CSRF. They solve different problems; the current OAuth security BCP expects both for public clients.
Best practices for PKCE in real apps
- 1.Store the verifier in session storage keyed per flow attempt, and delete it as soon as the token response lands or the user cancels, so a refresh cannot resurrect a stale pair.
- 2.Validate the state value in the callback before exchanging the code; treat a mismatch as an aborted login, never as a retry with a new state.
- 3.Register exact-match redirect URIs with no wildcards and no open redirects, because PKCE does not help if the code is delivered to a URI an attacker controls.
- 4.Use the PKCE checker above during development to confirm your digest implementation matches before opening a ticket with the identity provider.
Frequently asked questions
What problem does PKCE solve in OAuth 2.0?
PKCE (Proof Key for Code Exchange, RFC 7636) protects the authorization-code flow when the OAuth client cannot keep a secret, which describes every single-page app and native mobile app. Without PKCE, an attacker who can intercept the one-time authorization code sent to a registered redirect URI can exchange it for tokens, because the code alone is enough. PKCE makes the attacker also need the random code_verifier that only the legitimate client generated, so a stolen code is worthless.
What is the difference between the code_verifier and the code_challenge?
The code_verifier is a long random string the client invents before redirecting the user to the login page. The code_challenge is a digest of that verifier, sent along in the authorization request. After the user approves, the client receives an authorization code and later exchanges it for tokens while sending the original verifier. The identity provider hashes the verifier, compares it to the stored challenge, and only then issues tokens, so the verifier itself never travels during the redirect where it could leak.
Why is S256 preferred over the plain method?
The plain method sends the verifier itself as the challenge, which still blocks code interception by a third party but exposes the verifier to anything that can read the authorization request, such as a compromised redirect page. S256 sends only the Base64url-encoded SHA-256 of the verifier, so the value in the browser history and referrer headers cannot be reversed into the secret. The RFC lists S256 as the mandatory-to-implement method and plain as optional; always choose S256 unless a legacy provider forces plain.
How long should a PKCE code_verifier be?
RFC 7636 requires between 43 and 128 characters drawn from the unreserved set: letters, digits, hyphen, period, underscore, and tilde. Forty-three characters of Base64url randomness is the practical floor and equals 32 bytes of entropy, which is far more than needed to resist guessing. This generator defaults to 64 characters for headroom; anything inside the allowed range satisfies the RFC, and providers must accept the full 43 to 128 span.
What is the state parameter and do I still need it with PKCE?
State is a per-request random value the client sends with the authorization request and expects back in the callback. It defends against cross-site request forgery on the redirect, meaning an attacker tricking a logged-in user into completing an attacker-started login. PKCE and state solve different problems; RFC 9700 (the OAuth security best-practice update) recommends using state alongside PKCE for confidential and public clients alike. The generator produces both values together so you cannot forget one.
Can I use one PKCE pair for multiple logins?
No. Each authorization request needs its own verifier and challenge pair because the provider stores the challenge bound to that single request. Reusing a verifier across attempts weakens the design and some providers reject repeats outright. Generate a fresh pair on every login initiation, keep the verifier in memory or session storage only for the duration of that flow, and discard it the moment the token response arrives or the attempt is abandoned.
Where should the code_verifier live in a browser app?
Session storage is the common choice because it survives the full-page redirect to the identity provider and back while clearing when the tab session ends, and it is scoped per tab so parallel login attempts do not collide. Local storage also works but keeps the verifier after the flow finishes, which is an unnecessary residue. Avoid cookies for the verifier unless you have a specific CSRF-token architecture that already relies on cookie handling and same-site rules.
Related auth and token tools
Build signed test JSON Web Tokens entirely in the browser
Inspect header, claims, and expiry of any JSON Web Token
Sign tokens with HS and RS algorithms, then verify signatures
Create random keys and IVs for symmetric encryption
Draft Content-Security-Policy headers with nonces and hashes
Percent-encode query values the authorize URL requires