Back to 20 Concepts
oauth-oidcAdvanced

OAuth 2.0 Authorization Code Flow with PKCE (Proof Key for Code Exchange)

PKCE eliminates the need for client secrets in public Single Page Apps (React/Next.js) and Mobile Apps. The client generates a random Code Verifier and sends its SHA-256 Code Challenge; the authorization server verifies the hash on token exchange.

Intuitive Mental Model

The Tamper-Evident Half-Ticket: Before sending a messenger to pick up your concert pass, you rip a ticket in half (Code Verifier) and give the box office a photo of the unique jagged rip line (Code Challenge). When the messenger arrives with the authorization code, only the person presenting the matching half-ticket can claim the real wristband.

Architecture Blueprint & CodeProduction Standard
// 1. Client generates high-entropy random string (Code Verifier):
const codeVerifier = generateRandomString(64);

// 2. Client computes SHA-256 hash (Code Challenge):
const codeChallenge = base64UrlEncode(sha256(codeVerifier));

// 3. User redirects to Auth0/Google with challenge:
// GET /authorize?response_type=code&client_id=...&code_challenge=${codeChallenge}&code_challenge_method=S256

// 4. Client exchanges received Auth Code + Verifier for Tokens:
// POST /oauth/token { code: "auth_code_123", code_verifier: codeVerifier }

Key Architectural Takeaways

  • Eliminates Client Secrets in Browsers: Public web clients cannot safely store a client secret; PKCE prevents authorization code interception attacks.
  • S256 Challenge Method: Always use SHA-256 hashing (code_challenge_method=S256) rather than plain text.
  • Industry Mandate: OAuth 2.1 officially deprecates the legacy Implicit Flow in favor of Authorization Code with PKCE.
Common Architectural Pitfall

Using the legacy OAuth 2.0 Implicit Grant flow (tokens returned directly in URL hash fragments), exposing access tokens in browser history and Referer headers.

Production Best Practice

Always use Authorization Code Flow with PKCE for all Single Page Apps and mobile clients.