OAuth PKCE Generator Online

Generate a PKCE code_verifier and its S256 code_challenge for an OAuth 2.0 or OpenID Connect authorization code flow, or paste a verifier and a challenge to check that they match. It is for developers wiring up sign-in in a single-page app, a mobile app or a CLI, and for anyone debugging an invalid_grant error from a token endpoint.

The verifier comes from your browser’s cryptographic random generator and is hashed with Web Crypto in this tab, so nothing is uploaded. DevPrix also builds the matching authorization URL and token request with placeholder values, and never puts the verifier in a share link.

PKCE pair

code_challenge · public, sent in the authorization request
—

BASE64URL(SHA-256(code_verifier)), no padding · code_challenge_method=S256

Treat the verifier as a one-time secretCreate a new verifier for every authorization request and keep it where only your client can read it (memory or session storage). Send it once, in the token request, and never put it in a URL, a log or this page’s share link.

1 · Authorization request

Authorization URL
—

2 · Token request

POST bodycode comes from the redirect
—

This is a public client (a browser or mobile app), so no client secret is sent. A confidential client also authenticates itself here, as its authorization server requires.

Waiting for a code_verifierProcessed locally

How to use it

  1. A code_verifier and its S256 code_challenge are generated when the page opens; press Generate (⌘↵) for a new pair, or paste your own verifier.
  2. Fill in your authorization endpoint, client_id, redirect_uri and scope to get the authorization URL and the token request.
  3. To debug a failed exchange, switch to Check a pair and paste the verifier and challenge your client used.

Related tools

JWT DecoderFormatURL ParserWeb & APISHA-256 Hash GeneratorGenerateBase64 Encoder & DecoderConvert

Next: decode the ID token or access token you get back in the JWT Decoder, or break the redirect back to your app into its parameters with the URL Parser.

What this tool does

PKCE (Proof Key for Code Exchange, RFC 7636) stops a stolen authorization code from being redeemed by anyone except the client that asked for it. Before redirecting the user, the client creates a random code_verifier of 43 to 128 characters from A–Z, a–z, 0–9 and - . _ ~ and sends only its code_challenge, BASE64URL(SHA-256(code_verifier)) without padding, in the authorization request, with code_challenge_method=S256. When it exchanges the code at the token endpoint it sends the verifier itself; the server hashes it and compares the result with the challenge it stored. The generator follows the RFC’s recipe: 32 random bytes from crypto.getRandomValues, base64url-encoded to 43 characters, with longer options up to 96 bytes (128 characters). A verifier you paste is checked against the RFC’s length and character rules. Check a pair recomputes the challenge and compares it exactly, as a server does, and names the usual mistakes: standard Base64 with + / and =, a hex-encoded hash, or the plain method by accident.

Example input and output

RFC 7636 Appendix B: verifier to S256 challenge
Input
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Output
code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
code_challenge_method=S256

This is the worked example from the RFC, so it is a good test vector for your own PKCE code. Load it with RFC example.

Check a pair: the challenge was encoded as standard Base64
Input
code_verifier:  dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
code_challenge: E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw+cM=
Output
The code_challenge is not valid
Remove the = padding: an S256 code_challenge is base64url without padding.
It contains + or /, so it is standard Base64. An S256 code_challenge uses base64url (- and _).
This is the right hash in standard Base64. Servers expect base64url without padding: replace + with -, / with _ and drop the =.
Expected code_challenge (S256): E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM

btoa() and most Base64 helpers produce standard Base64. Converting the result to base64url fixes it.

The authorization URL for that challenge
Input
Authorization endpoint: https://auth.example.com/authorize
client_id: example-client-id
redirect_uri: https://app.example.com/callback
scope: openid profile
state: af0ifjsldkj
Output
https://auth.example.com/authorize?response_type=code&client_id=example-client-id&redirect_uri=https%3A%2F%2Fapp.example.com%2Fcallback&scope=openid%20profile&state=af0ifjsldkj&code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&code_challenge_method=S256

