OAuth2 Token Binding with DPoP
A pen test exfiltrated a valid access token from browser devtools. Curl from an attacker's laptop returned 200 until expiry. DPoP (RFC 9449) binds the access token to an ephemeral key pair—require a signed proof on every resource request.
Bearer vs sender-constrained
DPoP fits public clients generating EC keys in Web Crypto or Secure Enclave without PKI provisioning per device.
DPoP proof JWT
Payload includes htm, htu, iat, jti, and ath (access token hash when presenting bearer token). Resource servers validate signature, method, URI, jkt thumbprint match to token cnf.jkt, and jti replay cache.
Authorization server
On token endpoint validate DPoP proof; issue access token with cnf.jkt confirmation claim. Bind refresh tokens to DPoP key where policy requires.
SPA architecture
BFF holds DPoP keys server-side; browser gets session cookie only—XSS cannot exfiltrate bearer token directly.
Failure modes
Gateway validates but internal services do not; clock skew on iat; load balancer URL mismatch in htu normalization; logging full DPoP headers unnecessarily.
Rollout
Client SDK attach DPoP; AS issue cnf.jkt; APIs log-only validation then enforce; coordinate mobile release with backend enforcement.
DPoP stops export of reusable bearer credentials to another machine—it does not stop XSS acting as the user inside the browser.
Resource server validation checklist
- Normalize
htuwithout query strings unless your API requires them in the proof. - Reject proofs with clock skew beyond ±60 seconds unless you operate stricter NTP.
- Maintain
jtireplay cache sized for peak RPS × TTL window. - Return 401 with
WWW-Authenticate: DPoPerror codes—clients need actionable failures.
Combining DPoP with mTLS for service mesh
East-west service calls may use mTLS while north-south mobile clients use DPoP. Document which paths require which sender constraint—mixed enforcement confuses incident response when tokens work from curl but fail from apps.
LLM BFF pattern
Browser-based LLM chat should not hold DPoP keys in JavaScript. Run DPoP on the BFF that calls model APIs; the browser holds only HttpOnly session cookies. Stolen session cookies remain a risk—pair with short session TTL and rotation on privilege changes.
Proof generation in clients
const proof = await createDPoPProof({
url: resourceUrl,
method: "POST",
accessTokenHash: hashAccessToken(accessToken),
privateKey: dpopKeyPair.privateKey,
});
// Authorization: DPoP <proof-jwt>, Bearer <access-token>
Generate fresh jti per request; cache private keys in secure enclave with rotation schedule.
Gateway normalization
Reverse proxies must forward DPoP header untouched and preserve method/URL seen by the app. Misconfigured nginx proxy_set_header strips proofs silently—add integration tests that fail CI when header missing at upstream.
Incident response
If DPoP private keys leak from a device batch, rotate AS signing keys is insufficient—revoke affected refresh families and publish forced app update. Monitor for proof validation failures concentrated on one app version (signals broken SDK release).
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Validate with staging load tests and document rollback before enabling enforcement in production.
Frequently asked questions
What problem does DPoP solve that HTTPS does not?
HTTPS protects tokens in transit. DPoP protects against tokens stolen after delivery—XSS, logs, malware. Bearer tokens alone prove nothing about who presents them.
How is DPoP different from mTLS?
mTLS binds at TLS layer—great for service-to-service. DPoP works at HTTP layer with ephemeral keys in mobile and browser clients via BFF.
Does DPoP replace refresh token rotation?
No. Rotation detects refresh reuse; DPoP constrains access token replay. Use both for public clients.
What if the resource server skips DPoP validation?
Attackers with stolen tokens operate normally. DPoP is security theater unless every resource server validates proofs.
Hiring a senior Android / Flutter engineer?
I architect and ship production mobile software — Kotlin, Jetpack Compose, Flutter — for robotics, EV infrastructure, fintech, and real-time systems. Open to remote roles in Europe and the US.
Get in touch →