Proof Key for Code Exchange (PKCE) has become a critical enhancement to the OAuth 2.0 Authorization Code Flow, especially for public clients such as mobile and single-page applications. By adding a cryptographically secure verification step, PKCE significantly reduces risks like authorization code interception and replay attacks.
What is PKCE and Why Was It Introduced?
Originally designed for native and public clients unable to securely store a client secret, PKCE addresses a fundamental security gap in OAuth 2.0. It prevents attackers from stealing authorization codes and exchanging them for access tokens because the authorization code is bound to a one-time generated secret known only to the client.
How PKCE Works
PKCE introduces two parameters:
- code_verifier: A high-entropy cryptographic random string generated by the client.
- code_challenge: A hashed (SHA-256) and base64-url-encoded version of the code_verifier, sent during the authorization request.
Flow steps:
- The client generates the code_verifier and computes the code_challenge.
- The client sends the code_challenge in the authorization request.
- After the user authenticates, the authorization server issues an authorization code.
- The client sends the authorization code along with the original code_verifier to the token endpoint.
- The server verifies the code_verifier matches the original code_challenge and, if valid, issues tokens.
PKCE Authorization Request Example
GET /authorize?
response_type=code&
client_id=your_client_id&
redirect_uri=https://yourapp.com/callback&
code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM&
code_challenge_method=S256
Token Request Example with Code Verifier
POST /token HTTP/1.1
Host: authorization-server.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&
code=SplxlOBeZQQYbYS6WxSbIA&
redirect_uri=https://yourapp.com/callback&
client_id=your_client_id&
code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk
Benefits of Using PKCE
- Eliminates the need for a client secret on public clients, enabling secure flows on mobile and browser-based apps.
- Protects against interception of authorization codes by malicious actors.
- Complies with OAuth 2.1 recommendations, which mandate PKCE for all Authorization Code Flow implementations.
Real-World Adoption
- Major identity providers like Google, Microsoft, and Okta require PKCE for native and SPA apps.
- ForgeRock Identity Cloud supports PKCE to enhance security on hosted login journeys.
- Mobile SDKs and OAuth client libraries increasingly embed PKCE support by default.
Security Considerations and Best Practices
- Always use
S256
as thecode_challenge_method
for better security. - Generate high-entropy, cryptographically random code_verifiers.
- Never reuse code_verifiers; they must be unique per authorization request.
- Combine PKCE with HTTPS to protect data in transit.
Reflective Questions
- How does your current OAuth client implementation handle PKCE?
- Are there legacy applications that need migration to PKCE-enabled flows?
- How can your security policies enforce PKCE usage in your OAuth infrastructure?
Conclusion
PKCE is no longer optional but essential for securing Authorization Code Flow, particularly in the era of public clients like SPAs and mobile apps. Implementing PKCE protects users and applications against critical attack vectors and aligns your system with modern OAuth 2.1 standards.
👉 Related: Understanding the Authorization Code Flow in OAuth 2.0
👉 Related: Understanding the Authorization Code Flow with PKCE in OAuth 2.0