The URL carries the challenge, never the verifier. The verifier goes only in the token request body, after the user comes back with a code.

Common errors and fixes

invalid_grant from the token endpoint (PKCE verification failed)
The code_verifier you sent does not hash to the code_challenge from the authorization request. Usually the client generated a new verifier after the redirect, lost it on a page reload, or read it from storage in another tab. Store the verifier before redirecting and read the same one back in the callback; Check a pair shows whether the two values belong together.
Character 32 is “+”, which a code_verifier can’t contain
The verifier was made with standard Base64, which uses + / and =. A verifier may contain only A–Z, a–z, 0–9 and - . _ ~, so encode the random bytes as base64url: replace + with -, / with _ and drop the = padding.
Too short: 34 characters. A code_verifier must be 43 to 128 characters long.
RFC 7636 sets 43 characters as the minimum. Base64url-encode 32 random bytes to get exactly 43 characters, or more bytes for a longer verifier.
An S256 code_challenge is always 43 characters
A SHA-256 hash is 32 bytes, which is 43 characters in base64url without padding. A 44-character value ending in = still has padding, and a 64-character value is the hash in hex. Encode the raw hash bytes as base64url.
invalid_request: code challenge required
The authorization server requires PKCE for this client and the request had no code_challenge (RFC 7636 §4.4.1). Add code_challenge and code_challenge_method=S256 to the authorization URL.
invalid_request: transform algorithm not supported
The server does not accept the code_challenge_method you sent. Use S256, which every PKCE server must support. Don’t fall back to plain after S256 fails: RFC 7636 §7.2 forbids that downgrade, because an error here points to a faulty server or an attacker.

Common use cases

  • Testing an OAuth 2.0 or OpenID Connect authorization code flow by hand in a browser, Postman or curl
  • Debugging invalid_grant errors when the token endpoint rejects a code_verifier
  • Checking that a client library produces the right S256 code_challenge
  • Creating fixed test vectors for unit tests of PKCE code
  • Learning how PKCE protects single-page apps, mobile apps and CLIs that can’t keep a client secret

Privacy and security notes

  • The verifier is made with crypto.getRandomValues and hashed with Web Crypto in this browser tab. Nothing you generate or paste is sent to DevPrix or stored on a server.
  • Share copies a link without your values, and Send to is not offered: the verifier is never placed in a URL. Reloading the page creates a new pair.
  • Values you copy from here are for testing. In production the client generates the verifier for each sign-in and discards it after the token request.

Frequently asked questions

Why do I need PKCE?

An authorization code travels through the browser, where it can leak through logs, history or a malicious app registered for the same redirect URI. PKCE binds the code to the client that started the flow, so a stolen code is useless without the verifier. The OAuth 2.0 Security Best Current Practice (RFC 9700) says public clients MUST use PKCE and recommends it for confidential clients too.

Why S256 and not plain?

With plain, the challenge is the verifier itself, so anyone who can read the authorization request can redeem the code. RFC 7636 says plain SHOULD NOT be used in new implementations, and RFC 9700 says clients SHOULD use a method that does not expose the verifier; currently S256 is the only one. Use plain only if a server cannot support S256.

How long should the code_verifier be?

Between 43 and 128 characters. RFC 7636 recommends 32 random bytes encoded as base64url, which gives 43 characters and 256 bits of randomness. That is already far beyond guessing; longer verifiers are allowed but add little.

Does PKCE replace the state parameter?

It can protect against cross-site request forgery, but only if you know the authorization server supports PKCE; otherwise state or the OpenID Connect nonce must do that job (RFC 9700 §4.7.1). Many apps keep a random state anyway, which is why the example request includes one.

Where should my app keep the verifier?

Somewhere only your client can read until the callback: memory, sessionStorage in a single-page app, or the app’s private storage on mobile. Delete it after the token request, and create a new one for every authorization request.