Skip to content
Agent Identity

IETF · September 2015

Proof Key for Code Exchange by OAuth Public Clients

RFC 7636

N. Sakimura, J. Bradley, N. Agarwal

RFCStableAuthenticationFoundationField guide

An agent that opens a browser (or a loopback redirect) to get user consent is a public or at-best confidential client in a hostile environment. PKCE is the difference between 'the code in the redirect is enough' and 'only the process that started the flow can finish it'.

At a glance

Problem
Public clients (native apps, many SPAs, many agents) cannot keep a client secret. An attacker who intercepts the authorization code can otherwise redeem it.
Identity / authn / authz
Protects the authorization-code redemption step (a form of client-to-AS authentication of the token request). Does not identify the user.

Actors

  • Public or confidential client
  • Authorization server

01

The gap for agents

Public clients cannot keep a client secret. An attacker who intercepts the authorization code — custom URI schemes, referrer leakage, a malicious app on the device, a compromised agent helper — can redeem it. PKCE binds redemption to the process that started the request.

Agents that open a browser, a loopback redirect, or a device-code-adjacent window are in this threat model even if someone labelled them 'confidential' in a portal. OAuth 2.1 and RFC 9700 require PKCE for authorization-code clients including confidential ones, because authorization-code injection is not only a native-app problem.

02

Actors and trust boundaries

The authorization code travels through the user-agent. The code_verifier never does: it stays in the client and appears only on the token-endpoint back channel. The AS is trusted to store the challenge and compare. The RS never sees PKCE parameters.

03

Mechanics

Client creates a high-entropy code_verifier. code_challenge = BASE64URL(SHA256(verifier)) with code_challenge_method=S256. Authorization request carries the challenge; token request carries the verifier. AS accepts the code only if SHA256(verifier) matches. RFC 7636 also defined plain; OAuth 2.1 prohibits it.

Generate a new verifier per authorization request. Do not log verifiers. Pair with exact redirect matching and, for mix-up, RFC 9207 iss.

code_challenge_method=S256from spec
Quoted as the only method OAuth 2.1 keeps. plain is prohibited.
code_verifierfrom spec
Quoted RFC 7636: cryptographically random string, sent only to the token endpoint.

04

Step-by-step flows

Flow 1

PKCE on authorization code

  1. 1

    Client generates code_verifier, derives S256 code_challenge.

  2. 2

    Authorization request includes code_challenge and code_challenge_method=S256.

  3. 3

    After redirect, token request includes code and code_verifier (plus client auth if any).

  4. 4

    AS recomputes S256 and compares. Mismatch → invalid_grant.

05

Identity vs authentication vs authorization

Protects the authorization-code redemption step — client-to-AS authentication of the token request, not user identity. Authorization of the API remains the access token.

06

How it composes

  • OAuth 2.1

    Folded into the core grant.

  • OAuth for native apps

    RFC 8252 required PKCE for native apps; 2.1 generalized it.

  • MCP authorization

    MCP clients doing authorization code MUST use PKCE as OAuth 2.1 clients.

  • DPoP

    PKCE protects the code; DPoP protects later resource requests. Both are needed if the agent is public and the token is valuable.

07

What bites agent implementers

  • Reuse of verifiers

    A static challenge is not PKCE. One verifier per request.

  • plain method

    If the AS still allows plain, an interceptor who sees the challenge sees the verifier. Refuse to use plain.

  • PKCE is not sender-constraint of the access token

    After redemption, a stolen Bearer access token still works. Add DPoP/mTLS/signatures.

08

Stability — what you can ship

RFC 7636, September 2015, N. Sakimura, J. Bradley, N. Agarwal. Stable. Required by RFC 9700 and OAuth 2.1. https://www.rfc-editor.org/rfc/rfc7636.html

Catalog claims (short form)

code_challenge_method=S256
The only method OAuth 2.1 keeps. 'plain' is prohibited.

Implementer notes

OAuth 2.1 and RFC 9700 require PKCE for authorization-code clients, including confidential ones. Generate a new verifier per authorization request.

Relationship to others

Primary sources

  • RFC 7636https://www.rfc-editor.org/rfc/rfc7636.html