rfc-9449

OAuth 2.0 Demonstrating Proof of Possession (DPoP)

D. Fett, B. Campbell, J. Bradley, T. Lodderstedt, M. Jones, D. Waite
date2023-09 streamIETF areasec wgoauth statusPROPOSED STANDARD pages39 canonicalhttps://www.rfc-editor.org/rfc/rfc9449 doi10.17487/RFC9449 errataview
This document describes a mechanism for sender-constraining OAuth 2.0 tokens via a proof-of-possession mechanism on the application level. This mechanism allows for the detection of replay attacks with access and refresh tokens.

Extracted elements (33)

design-rationale §4.2

DPoP proof JWTs cover only the HTTP method and URI, not the full message body or headers. This intentional minimalism avoids the substantial difficulties of normalizing HTTP messages, while signing just enough data to provide reasonable proof of possession.

oauth, http, security

design-rationale §5

Refresh tokens issued to confidential clients are not bound to the DPoP proof public key because they are already sender-constrained via client authentication. Existing OAuth 2.0 binding to client_id with authentication is more flexible (allows credential rotation) than binding to a specific public key.

oauth, security

design-rationale §11.10

SHA-256 is used exclusively for the jkt confirmation method, ath claim, and dpop_jkt parameter — a deliberate choice for simplicity and to avoid security and interoperability issues from parameterized algorithm agility schemes. A future update specification would define new parameters if SHA-256 became insufficient.

oauth, crypto, security

interoperability-note §7.2

A DPoP-bound access token may be accepted by a Bearer-only resource server unaware of DPoP, since JWT specs say to ignore unrecognized claims and RFC 6750 is silent on token content. This simplifies phased upgrades and mixed deployments, but requires DPoP-aware servers to explicitly reject DPoP tokens presented as Bearer tokens.

oauth, security, http

interoperability-note §7.1

Browser-based clients using CORS have access only to CORS-safelisted response headers by default. Servers must include WWW-Authenticate and DPoP-Nonce in the Access-Control-Expose-Headers response header for browser clients to obtain these values.

oauth, http, security

normative-requirement §7.1 MUST NOT

A resource server MUST check the DPoP proof according to Section 4.3 and verify the public key match to the access token. The resource server MUST NOT grant access unless all checks are successful.

oauth, security

normative-requirement §5 MUST

A token_type of DPoP MUST be included in the access token response to signal to the client that the access token is bound to its DPoP key. If the access token response contains a different token_type, the client MUST discard the response if DPoP protection is required for the application.

oauth, security

normative-requirement §2 MUST

DPoP MUST always be used in conjunction with HTTPS; it is not a substitute for a secure transport layer.

oauth, security, tls

normative-requirement §8 MUST

If the nonce claim in the DPoP proof does not exactly match a nonce recently supplied by the authorization server, the authorization server MUST reject the request. A server MUST NOT accept DPoP proofs without the nonce claim when a DPoP nonce has been provided to the client.

oauth, security

normative-requirement §7.2 MUST

Protected resources supporting both DPoP and Bearer schemes MUST reject a DPoP-bound access token received as a bearer token (RFC 6750) to prevent token downgrade attacks.

oauth, security, http

normative-requirement §6 MUST

Resource servers MUST be able to reliably identify whether an access token is DPoP-bound and MUST ensure the public key from the DPoP proof matches the public key bound to the access token.

oauth, security

normative-requirement §4.2 MUST NOT

The alg JOSE Header Parameter in a DPoP proof MUST NOT be none and MUST NOT identify a symmetric algorithm (MAC). Only registered asymmetric digital signature algorithms are permitted.

oauth, jose, crypto, security

normative-requirement §8.2 MUST

The client MUST use the new nonce value supplied in a DPoP-Nonce header for the next token request and all subsequent token requests until the authorization server supplies a new nonce.

oauth, security

normative-requirement §5 MUST

To request a DPoP-bound access token, the client MUST provide a valid DPoP proof JWT in the DPoP header at the token endpoint. This applies to all grant types. Invalid proofs result in an invalid_dpop_proof error response.

oauth, security

normative-requirement §4.3 MUST

To validate a DPoP proof, the receiving server MUST verify: no more than one DPoP header, well-formed JWT, all required claims present, typ is dpop+jwt, alg is acceptable asymmetric algorithm, signature verifies with jwk, jwk contains no private key, htm and htu match the current request, nonce matches if provided, iat is within acceptable window, and (for protected resources) ath matches the access token hash and public keys match.

oauth, jose, security, http

normative-requirement §4.2 MUST

When a DPoP proof is used in conjunction with an access token at a protected resource, the proof MUST also contain the ath claim: the base64url-encoded SHA-256 hash of the ASCII encoding of the access token's value.

oauth, jose, security

normative-requirement §5 MUST

When an authorization server issues a refresh token to a public client that presents a valid DPoP proof, the refresh token MUST be bound to the respective public key. The binding MUST be validated when the refresh token is later used.

