OAuth2 Token Binding with DPoP

SecurityOAuthAuthenticationBackend
Share on LinkedIn Share on X Share on Reddit Share on HN Share on Bluesky

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

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 →