OAuth 2.0 is a widely used authorization framework that allows applications to obtain limited access to user resources without handling user credentials directly. The Authorization Code Flow with PKCE (Proof Key for Code Exchange) is a security-enhanced version of the Authorization Code Flow, specifically designed to address vulnerabilities in public clients like mobile apps and single-page applications (SPAs) that cannot safely store a client secret.
Why PKCE Is Needed
Traditional Authorization Code Flow relies on a client_secret
to authenticate the client when exchanging an authorization code for a token. In public clients (like browser apps or mobile apps), this secret cannot be safely stored. Without proper safeguards, attackers could intercept the authorization code during redirection and exchange it for tokens.
PKCE mitigates this threat by introducing a one-time verification mechanism between the client and the authorization server that does not rely on a client secret, making the flow secure for public clients.
How Authorization Code Flow with PKCE Works
Here’s a step-by-step breakdown of the process:
1. Client Generates a Code Verifier and Code Challenge
- The code verifier is a cryptographically random string (43–128 characters).
- The code challenge is derived by applying a SHA256 hash (or using plain) to the code verifier and base64-url encoding the result.
code_verifier = "randomly_generated_string"
code_challenge = BASE64URL-ENCODE(SHA256(code_verifier))
2. Client Initiates Authorization Request
The client redirects the user to the authorization server’s /authorize
endpoint with the following parameters:
response_type=code
client_id
redirect_uri
scope
code_challenge
code_challenge_method=S256
GET /authorize?
response_type=code&
client_id=your-client-id&
redirect_uri=https://app.com/callback&
scope=openid profile email&
code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&
code_challenge_method=S256
3. User Authenticates and Grants Access
The user logs in and approves the authorization request. The authorization server redirects back to the redirect_uri
with an authorization code.
4. Client Sends Token Request
The client then sends a POST
request to the /token
endpoint including:
grant_type=authorization_code
code
(received in step 3)redirect_uri
(must match original)client_id
code_verifier
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=SplxlOBeZQQYbYS6WxSbIA&
redirect_uri=https://app.com/callback&
client_id=your-client-id&
code_verifier=randomly_generated_string
5. Authorization Server Validates Code Verifier
The server hashes the code_verifier
and compares it to the original code_challenge
. If they match, it returns:
access_token
id_token
(if OpenID Connect is used)refresh_token
(if applicable)
6. Client Uses Access Token
The client includes the access_token
in the Authorization: Bearer
header to access protected resources.
Security Advantages of PKCE
- Protects against authorization code interception
- Eliminates reliance on client secrets for public clients
- Recommended by the OAuth 2.1 draft for all client types
When to Use PKCE
- Mobile applications (iOS, Android)
- Single-page applications (SPA)
- Any client that cannot securely store a
client_secret
Conclusion
The Authorization Code Flow with PKCE represents a modern, secure way for public clients to participate in OAuth 2.0. By binding the authorization code to a dynamically generated key pair, PKCE eliminates a major vulnerability and strengthens trust in user authorization without requiring secret storage. As OAuth continues to evolve, PKCE is considered a best practice and should be the default choice for native and browser-based applications.