Safeguard
Security Guides•

DPoP explained: making stolen OAuth tokens useless

DPoP binds an OAuth token to a client key so a stolen token alone fails. See how the proof JWT works, what it stops, and what it does not cover.

Safeguard Security Team
3 min read

DPoP (RFC 9449) ties an OAuth access token to a key pair held by the client. Each request carries a signed proof, so a thief who steals only the token cannot use it. It does not help if malicious code is running inside the client itself.

The problem with bearer tokens

An ordinary bearer token works for whoever holds it. If it leaks through logs, a proxy, a compromised dependency or a stolen device backup, the thief can call the API as the user until it expires. The same goes for refresh tokens, which last longer.

How DPoP works

The client generates a key pair. With each request it sends a DPoP header holding a signed JWT, the proof.

The proof header has:

  • typ of dpop+jwt
  • an asymmetric alg, never none or a MAC
  • jwk, the public key, with no private material

The proof payload has:

  • jti: unique ID, to detect replay
  • htm: the HTTP method
  • htu: the target URI without query or fragment
  • iat: creation time
  • ath: base64url SHA-256 of the access token, when calling a resource
  • nonce: a server supplied value, when required

At the token endpoint, the authorization server binds the issued token to the proof key, recording the key's thumbprint in the cnf claim as jkt. The token type returned is DPoP. The resource server then checks the proof signature, method, URI, freshness and ath, and confirms the proof key matches jkt.

What it protects against

  • Use of stolen access or refresh tokens by someone without the private key.
  • Replay of a token at a different endpoint, since proofs are bound to method and URI.
  • Pre generated proofs, especially when server nonces are used.
  • Downgrade to bearer use of a DPoP bound token, which resource servers must reject.

Server nonces, delivered through the DPoP-Nonce header, let the server limit how long a proof stays valid.

What it does not protect against

  • Malicious code in the client, such as cross site scripting, which can still create valid proofs while the client is online.
  • Tampering with the body or most headers, since only the method and URI are signed. TLS still has to provide integrity.
  • Replay within the validity window, unless servers track jti values.
  • Authorization decisions. A valid proof is not permission.

RFC 9449 also says DPoP is not a substitute for secure transport.

Where it fits

RFC 9700 says refresh tokens for public clients must be sender constrained or rotated, and that sender constrained access tokens should be used, via mutual TLS or DPoP. DPoP is attractive for single page and mobile apps where mutual TLS is awkward.

Adoption checklist

  1. Check that your authorization server and APIs both support DPoP.
  2. Keep the private key non extractable where the platform allows.
  3. Track jti values for a short window.
  4. Use server nonces for high value APIs.
  5. Continue to use short access token lifetimes.

Quick check

Does DPoP make token theft impossible?

No. It stops use of a token by a party without the key. Code running inside the client can still sign proofs.

Is DPoP the same as mutual TLS?

Both bind tokens to a key. DPoP works at the application layer with a signed header, so it needs no client certificate handling.

Sources

Last reviewed: 19 October 2026.

Never miss an update

Weekly insights on software supply chain security, delivered to your inbox.

Self-healing security runs on Safeguard.

Your first fix PR is minutes away.

No sales call required, even your agent can complete the purchase over MCP.