On this page
A copied bearer token can be presented by whoever possesses it. DPoP changes that contract: the caller must also prove possession of the private key associated with the token.
ProAuth introduced DPoP in 3.0.0. This is the released-feature follow-up to our DPoP preview.
Token issuance establishes the binding
Configure dpopBoundAccessTokens on the client’s authentication configuration. ProAuth then requires a valid DPoP proof when issuing tokens and returns a DPoP access token with the public-key thumbprint in cnf.jkt.
The proof is a signed JWT containing request-specific evidence, including the HTTP method, target URI, issue time and a unique identifier. A public key is included so the receiver can verify the signature. The private key stays with the client.
flowchart TD
Key[Client holds private key] --> Proof[Sign request proof]
Proof --> Issue[ProAuth validates proof and issues bound token]
Issue --> Call[Client sends token and a new API proof]
Call --> Validate[API validates token and proof together]
Validate --> Decision[API applies audience and scope policy]
The DPoP configuration guide covers proof fields, nonce handling and discovery. The protocol is defined in RFC 9449.
The API has its own enforcement job
Issuing a bound token does not make an ordinary bearer-only API validate possession automatically. The resource server must validate the proof signature, method, URI, time, replay identifier and access-token hash. The proof key must match cnf.jkt in the token or active introspection result. Normal issuer, audience, expiry and scope checks remain necessary.
For API calls, the authorization scheme is DPoP, accompanied by a separate DPoP proof header. ProAuth validates the binding at its protected OIDC resource endpoints, including UserInfo. External APIs need equivalent enforcement; see the resource-server guide.
The gain is specific: leaking the token alone no longer supplies everything needed to use it. An attacker who controls the client or can invoke its signing key can still act through that client. Key storage and application integrity remain part of the architecture.
Plan for nonces and key continuity
With requireDpopNonce, clients must handle a use_dpop_nonce response and retry with the supplied nonce in a newly signed proof. Test this path before enabling the requirement.
Authorization codes can also be bound to a key through dpop_jkt. A binding established there must match token redemption. Public-client refresh tokens issued in a bound flow retain their key binding. Losing that key is an application reauthorization event, rather than a reason to retry with a replacement key and the old refresh token.
Keep confidential-client authentication explicit. DPoP proves possession of the token-bound key; it does not replace the separate method used to authenticate a confidential client. Review both obligations in the integration design.
Test the rejected request as carefully as the accepted one
Before rollout, verify a valid API call, then repeat it with a different key, wrong method, wrong URI, modified token and replayed proof. Exercise refresh after a client restart so key persistence is tested too.
Make key continuity an acceptance check, rather than relying on a successful request from one running process. The resource-server guide covers API validation, while the 3.0 release notes establish the released DPoP capability. The useful result is a client and API that agree on the possession proof throughout the token lifetime.