DPoP
The HTTP DPoP request header carries a JSON Web Token proof binding an OAuth access token to a specific client key pair, preventing token theft and replay attacks.
Usage
OAuth access tokens are typically bearer tokens. Anyone possessing the token uses the token to access protected resources. When a token is stolen from storage or intercepted in transit, an attacker gains full access to resources until the token expires.
DPoP (Demonstrating Proof of Possession) changes this model by binding access tokens to a public/private key pair owned by the client. The client proves possession of the private key on each request by including a signed JWT in the DPoP header. Resource servers verify the signature against the public key bound to the access token, confirming the request originates from the legitimate token holder.
The mechanism applies to both Authentication requests to the authorization server and resource requests to protected APIs. Authorization servers bind issued tokens to the public key presented in the DPoP proof, creating sender-constrained tokens instead of bearer tokens.
DPoP addresses token theft at the application level without requiring transport-layer changes. Public clients like single-page applications and mobile apps benefit most, as these environments lack secure storage for client credentials.
Values
The DPoP header value is a JWT containing a specific set of claims and signed with the client's private key.
typ
The JWT typ header parameter is set to dpop+jwt. This identifies the
token as a DPoP proof JWT rather than a standard JWT.
alg
The JWT alg header parameter specifies the signing algorithm. The
specification requires an asymmetric digital signature algorithm. Common values
include RS256, ES256, and EdDSA.
jwk
The JWT jwk header parameter contains the public key corresponding to the
private key used to sign the proof. The authorization server extracts this
public key and binds the issued access token to the key.
jti
The jti claim contains a unique identifier for the proof JWT. Authorization
and resource servers use this identifier to detect replay attacks by tracking
recently seen proof tokens.
htm
The htm claim contains the HTTP method of the request, such as GET,
POST, or PUT. The server verifies the DPoP proof was generated for the
current HTTP method.
htu
The htu claim contains the HTTP URI of the
request, excluding query and
fragment components. The server verifies the proof was generated for the
target resource URI.
iat
The iat claim contains the time at which the proof JWT was created. Servers
reject proofs older than an acceptable threshold to limit replay windows.
ath
When the DPoP header accompanies a request using a DPoP-bound access
token, the ath claim contains the hash of the access token. This
cryptographically binds the proof to the specific access token being used.
nonce
When the authorization or resource server requires a nonce value, the client includes the nonce in this claim. The server provides nonces via the DPoP-Nonce response header. Including the nonce proves freshness and prevents replay attacks.
Example
A client requesting an access token from an authorization server. The DPoP proof includes the public key, HTTP method, target URI, and a unique identifier. The authorization server validates the proof and issues a DPoP-bound access token.
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik
VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR
nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE
QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiItQndDM0VTYzZhY2MybFRjIiwiaHRtIj
oiUE9TVCIsImh0dSI6Imh0dHBzOi8vc2VydmVyLmV4YW1wbGUuY29tL3Rva2VuIiwia
WF0IjoxNTYyMjYyNjE2fQ.2-GxA6T8lP4vfrg8v-FdWP0A0zdrj8igiMLvqRMUvwnQg
4PtFLbdLXiOSsX0x7NVY-FNyJK70nfbV37xRZT3Lg
A client using a DPoP-bound access token to access a protected resource. The
proof includes all standard claims plus the ath claim containing the hashed
access token. The resource server verifies the signature, validates the
claims, and confirms the proof matches the presented access token.
DPoP: eyJ0eXAiOiJkcG9wK2p3dCIsImFsZyI6IkVTMjU2IiwiandrIjp7Imt0eSI6Ik
VDIiwieCI6Imw4dEZyaHgtMzR0VjNoUklDUkRZOXpDa0RscEJoRjQyVVFVZldWQVdCR
nMiLCJ5IjoiOVZFNGpmX09rX282NHpiVFRsY3VOSmFqSG10NnY5VERWclUwQ2R2R1JE
QSIsImNydiI6IlAtMjU2In19.eyJqdGkiOiJlMWozVl9iS2ljOC1MQUVCIiwiaHRtIj
oiR0VUIiwiaHR1IjoiaHR0cHM6Ly9yZXNvdXJjZS5leGFtcGxlLm9yZy9wcm90ZWN0Z
WRyZXNvdXJjZSIsImlhdCI6MTU2MjI2MjYxOCwiYXRoIjoiZlVIeU8ycjJaM0RGNzFw
c2lSS1B2TWxtNzFsSzR5UEY0TlJqQnJjMXVEYyJ9.bLLjeCaUqPVpDMOIAqoLlzXDY
vk8qDKRFHGmYjNMBhD3REV7pxMxZI0mF2fC4FiVfLjDxBvPHzF0OqJG5lZ3Kg
Takeaway
The DPoP header provides cryptographic proof the client making an OAuth request possesses the private key bound to the access token, preventing stolen tokens from being used by attackers.
See also
- RFC 9449: OAuth 2.0 Demonstrating Proof of Possession (DPoP)
- DPoP-Nonce
- Authorization
- Authentication
- HTTP headers