What is PKCE and why you should use it?
Using Authorization Code flow with OAuth 2.0 is a secure way to authenticate users and obtain access tokens. However, this flow is vulnerable to interception attacks, especially when used by public clients such as mobile or single-page applications.
To mitigate this risk, the Proof Key for Code Exchange (PKCE) extension was introduced to the OAuth 2.0 protocol.
What is the risk?
When using the Authorization Code flow, the client application exchanges an authorization code for an access token. This code is typically sent over a redirect URI from the authorization server to the client application. If an attacker intercepts this code, they can use it to obtain an access token, then impersonate the user.
What is PKCE?
PKCE (pronounced "pixy") is an extension to the OAuth 2.0 Authorization Code flow that provides additional security for public clients. It is designed to protect against code interception attacks by ensuring that the authorization code can only be exchanged for an access token by the client that initiated the authorization request.
How does PKCE work?
When a client initiates the Authorization Code flow with PKCE, it generate a code verifier and a code challenge. This code verifier is only know by the Relying Party and can be verified by the authorization code. This mechanism allows Authorization Server to verify the authorization code when exchanging it for tokens.
Here's how PKCE works in practice:
- Generate a Code Verifier: The client generates a high-entropy cryptographic random string called a code verifier.
code_verifier = "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
- Create a Code Challenge: The client then creates a code challenge derived from the code verifier. This is typically done using a SHA-256 hash of the code verifier, which is then base64-url-encoded.
code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))
- Authorization Request: The client includes the code challenge and the method used to create it (usually
S256
) in the authorization request to the authorization server.
GET /authorize?response_type=code&client_id=abcd1234&redirect_uri=https://mydomain.com/callback&code_challenge=CODE_CHALLENGE&code_challenge_method=S256
-
Authorization Server Response: The authorization server authenticates the user and returns an authorization code to the client.
-
Token Request: The client sends the authorization code along with the
code verifier
to the token endpoint.
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=https://mydomain.com/callback&client_id=abcd1234&code_verifier=CODE_VERIFIER
- Token Response: The authorization server verifies the
code verifier
against the code challenge and, if valid, issues an access token.
By using PKCE, the authorization code can only be exchanged for an access token by the client that initiated the request, thus mitigating the risk of interception attacks.