Proof Key for Code Exchange (PKCE)

OAuth 2.0 public clients utilizing the Authorization Code Grant are susceptible to the authorization code interception attack. This specification describes the attack as well as a technique to mitigate the threat through the use of Proof Key for Code Exchange (PKCE, pronounced "pixy").

Uses Proof Key for Code Exchange (PKCE) instead of a client secret. A one-time key is generated by the client and sent with each request. Instead of proving the identity of a client, this ensures that only the client that requested the token can redeem it.

PKCE can be configured on the oauth2 client, and the possible values can be seen in the table below:

ValueDescription
noneThis means that PKCE flow is disabled
anyPKCE is enforced, but the method is selected based on the parameter in the request. This mode can be used to be compliant with RFC7636 indicating "plain" to be the default if the method is not provided in the request.
S256PKCE is enforced with 'S256' method

Why do we need PKCE?

There are two types of clients in OAuth 2.0. Confidential clients and public clients. “Confidential clients are clients who have the capability of maintaining the confidentiality of their credentials. Public clients are clients who don't have the capability of maintaining the confidentiality of their credentials.” In other words, a public client can't be trusted with credentials since it has no means of keeping them safe from misuse.

Public clients are defenseless against authorization code inspection attacks specially when the communication path is not protected by Transport Layer Security(TLS). Attackers can easily get the authorization code from the authorization endpoint and they can use it to obtain access token subsequently gaining access to data they shouldn't be allowed access to.

Example of requests with all PKCE options

Code challenge method none

As mentioned above, none, means that PKCE support is disabled, and therefore the normal OAuth 2.0/OIDC flow is performed

Example of requests:

Authorize request:

CURL
Copy

If the user is logged in at OP (openID provider), the user will be redirected back to the SP (service provider) application, with the code, otherwise it will be redirected back to the OP login page. Assuming that the user already has a session at OP, he/she will be redirected back to the SP application, and the next request will be the below one:

Token request:

CURL
Copy

Please note that you need to pass client_secret when using a client registered with code_challenge_method=none

Code challenge method S256

In this flow, the client has to create the a random string and hashes it and encodes it using the following formula code_challenge=BASE64URL-ENCODE(SHA256(ASCII(code_verifier))). This string is sent in the authorization request in a new query parameter called code_challengealong with the code_challenge method which specifies the method used for creating the code challenge.

Example of requests:

Authorization request:

CURL
Copy

Please note that the code_challenge_method is optional, and if it's not explicitly set to S256, it will default to plain, and this can cause issues when exchanging the code for getting an access token because the request will fail as the code verifier will not match with the code challenge.

If the user is logged in at OP (openID provider), the user will be redirected back to the SP (service provider) application, with the code, otherwise it will be redirected back to the OP login page. Assuming that the user already has a session at OP, he/she will be redirected back to the SP application, and the next request will be the below one:

Token request:

CURL
Copy

The request contains the code_verifier query parameter, which substitutes the client_secret. Once OP will receive this request, it will verify the code verifier, by applying the formula mentioned above, and verify if the hashed match. If the hashes are matching, assuming that all the other attributes are correct, it will issue an access token.

Code challenge method plain

Using the code challenge plain implies not hashing the code challenge, and therefore, in this situation, the following formula will apply: code_challenge = code_verifier

Example of requests:

Authorization request:

CURL
Copy

If the user is logged in at OP (openID provider), the user will be redirected back to the SP (service provider) application, with the code, otherwise it will be redirected back to the OP login page. Assuming that the user already has a session at OP, he/she will be redirected back to the SP application, and the next request will be the below one:

Token request:

CURL
Copy
Type to search, ESC to discard
Type to search, ESC to discard
Type to search, ESC to discard
  Last updated by Stein Welberg