Key points
- Defined in RFC 9449
- Mitigates OAuth token theft and replay
- Client signs a per-request JWT (DPoP proof) with a private key
- Lighter-weight alternative to mTLS-bound tokens
- Adopted by FAPI 2.0 and modern banking APIs
What it is
DPoP turns a bearer token into a sender-constrained token. Even if an attacker steals the access token, they cannot use it without also stealing the client's private key — which typically lives in the device or browser's secure storage.
How it works
- The client generates a key pair and includes the public key (
jktthumbprint) when requesting a token. - On every API request, the client attaches a
DPoPheader — a short-lived JWT signed with the private key, binding the request method, URL, and token hash. - The resource server verifies the DPoP proof and checks that the access token's
cnf.jktmatches the proof's key.
When buyers care
- High-value APIs (banking, payments, healthcare) where token theft is realistic
- SPAs and mobile apps where mTLS is impractical
- Compliance with FAPI 2.0 / Open Banking profiles
Common misconceptions
- DPoP is not encryption. It's proof-of-possession; the token itself is still readable.
- DPoP and mTLS solve the same problem differently. Pick mTLS for service-to-service, DPoP for browsers and mobile.
FAQ
Is DPoP a replacement for PKCE?
No. PKCE protects the authorization code exchange. DPoP protects the access token in use. Use both.
Do all IdPs support DPoP?
Support is growing but uneven. Verify your IdP and resource servers both implement RFC 9449 before designing around it.
