Overview#Proof Key for Code Exchange by OAuth Public Clients specification defined in RFC 7636 adds additional parameters to the OAuth 2.0 Authorization Request and Access Token Requests.
OAuth 2.0 OAuth Public Clients utilizing the Authorization Code Grant are susceptible to the authorization code interception attack. Proof Key for Code Exchange by OAuth Public Clients specification describes the attack as well as a technique to mitigate against the threat through the use of Proof Key for Code Exchange (PKCE, pronounced "pixy").
Proof Key for Code Exchange by OAuth Public Clients extension utilizes a dynamically created cryptographically random key called "code_verifier".
A unique Code_verifier is created for every authorization Request, and its transformed value, called "code_challenge", is sent to the Authorization Server to obtain the Authorization Code. The Authorization Code obtained is then sent to the Token_endpoint with the "code verifier", and the Authorization Server compares it with the previously received request code so that it can perform the Proof-of-Possession of the "code verifier" by the client. This works as the mitigation since the attacker would not know this one-time key, since it is sent over TLS and cannot be intercepted.
"how (PKCE) would mitigate the issue where the browser-based app can't store the client secret securely"#Because there are no Client Secrets using PKCE.
PKCE works by having the application generate a random the unique string value at the beginning of the flow called a code_verifier. The Application hashes the code_verifier and the result is called the code_challenge. The Application then kicks off the Authorization Code Flow, EXCEPT without the Client Secret but includes the code_challenge in the query string for the Authorization Request to the Authorization Server.
3. Terminology#In addition to the terms defined in OAuth 2.0 RFC 6749, this specification defines the following terms:
- code_verifier - A cryptographically random string that is used to correlate the Authorization Request to the Access Token Requests.
- code_challenge - A challenge derived from the code verifier that is sent in the Authorization Request, to be verified against later.
- Base64url Encoding - Base64 encoding using the URL- and filename-safe character set defined in Section 5 of RFC 4648, with all trailing '=' characters omitted (as permitted by Section 3.2 of RFC 4648) and without the inclusion of any line breaks, whitespace, or other additional characters.
4.1. OAuth Client creates a code verifier#The OAuth Client first creates a code_verifier, "code_verifier", for each OAuth 2.0 RFC 6749 Authorization Request
4.2. OAuth Client creates the code_challenge#The OAuth Client then creates a code_challenge derived from the code_verifier
4.3. OAuth Client sends the code challenge with the Authorization Request#The client sends the code_challenge as part of the OAuth 2.0 Authorization Request (Section 4.1.1 of RFC 6749.) Authorization Server issues the Authorization Code in the Authorization Response, it MUST associate the code_challenge and code_challenge_method values with the Authorization Code so it can be verified later.
Typically, the code_challenge and code_challenge_method values are stored in encrypted form in the "code" itself, but could alternatively be stored on the server, associated with the code. The server MUST NOT include the code_challenge value in client requests in a form that other entities can extract.
4.4.1. Error Response If the server requires Proof Key for Code Exchange by OAuth Public Clients (PKCE) by OAuth Public Clients, and the OAuth Client does not send the code_challenge in the request, the Authorization_endpoint MUST return the authorization error response with "error" value set to "invalid_request". The "error_description" or the response of "error_uri" SHOULD explain the nature of error, e.g., Code_challenge required.
If the server supporting PKCE does not support the requested transform, the authorization endpoint MUST return the authorization error response with "error" value set to "invalid_request". The "error_description" or the response of "error_uri" SHOULD explain the nature of error, e.g., transform algorithm not supported.
4.5. Client sends the Authorization Code and the Code Verifier to the Token_endpoint#Upon receipt of the Authorization Code, the client sends an Access Token Request to the Token_endpoint.
4.6. Server verifies code_verifier before returning the tokens#Upon receipt of the request at the Token_endpoint, the server verifies it by calculating the code_challenge from received code_verifier and comparing it with the previously associated code_challenge, after first transforming it according to the code_challenge_method method specified by the client.
code_challenge = base64url.encode(crypto.createHash('sha256').update(code_verifier).digest());
If the "code_challenge_method" from Section 4.2 was "plain", they are compared directly. i.e.,
"code_verifier" == "code_challenge".
5. Compatibility#Server implementations of this specification MAY accept OAuth Clients that do not implement this extension. If the code_verifier is not received from the OAuth Client in the Authorization Request, servers supporting backwards compatibility revert to a normal OAuth 2.0 RFC 6749 protocol.
As the OAuth 2.0 RFC 6749 server responses are unchanged by this specification, client implementations of this specification do not need to know if the server has implemented this specification or not, and SHOULD send the additional parameters as defined in Section 3. to all servers.OAuth 2.0 Security Best Current Practice (BCP)it has been proposed to make PKCE REQUIRED.
PKCE solves two problems:
- stolen authorization_codes for OAuth Public Clients
- authorization_codes injection for all OAuth Clients
The section of the OAuth 2.0 Security Best Current Practice BCP (4.5.3). Proposed Countermeasures) which says clients can do PKCE or use the nonce, is only talking about preventing authorization_code injection.
The nonce parameter solves authorization code injection if the client requests an Id_token. OAuth Public Clients using the nonce parameter are still susceptible to stolen authorization_codes so they still need to do PKCE as well.
The only case where OpenID Connect clients do not benefit from PKCE is if they are also OAuth Confidential Clients. OAuth Public Clients (even OIDC clients) still need to do PKCE even if they check the nonce.
More Information#There might be more information for this subject on one of the following:
- Access Token Request
- Authorization Request Parameters
- Authorization Response
- Best Practices OpenID Connect
- OAuth 2.0 Security Best Current Practice
- OAuth 2.0 for Native Apps
- OAuth Parameters Registry
- OAuth Public Client
- Proof Key for Code Exchange by OAuth Public Clients
- Proof-of-Possession Key Semantics for JSON Web Tokens (JWTs)
- RFC 7636
- Web Blog_blogentry_150617_1
- Web Blog_blogentry_310715_1