DPoP Binds OAuth Access Tokens to a Client Key

A bearer access token is usable by any party that obtains the token and can present it to the resource server. TLS protects the token while it crosses a correctly authenticated connection, but it does not change that bearer property after the token reaches an endpoint, log, process, browser context, or other storage location.

Demonstrating Proof of Possession (DPoP), specified by RFC 9449, adds a key-bound layer at the application protocol. The client creates an asymmetric key pair and signs a DPoP proof JWT. An authorization server can bind an issued access token to the public key represented by that proof. The resource server then requires both the token and a valid proof created with the corresponding private key.

The resulting token is sender-constrained rather than freely transferable as a bearer credential. That constraint is specific: possession of the token alone is insufficient. DPoP does not make token theft impossible, prove that the client host is uncompromised, or replace the rest of OAuth authorization policy.

The binding is represented by a key thumbprint

A DPoP proof carries the client’s public key in the jwk protected header. When an authorization server issues a DPoP-bound access token, the token authorization data is associated with the public key. For JWT access tokens, RFC 9449 defines a cnf claim containing jkt, the JWK SHA-256 thumbprint of that key.

A simplified relationship is:

client private key
       |
       v
signed DPoP proof ---- public JWK ----+
                                      |
                                      v
                               JWK thumbprint
                                      |
                                      v
                           access token cnf.jkt

The private key is not sent in the proof. The signature demonstrates control of it, while the public JWK gives the verifier the material needed to verify that signature and derive the thumbprint.

At the resource server, accepting the token and accepting the DPoP proof are linked checks. A proof signed by an unrelated key does not satisfy the sender constraint merely because its signature is cryptographically valid.

Each proof is scoped to an HTTP request

A DPoP proof is not a reusable client certificate. It is a JWT constructed for a particular HTTP operation. Its claims include htm for the HTTP method, htu for the target URI, iat for issuance time, and jti as a unique identifier. A proof sent with an access token also includes ath, a hash of the access token.

Those fields bind the proof to more than a key:

proof signature
  + HTTP method
  + target URI
  + issuance time
  + unique identifier
  + access-token hash

The verifier checks these values under the rules in RFC 9449. A captured proof for one target is therefore not a generic signature that can simply be attached to a different method or URI. The ath value also ties a protected-resource proof to the particular access token presented with it.

URI comparison deserves care. DPoP defines how the htu value is formed and compared, including treatment of query and fragment components. Implementations should follow those protocol rules rather than applying an unrelated URL-normalization routine that silently changes the signed request identity.

Freshness limits replay but requires verifier state or policy

A valid signature does not make a DPoP proof permanently acceptable. The verifier evaluates iat against an acceptable time window and can use jti to detect reuse according to its replay policy.

This creates an operational boundary. A short acceptance window reduces the useful lifetime of a captured proof, while replay detection across multiple resource-server instances may require shared or consistently partitioned state. A deployment that validates only the signature but ignores the protocol’s freshness and request-binding checks discards central parts of the construction.

DPoP also supports server-provided nonces. An authorization server or resource server can require a nonce and return a fresh value for subsequent proofs. The client places that value in the nonce claim. This gives the server a mechanism to require proof freshness based on server-generated material rather than relying only on the client’s clock and identifier.

Nonce support introduces request sequencing and retry behavior that clients must handle according to the protocol. It is not a substitute for checking the other proof claims.

DPoP can appear at two distinct OAuth boundaries. During token acquisition, the client sends a DPoP proof to the authorization server. That proof lets the server bind the resulting token to the client’s public key.

During protected-resource access, the client creates another proof for the resource request and sends the access token using the DPoP authorization scheme. The resource server verifies the token, the proof, and the key binding between them.

The two proofs are not interchangeable because their HTTP targets, methods, timestamps, identifiers, and token-hash requirements differ. Reusing a token-endpoint proof at an API endpoint should fail the request-binding checks.

This separation also keeps authority clear. The authorization server decides what token to issue and records the key binding. The resource server enforces that binding when authorizing access to its resources.

DPoP constrains token use, not client software integrity

If malware can invoke the legitimate client’s signing operation, possession of a non-exportable or otherwise protected private key may not prevent malicious requests. DPoP proves that a request was signed with the bound key; it does not attest to the intent of the software that requested the signature.

Similarly, a client that stores an exportable private key beside its access token can lose both artifacts in the same compromise. An attacker holding both can produce new proofs until other controls invalidate the credentials or prevent their use.

Key storage therefore remains part of the threat model. Platform keystores, hardware-backed keys, process isolation, and credential lifecycle controls can change the difficulty of extracting or abusing the key, but those properties come from the platform and deployment rather than from DPoP itself.

Sender constraint does not replace audience or authorization checks

A resource server still needs normal access-token validation. Depending on token format and deployment, that can include issuer, audience, expiry, signature, scope, and other authorization data. DPoP adds proof that the presenter controls the key to which the token is bound; it does not decide whether the token authorizes the requested business operation.

The same distinction applies to token audience. A proof’s htu binds the proof to an HTTP URI, while token audience policy determines where the token is intended to be accepted. Both checks can matter. One does not infer the other.

DPoP also does not replace TLS. The protocol is designed for use with HTTPS. Transport security protects requests and responses in transit, while DPoP addresses the separate bearer-token transfer problem by adding a sender constraint.

Proxies must preserve the request identity used for verification

Reverse proxies and gateways can complicate htu validation because the externally visible URI may differ from the backend connection target. A verifier needs a trustworthy view of the HTTP URI that the client used to construct the proof.

Blindly trusting client-controlled forwarding headers can let an attacker influence that reconstruction. Deployments behind proxies should define which infrastructure supplies authoritative scheme, host, and request-target information, sanitize competing headers, and keep that trust boundary consistent with DPoP verification.

This is the same class of problem seen in other security checks based on an external request identity: the cryptographic check can be correct while the input reconstructed by the application is wrong.

Key rotation changes the sender constraint

Because the access token is bound to a particular public key, replacing the DPoP key is not transparent to an already issued token. A new key produces a different JWK thumbprint and therefore cannot satisfy the old token’s binding.

Clients need lifecycle behavior that accounts for both token expiry and key rotation. Rotating a key can require obtaining new bound tokens. Conversely, retaining a key indefinitely solely to keep old tokens usable can extend the lifetime of key material beyond the intended policy.

The useful security boundary is narrow and concrete: an accepted protected-resource request must carry an authorized token and a fresh DPoP proof whose signing key matches that token’s sender constraint. Keeping that boundary precise makes DPoP valuable without assigning it properties that belong to endpoint security, TLS, or application authorization.

References