OAuth PKCE Verifier + Challenge
Gera code_verifier (43-128 chars) e code_challenge S256 (usa SubtleCrypto se disponível).
verifier + challenge
—
What PKCE is and why it exists
PKCE (Proof Key for Code Exchange, pronounced "pixy") is the OAuth 2.0 extension specified in RFC 7636 (2015) that hardens the Authorization Code flow for clients that cannot keep a secret — namely native mobile apps, desktop apps and single-page web applications. In a classical confidential client the server holds a client_secret baked into a backend that the user never sees, and that secret is what proves to the token endpoint that the redemption of an authorization code is legitimate. Public clients have no such hiding place: anything shipped with the binary can be extracted, anything in JavaScript is visible in DevTools. PKCE replaces the static client secret with a per-request proof.
Without PKCE, a public client is exposed to a code interception attack: a malicious app registered under the same custom URL scheme, or a compromised browser extension, can grab the authorization code from the redirect and exchange it for tokens before the legitimate app does. With PKCE, knowing the code is no longer enough — the attacker also needs the verifier, which never left the original client.
The verifier / challenge protocol
- The client generates a code_verifier: a high-entropy random string of 43 to 128 characters from the unreserved set
[A-Z a-z 0-9 - . _ ~]. Roughly 32 bytes of CSPRNG output base64url-encoded gives 43 characters and ~256 bits of entropy — the minimum recommended. - The client derives the code_challenge =
BASE64URL(SHA256(verifier))withcode_challenge_method=S256. Theplainmethod (challenge = verifier) is permitted by the RFC but discouraged and forbidden in OAuth 2.1. - The client sends
code_challengeon/authorize; the authorization server binds it to the issued code. - The client then calls
/tokenwith the code and the original verifier; the server checksSHA256(verifier) == stored_challengebefore issuing tokens.
Implementation notes
The verifier must be unique per authorization request — reusing it across flows defeats the proof and would let a leaked challenge be matched against a fresh code. Keep it in memory or in sessionStorage with a short TTL; never persist it long-term and never send it on the front channel. Mature libraries (oidc-client-ts, AppAuth for iOS/Android, pkce-challenge on npm, authlib in Python) handle the pairing for you. PKCE does not replace HTTPS — both legs of the flow must still run over TLS, otherwise a network attacker reads everything anyway.
PKCE vs the state parameter
PKCE is sometimes confused with the OAuth state parameter, but they solve different problems. state is a CSRF token: it binds the /authorize request to the eventual callback so an attacker cannot trick a victim into completing an attacker's flow. PKCE binds the token redemption to the original initiator: even with a stolen code, you cannot redeem it without the verifier. You want both on every public-client flow — they are complementary, not alternatives.
FAQ
Do I need PKCE on a backend web app that already has a client_secret? The original RFC 7636 marks it MUST for public clients and RECOMMENDED for confidential clients. The OAuth 2.1 draft promotes it to MUST for all clients regardless of type, on the grounds that the marginal cost is negligible and the defense is genuinely useful.
S256 or plain? Always S256. The plain method only exists for legacy embedded devices that cannot compute SHA-256, which in 2026 is essentially nothing. Most authorization servers refuse plain outright.
Can I reuse the same verifier? No. The whole guarantee collapses if the verifier is predictable or repeated. Generate a fresh 32-byte random value for every /authorize call.
What if the user opens two tabs of the same app at once? Each tab needs its own verifier; bind them per-state or per-tab in storage, otherwise the second redemption will fail.
Is the verifier here transmitted anywhere? No. Both the verifier and the challenge are computed in your browser via crypto.getRandomValues() and SubtleCrypto.digest — nothing is sent to a server.
Related Tools
Handwriting Generator
Convert typed text into an image with handwriting appearance. Useful for adding a personal touch to digital work.
Resume Generator
Fill a simple printable A4 CV from a form with personal data, education and experience.
Favicon Generator
Generate a favicon from text/emoji in all common sizes (16, 32, 48, 64, 192, 512). PNG download.