PKCE downgrade
16A server that silently accepts an unbound code can undo a client’s reliance on PKCE for CSRF protection.
Terms in this drawing
Related RFCs and changes
“Updates” changes part of an earlier RFC. “Obsoletes” replaces it. This list shows selected related documents.
DIAGRAM§ 4.8 ↗
RFC 9700 · § 4.8DEFENSE
3 / 3
03
Reject this inconsistent exchange.
A verifier must not be accepted for a code that had no challenge.
Protocol participantThreat or exceptionProtocol controlSimplified drawings · precise section references
RFC 6749 § 4.1RFC 9700 § 4.8.2
PKCE downgrade protection is explicit: a verifier must be rejected if the original authorization request contained no challenge.
Read the updated RFC section ↗A verifier requires a recorded challenge.
- Servers MUST bind the presence of the challenge to the issued code.
- If a challenge was supplied, enforce a correct verifier.
- If no challenge was supplied, a token request containing a verifier MUST be rejected. Mandating PKCE also enforces this protection.
The attacker removes a challenge in their own flow and injects the resulting unbound code into a victim’s flow. This does not require breaking TLS or editing the victim’s network traffic.
Read the RFC section ↗Diagrams simplify the RFC. Read the linked sections for complete requirements.
PrivacyAll chapters in this RFC
- OAuth overview
- Authorization code + PKCE
- Retire unsafe grants
- Prevent token replay
- Limit token privileges
- Authenticate the client
- Metadata, TLS & CORS
- The attacker model
- Redirect URI validation
- Referer header leakage
- Browser history leakage
- Authorization server mix-up
- Authorization code injection
- Access token injection
- Cross-site request forgery
- PKCE downgrade
- Leakage at resource servers
- Misuse of stolen tokens
- Open redirection
- 307 credential forwarding
- TLS termination & proxies
- Refresh token protection
- Client as resource owner
- Clickjacking
- In-browser messaging