PKCE Code Verifier Generator | OAuth 2.0 PKCE Test Pair Generator
Generate a fresh code_verifier and S256 code_challenge pair for the OAuth 2.0 PKCE flow (RFC 7636) right in your browser, with verifier lengths from 43 to 128 characters. The page also shows ready-to-paste /authorize and /token request shapes so you can wire the values straight into Postman, curl, or your own SPA, mobile, or CLI client without leaving the tab.
💡 About this tool
PKCE is the mitigation for the authorization code interception attack against public OAuth 2.0 clients — SPAs, mobile apps, native CLIs, and anything else that cannot hold a client secret. The spec (RFC 7636) requires the client to generate a high-entropy code_verifier (43–128 characters from [A-Z][a-z][0-9]-._~), derive a code_challenge as base64url(SHA-256(verifier)), and pass the challenge to /authorize and the original verifier back to /token. The math is simple but tedious to do by hand every time you want to smoke-test an authorization server.
This tool reads from crypto.getRandomValues and crypto.subtle.digest('SHA-256') to produce a real spec-compliant pair on every slider move or Regenerate click, with full base64url encoding (no padding, +/ swapped for -_). The snippet panel below the values reproduces the exact request shapes:
GET /authorize?response_type=code&client_id=YOUR_CLIENT_ID&code_challenge=...&code_challenge_method=S256&redirect_uri=...&state=RANDOM_STATE
POST /token (form): grant_type=authorization_code&code=...&code_verifier=...
so you can paste the same verifier/challenge into Auth0, Okta, Keycloak, AWS Cognito, Azure AD B2C, or your own IdP and confirm the round-trip succeeds. Everything stays in the tab — no value is sent to any server — which makes it safe for staging tests, CTF challenges, and security trainings.
🧐 Frequently Asked Questions
Q. What verifier length should I pick? A. Anything from 43 to 128 characters is valid. Mainstream libraries (Auth0 SPA SDK, MSAL.js, AppAuth for Android/iOS) typically default to 43–64 characters. Start at 64 — if your authorization server accepts it the length is fine. Drop to 43 if log volume matters or go to 128 if you want maximum entropy for audit reports.
Q. Why is the plain method not offered?
A. RFC 7636 §4.2 marks S256 as MUST-support and plain as a fallback only when the client cannot compute SHA-256. In 2026 every mainstream authorization server (Auth0, Okta, Google, Microsoft, GitHub, Spotify, Twitch, X) requires S256, and the OAuth 2.1 draft removes plain entirely. The tool intentionally never emits plain to avoid wiring an insecure pair into your test.
Q. Will this work in older browsers without SubtleCrypto?
A. crypto.subtle.digest('SHA-256') is supported in every evergreen browser (Chrome, Edge, Firefox, Safari) and on https:// or localhost contexts. The tool runs in any modern dev environment but will silently fail on IE 11 or pages loaded over plain http:// outside localhost.
Q. Are the generated verifier and challenge stored anywhere? A. No. Each slider tick and Regenerate click produces a fresh pair, and nothing is persisted to local storage, cookies, or the server. Treat every pair as throwaway — reloading the page replaces them.
Q. What goes into the state parameter in the snippet?
A. state is your CSRF guard — generate a random string per session, store it server-side or in a secure cookie, and verify the callback hands the same value back. The snippet leaves RANDOM_STATE as a placeholder because state is the client's responsibility, not part of PKCE itself.
📚 Fun Facts
PKCE shipped in 2015 as RFC 7636 and was originally framed as a "native app extension" to OAuth 2.0. The 2019 OAuth 2.1 draft promoted it to "all clients always" and the major IdPs followed suit: Spotify deprecated Implicit Grant when they enforced PKCE on their Web API in 2021, Twitch did the same with their Helix API, and X (Twitter) made PKCE mandatory for v2 OAuth 2.0 in 2022. The code_challenge_method field theoretically supports anything an authorization server adds, but in practice only S256 and plain were ever standardized — and plain is on its way out, so a modern generator only needs to emit S256 to cover effectively the entire web.