We previously discussed how the Authorization Code flow is secure because the token exchange happens on a back-channel. But what if there is no back-channel? For mobile apps or SPAs, the 'Client Secret' cannot be stored securely. This is where PKCE (pronounced 'pixie') comes in.
In a standard flow on a mobile device, the Authorization Code is delivered via a custom URI scheme (e.g., `myapp://callback`). A malicious app on the same device could register that same scheme and intercept the code.
PKCE prevents this by requiring the client to prove it is the same entity that requested the code, without needing a static secret.
// 1. Generate a random 'Code Verifier'
const verifier = generateRandomString(64);
// 2. Create 'Code Challenge' (S256)
const challenge = base64UrlEncode(sha256(verifier));
// 3. Send challenge in the initial request
const authUrl = `...&code_challenge=${challenge}&code_challenge_method=S256`;The client sends the *challenge* during the initial request. The server stores this challenge and associates it with the issued authorization code.
๐ก The magic happens at the end. The client must send the original raw 'Code Verifier' when exchanging the code for the token.
The server hashes the provided `code_verifier` and checks if it matches the `code_challenge` sent earlier. If it matches, it proves the requester is the original client.
| Feature | Standard Auth Code | Auth Code + PKCE |
|---|---|---|
| Secret Storage | Required (Client Secret) | Not Required |
| Client Type | Confidential (Backend) | Public (Mobile/SPA/Backend) |
| Interception Risk | Vulnerable on Mobile | Protected |
| Verification | Secret-based | Challenge/Verifier-based |
Modern security standards (OAuth 2.1) mandate PKCE for all clients, even those with a backend. It adds a layer of defense-in-depth that protects against code injection and interception.
Do not use the 'plain' method for `code_challenge_method`. It provides almost no security benefit over the standard flow.
Verify exercises to earn โ 230 XP and unlock next lab level.