Devkitr
Encoding & Security

PKCE Explained — Securing OAuth 2.0 Authorization Code Flow

2026-03-109 min readby Kashif

PKCE (Proof Key for Code Exchange, pronounced "pixie") is a security extension for OAuth 2.0 that prevents authorization code interception attacks. It is defined in RFC 7636 and is required for all public OAuth 2.0 clients — including Single-Page Applications (SPAs) and mobile apps.


The Problem PKCE Solves


In the OAuth 2.0 authorization code flow, after a user authenticates with an identity provider, the provider redirects back to your application with an authorization code. On mobile devices and desktops, a malicious app registered for the same redirect URI could intercept this code and exchange it for an access token.


PKCE eliminates this risk by proving that the app that started the authorization request is the same app that completes the token exchange.


How PKCE Works


PKCE introduces two values generated by the client:


1. code_verifier

A cryptographically random string of 43–128 characters using the unreserved characters [A-Z a-z 0-9 - . _ ~]. Generated using a cryptographically secure random number generator.


code_verifier = base64url(random_bytes(32))

// Example: "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"


2. code_challenge

A SHA-256 hash of the code_verifier, base64url-encoded:


code_challenge = base64url(SHA256(code_verifier))

// Example: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM"


The PKCE Flow Step by Step


Step 1 — Client generates the PKCE pair

Before redirecting to the authorization server, your app generates a code_verifier and computes the code_challenge.


Step 2 — Authorization request includes code_challenge

GET https://auth.example.com/authorize?

response_type=code&

client_id=your_client_id&

redirect_uri=https://app.example.com/callback&

code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&

code_challenge_method=S256&

scope=openid profile


Step 3 — Server stores the code_challenge

The authorization server stores the code_challenge alongside the generated code.


Step 4 — User authenticates and app receives the code

The server redirects back: https://app.example.com/callback?code=abc123


Step 5 — Token exchange includes code_verifier

POST https://auth.example.com/token

Content-Type: application/x-www-form-urlencoded


grant_type=authorization_code&

code=abc123&

redirect_uri=https://app.example.com/callback&

client_id=your_client_id&

code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk


Step 6 — Server verifies by recomputing the hash

The authorization server computes SHA256(code_verifier) and confirms it matches the stored code_challenge. If they match, it returns the access token.


A stolen code is useless without the original code_verifier.


When to Use PKCE


  • Always for SPAs (browser-based apps with no server-side component)
  • Always for native mobile apps (iOS, Android)
  • Recommended for all authorization code flows (the OAuth 2.1 draft mandates PKCE for all clients)

  • PKCE vs Client Secret


    | | Client Secret | PKCE |

    |---|---|---|

    | Suitable for SPAs | ❌ (secret would be exposed) | ✅ |

    | Suitable for mobile | ❌ | ✅ |

    | Server-side apps | ✅ | ✅ (use both) |

    | Replaces client secret | ❌ | For public clients only |


    Generating PKCE Values


    Use our free PKCE Generator to instantly generate a cryptographically secure code_verifier and code_challenge pair — both computed entirely in your browser using the Web Crypto API.


    Related Articles

    Back to Blog