Bearer tokens and DPoP tokens can authorize the same API call, but they answer a different question. A bearer token says, “whoever has this string may use it.” A DPoP-bound token also asks the client to prove that it controls a particular private key on every request.
That extra proof narrows what a stolen access token can do. It does not make token storage, TLS, audience checks, scopes or short lifetimes optional.
Bearer and DPoP at a glance
| Property | Bearer token | DPoP-bound token |
|---|---|---|
| What the resource server receives | Access token | Access token plus a DPoP proof |
| Cryptographic proof from the client | None beyond possession of the token | A signed JWT made with the bound private key |
| Effect of copying the access token | The copy can be presented until other controls stop it | The copy should fail without the matching private key |
| Server work | Validate the token and normal authorization conditions | Validate the token, key binding and proof claims |
| Replay protection | Relies on transport, storage, lifetime and server controls | Adds request-bound proof and replay detection, with limits |
RFC 6750 defines a bearer token as one that any holder can use without proving possession of cryptographic key material. RFC 9449 defines DPoP as an application-level sender-constraining mechanism for OAuth access and refresh tokens.
What DPoP changes in the request
The client creates an asymmetric key pair. The authorization server binds an issued token to the public key. For an API request, the client sends both the access token and a signed DPoP proof.
That proof is a JWT with a public key in its protected header. Its payload identifies the HTTP method and target URI, and includes an issued-at time plus a unique identifier. When an access token accompanies the request, the proof also carries a hash of that token.
A resource server therefore checks two linked objects:
- the access token is valid for this audience and operation;
- the token is bound to a public-key thumbprint;
- the DPoP proof verifies under that public key;
- the proof describes the actual method and URI;
- the token hash matches the presented access token;
- the proof is recent and has not already been accepted where replay tracking is applied.
A copied proof is not a reusable second token. Changing the method, target URI or access token breaks the signed relationship. Reusing an unchanged proof can be rejected by its identifier and time window.
The binding is the important part
A signed request is not enough by itself. The authorization server must issue a token whose confirmation information identifies the same key that signs the DPoP proof. The resource server then compares the key thumbprint in the token with the public key in the proof.
This is the boundary that turns “a client sent a signed JWT” into “the presenter controls the key to which this token was issued.”
The authorization request and token request also need the right DPoP handling. A deployment that accepts an ordinary bearer token at one stage and only checks a proof later may not have the sender constraint it expects. The protocol has to be implemented across the authorization server, client and resource server.
What DPoP can stop
DPoP is designed to reduce the value of a leaked token. If an attacker copies only a sender-constrained access token from a log, storage snapshot or intercepted application state, the attacker should not be able to present it from another client without the private key.
The same principle can apply to refresh tokens. Binding refresh tokens limits the usefulness of copying the refresh-token string alone.
This is materially different from an opaque-versus-JWT choice. Either token format can be bearer or sender-constrained. “JWT” describes a representation. “DPoP” describes how the presenter proves possession of a key.
What DPoP does not stop
DPoP does not repair every compromise.
If an attacker obtains both the token and the private key, the sender constraint is lost. If malicious code can ask the legitimate key holder to sign attacker-chosen requests, proof of possession may still succeed. RFC 9449 also notes that a resource server cannot generally distinguish a replayed proof from a legitimate retry unless it records proof identifiers or uses a server-provided nonce.
DPoP also does not replace:
- TLS and certificate validation;
- correct issuer, audience and scope checks;
- careful token storage;
- key rotation and revocation plans;
- short token lifetimes;
- authorization checks for the requested resource.
A nonce can make a proof depend on fresh server state, but it adds another round trip or retry path. That tradeoff matters on mobile networks and in distributed APIs.
Implementation choices to settle early
Where the private key lives
The threat model changes if the key is exportable, stored in general application storage or backed by a platform keystore. DPoP proves possession of a key; it does not certify how the key was generated or protected.
How the server handles retries
Network retries can legitimately repeat an application operation. The client should create a fresh DPoP proof for a retried HTTP request. Separately, the API may still need an idempotency key to prevent one business operation from being applied twice. Our idempotency-key guide covers that different layer.
How URI comparison works
The proof binds to the HTTP target URI according to RFC 9449’s normalization rules. Reverse proxies, rewritten paths and inconsistent scheme or host handling can cause valid requests to fail—or produce a weaker check if the server compares the wrong value.
How replay state is stored
A server can remember proof identifiers during the accepted time window, but doing so across many resource servers requires shared or partitioned state. A nonce reduces reliance on a global identifier store but creates challenge handling that every client must implement correctly.
A practical verification checklist
For each protected request, verify the normal token conditions first, then the DPoP-specific conditions. Record failures without logging the raw token or private proof material.
Useful test cases include:
- the correct token with no DPoP proof;
- a valid proof signed by the wrong key;
- the right proof replayed against a different URI;
- the right proof replayed with a different method;
- a proof whose access-token hash does not match;
- an old proof outside the accepted time window;
- a repeated proof identifier;
- a nonce challenge followed by a fresh proof;
- a refresh token presented without its bound key.
These are protocol tests, not evidence that a particular library implements DPoP safely.
DPoP or bearer: the design decision
Bearer tokens remain simpler and widely supported. They can be appropriate when tokens are short-lived, well protected and used in a controlled server-to-server path. DPoP is useful when reducing the value of copied tokens justifies key management, proof verification, replay handling and interoperability work.
The decision is not “secure versus insecure.” It is whether sender constraining addresses a realistic theft path in your system, and whether every participating component can enforce the binding consistently.
For related HTTP precondition mechanics, see ETag vs Last-Modified. For transport behavior that can replay early application data, see TLS 1.3 0-RTT.
Sources and version note
This explainer was checked on 25 October 2026 against RFC 9449: OAuth 2.0 Demonstrating Proof of Possession, published September 2023; RFC 6750: Bearer Token Usage, published October 2012; and RFC 9700: Best Current Practice for OAuth 2.0 Security, published January 2025.