oauth, security

normative-requirement §10.1 MUST

When Pushed Authorization Requests are used with DPoP, an authorization server that supports both PAR and DPoP MUST support both the dpop_jkt parameter and the DPoP header in the PAR request. If both are used simultaneously, the server MUST reject the request if the JWK Thumbprints do not match.

oauth, security

normative-requirement §4.2 MUST

When the authorization server or resource server has provided a DPoP-Nonce HTTP header, the DPoP proof MUST also contain a nonce claim carrying the recent server-provided nonce value.

oauth, security

protocol-element §4.2

A DPoP proof is a JWT sent in the DPoP HTTP header field, signed with a client-chosen private key. The JOSE Header MUST include typ (dpop+jwt), alg (asymmetric only), and jwk (public key in JWK format, no private key). The payload MUST include jti, htm, htu, and iat claims.

oauth, jose, security, http

protocol-element §8

Authorization servers and resource servers may provide opaque nonce values via the DPoP-Nonce HTTP header to limit the lifetime of DPoP proofs. Nonce values MUST be unpredictable. Servers respond with use_dpop_nonce error and a DPoP-Nonce header if a required nonce is absent or mismatched.

oauth, security, http

protocol-element §6.2

For DPoP-bound access tokens retrieved via token introspection (RFC 7662), the cnf/jkt structure is conveyed as a top-level member of the introspection response JSON. If token_type is included in the introspection response, it MUST contain the value DPoP.

oauth, jose

protocol-element §7.1

The DPoP authentication scheme sends a DPoP-bound access token in the Authorization header using the syntax: Authorization: DPoP <token68>. Resource servers must also receive a DPoP proof in the DPoP header field and verify it per Section 4.3.

oauth, http, security

protocol-element §5.2

The dpop_bound_access_tokens client registration metadata parameter is a boolean indicating the client always uses DPoP for token requests (default false). If true, the authorization server MUST reject token requests from that client lacking the DPoP header.

oauth, security

protocol-element §10

The dpop_jkt authorization request parameter binds the authorization code to a DPoP key. Its value is the JWK Thumbprint (SHA-256) of the proof-of-possession public key, the same value used for the jkt confirmation method. The authorization server MUST reject token requests where this value does not match the DPoP proof key.

oauth, security, crypto

protocol-element §5.1

The dpop_signing_alg_values_supported authorization server metadata parameter is a JSON array listing the JWS alg values the server supports for DPoP proof JWTs, allowing clients to discover which algorithms are acceptable.

oauth, jose

protocol-element §6.1

The jkt JWT Confirmation Method member conveys the JWK SHA-256 Thumbprint of the DPoP public key in JWT-structured access tokens under the cnf claim. Its value MUST be the base64url encoding of the JWK SHA-256 Thumbprint per RFC 7638.

oauth, jose, crypto

registry §12

This document creates or updates the following IANA registries: OAuth Access Token Types (DPoP), OAuth Extensions Errors (invalid_dpop_proof, use_dpop_nonce), OAuth Parameters (dpop_jkt), HTTP Authentication Schemes (DPoP), Media Types (application/dpop+jwt), JWT Confirmation Methods (jkt), JWT Claims (htm, htu, ath; nonce updated), HTTP Field Names (DPoP, DPoP-Nonce), OAuth Authorization Server Metadata (dpop_signing_alg_values_supported), and OAuth Dynamic Client Registration Metadata (dpop_bound_access_tokens).

oauth, registry, jose, http

security-consideration §11.2

An attacker controlling a client can pre-generate DPoP proofs with future iat values and exfiltrate them for later use without the private key. Server-provided unpredictable nonces prevent this attack by limiting proof lifetime. Deployments without nonces SHOULD NOT issue long-lived DPoP-constrained access tokens.

oauth, security

security-consideration §11.7

DPoP does not ensure integrity of the request payload or general headers — only the HTTP URI and method are covered by the DPoP proof. This is an intentional design decision to keep DPoP simple; TLS is relied upon for message integrity.

oauth, security, tls

security-consideration §11.4

If untrusted code (e.g., via XSS) runs in the client's execution context, DPoP security is not guaranteed. If the private key is non-extractable (e.g., stored in a hardware/software security module), key exfiltration is prevented, but an online attacker can still create fresh DPoP proofs. Content Security Policy is recommended as a second layer of defense.

oauth, security, privacy

security-consideration §11.5

Servers accepting DPoP proof JWTs MUST verify that the typ field is dpop+jwt in the JWT header to prevent signed JWTs created for other purposes (e.g., ID tokens) from being swapped in as DPoP proofs.

oauth, jose, security

security-consideration §11.1

Servers MUST only accept DPoP proofs for a limited time after their creation (preferably seconds or minutes) to prevent replay of captured DPoP proof JWTs at the same endpoint. Servers may store jti values for the validity window to enforce single-use, though this may not be feasible with stateless distributed servers.

oauth, security