Proof Key for Code Exchange by OAuth Public Clients
Extracted elements (18)
OAuth 2.0 public clients using the Authorization Code Grant are susceptible to authorization code interception attacks, where a malicious app registered with the same custom URI scheme can intercept the authorization code returned via the redirect URI and use it to obtain an access token. PKCE mitigates this by binding the authorization code to a dynamically created cryptographic secret (code_verifier) that the attacker does not possess.
Salting is intentionally omitted from the code_challenge production because the code_verifier already contains sufficient entropy (256 bits) to prevent brute-force attacks. Unlike passwords, the code_verifier's high entropy makes salt unnecessary for security, and modern GPUs can compute SHA-256 hashes faster than dictionary lookups anyway.
The 'plain' transformation method exists solely for compatibility with existing deployments and constrained environments that cannot perform SHA-256 hashing. It provides no protection against eavesdroppers who can observe the authorization request, unlike S256.
Server implementations MAY accept OAuth 2.0 clients that do not implement PKCE, reverting to standard OAuth 2.0 behavior when code_verifier is absent. Clients implementing PKCE SHOULD send the additional parameters to all servers regardless of whether the server supports PKCE.
At the token endpoint, the client MUST send the code_verifier as an additional REQUIRED parameter along with the authorization code.
If the client is capable of using 'S256', it MUST use 'S256', as 'S256' is Mandatory To Implement (MTI) on the server. Clients are permitted to use 'plain' only if they cannot support 'S256' for some technical reason and know via out-of-band configuration that the server supports 'plain'.
If the server requires PKCE and the client does not send code_challenge, the authorization endpoint MUST return an error response with 'error' set to 'invalid_request'. If the server does not support the requested transformation, it MUST also return 'invalid_request'.
The client sends code_challenge (REQUIRED) and code_challenge_method (OPTIONAL, defaults to 'plain') as additional parameters in the OAuth 2.0 Authorization Request.
The code_verifier SHOULD have enough entropy to make it impractical to guess. It is RECOMMENDED that a suitable random number generator produce a 32-octet sequence, which is then base64url-encoded to a 43-octet URL-safe string.
The token endpoint MUST use the code_challenge_method bound to the authorization code to verify the code_verifier. If the computed challenge equals the stored code_challenge, processing continues normally; otherwise, the server MUST return an 'invalid_grant' error.
When the server issues the authorization code, it MUST associate the code_challenge and code_challenge_method values with the authorization code so they can be verified later. The server MUST NOT include the code_challenge value in client requests in a form that other entities can extract.
The code_challenge is derived from the code_verifier using either the 'plain' method (code_challenge = code_verifier) or the 'S256' method (code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))). ABNF: code-challenge = 43*128unreserved.
The code_verifier is a high-entropy cryptographic random string using unreserved characters [A-Z]/[a-z]/[0-9]/"-"/"."/"_"/"~" with a minimum length of 43 characters and a maximum length of 128 characters, created fresh for each authorization request. ABNF: code-verifier = 43*128unreserved.
This specification establishes the 'PKCE Code Challenge Methods' registry as a sub-registry of 'OAuth Parameters', using Specification Required policy. Initial entries are 'plain' and 'S256', both defined in Section 4.2 of RFC 7636.
Three new parameters are registered in the IANA 'OAuth Parameters' registry: code_verifier (token request), code_challenge (authorization request), and code_challenge_method (authorization request), all with change controller IESG.
Clients MUST NOT downgrade from 'S256' to 'plain' after a failure, as an error when 'S256' is presented can only mean the server is faulty or a MITM attacker is performing a downgrade attack. The 'plain' method SHOULD NOT be used in new implementations.
If code_challenge_method is 'plain' and the code_challenge is stored inside the authorization code for a stateless server, it MUST be encrypted such that only the server can decrypt it, to prevent disclosure of the code_verifier equivalent.
The code_verifier SHOULD be created with a minimum of 256 bits of entropy using a cryptographically random number generator producing a 32-octet sequence base64url-encoded. The security model relies entirely on the attacker's inability to guess or learn the code_verifier.