How OAuth 2.0 PKCE Works
IntermediatePKCE (Proof Key for Code Exchange) hardens the OAuth 2.0 authorization code flow against interception attacks. The flow exchanges a temporary authorization code for tokens, but on public clients — single-page apps and mobile apps that cannot keep a secret — an attacker who steals the code could redeem it. PKCE fixes this: the client generates a random secret (the code verifier), sends only a hash of it (the challenge) up front, and proves it holds the original when redeeming the code. It is now recommended for all clients.
Think of a locker with a claim check you keep
You store a bag and get a claim ticket (the authorization code). Normally anyone with the ticket could grab your bag. With PKCE, when you drop the bag you also whisper a secret word and hand over only its scrambled form. When you return with the ticket, you must say the original secret word to prove you are the same person. A thief who steals your ticket cannot collect the bag, because they never knew the secret word.
Step by Step
Key Concepts
Code Verifier
A cryptographically random secret the client generates and keeps private. It is presented when redeeming the authorization code to prove the client identity.
Code Challenge
A SHA-256 hash of the verifier, sent at the start of the flow. Because it is one-way, it can travel through the browser safely — an attacker cannot derive the verifier from it.
Public vs Confidential Client
A confidential client (a backend) can safely store a client secret; a public client (SPA, mobile app) cannot. PKCE gives public clients equivalent protection without needing a stored secret.
Authorization Code Interception
The attack PKCE defends against: stealing the temporary authorization code from a redirect. Without PKCE, the thief could exchange it for tokens; with PKCE, they lack the verifier.
Key Facts
- PKCE was designed for public clients (mobile and single-page apps) but the OAuth 2.1 guidance now recommends it for all clients, including confidential ones.
- The code challenge is a one-way hash, so it can safely pass through the browser and redirect URL where an attacker might see it.
- PKCE replaced the deprecated OAuth implicit flow, which returned tokens directly in the URL and was inherently less secure.
Real-World Applications
Login in a single-page app
A React or mobile app uses the authorization code flow with PKCE to log users in via an identity provider, getting tokens securely without embedding a client secret that could be extracted from the app.
Native mobile authentication
A mobile app registers a custom redirect and uses PKCE so that even if another app on the device intercepts the redirect and its code, it cannot exchange the code without the verifier held by the legitimate app.
Frequently Asked Questions
What is PKCE in OAuth 2.0?
PKCE (Proof Key for Code Exchange) is an extension to the OAuth 2.0 authorization code flow that protects against authorization code interception. The client generates a random secret called the code verifier and sends only its hash (the code challenge) when starting the flow. When it later exchanges the authorization code for tokens, it must present the original verifier, which the server checks against the stored challenge. This proves the client is the one that started the flow.
Why do public clients need PKCE?
Public clients like single-page apps and mobile apps run on devices the user controls, so they cannot safely store a client secret — it could be extracted from the app or its source. Without a secret, an attacker who intercepts the authorization code (from a redirect or a malicious app) could exchange it for tokens. PKCE provides equivalent protection without a stored secret: the attacker also needs the code verifier, which never leaves the legitimate client.
What is the difference between the code verifier and the code challenge?
The code verifier is a cryptographically random secret string the client generates and keeps private. The code challenge is a SHA-256 hash of that verifier, sent at the start of the flow. Because the challenge is a one-way hash, it can safely travel through the browser and redirect URL — an attacker who sees it cannot reverse it to obtain the verifier, which is required to redeem the authorization code.
How does PKCE stop authorization code interception?
The authorization server ties the issued code to the code challenge it received at the start. When the code is exchanged for tokens, the client must send the original code verifier, which the server hashes and compares to the stored challenge. An attacker who intercepts the authorization code cannot complete the exchange because they do not possess the verifier, and they cannot derive it from the one-way challenge. So the stolen code is useless.