PKCE โ Proof Key for Code Exchange
Last updated: April 2026
PKCE (pronounced "pixie") is an OAuth 2.0 extension that helps protect against authorization code interception attacks. It is required for public clients (SPAs and mobile apps) and recommended for all OAuth flows in OAuth 2.1.
How PKCE works
# 1. App generates a random code_verifier code_verifier = base64url(random(32 bytes)) # Example: dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk # 2. App creates code_challenge from verifier code_challenge = base64url(sha256(code_verifier)) # Example: E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM # 3. App sends code_challenge to authorization endpoint GET /authorize ?code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM &code_challenge_method=S256 &... # 4. Server stores code_challenge with the auth code # 5. App sends code_verifier when exchanging code for token POST /token code=AUTH_CODE &code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk &... # 6. Server verifies: sha256(code_verifier) == stored code_challenge
Enable PKCE in common providers
Auth0: Application Settings โ Grant Types โ enable Authorization Code (PKCE). Use auth0-react or auth0-spa-js SDK.
Okta: Application โ Sign-On Policy โ enable PKCE. Set pkce: true in OktaAuth config.
Cognito: App client โ Auth flows โ enable PKCE. Set in Amplify config.
JavaScript implementation
async function generatePKCE() {
const verifier = crypto.getRandomValues(new Uint8Array(32));
const challenge = await crypto.subtle.digest('SHA-256', verifier);
return {
code_verifier: btoa(String.fromCharCode(...verifier))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''),
code_challenge: btoa(String.fromCharCode(...new Uint8Array(challenge)))
.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, ''),
};
}