Join our Newsletter — 33% off our NHI Course
Home› Guides› DPoP Guide: Sender-Constrained Tokens Without mTLS
Guide Authentication

DPoP Guide: Sender-Constrained Tokens Without mTLS

PDF for newsletter subscribers · free to read online

← All guides
By NHI Mgmt Group, edited by Lalit Choda Updated 26 October 2026 12 min read
On this page

A bearer access token works for whoever holds it, so a token copied from a log, a proxy, a browser or a compromised integration can be replayed from anywhere until it expires. DPoP (Demonstrating Proof of Possession, RFC 9449) is the OAuth 2.0 extension that binds an access token to a key pair the client holds, so a stolen token is useless without the private key. It does this at the application layer with signed JWTs in an HTTP header, which makes it usable where mutual TLS (RFC 8705) is impractical: browser apps, mobile apps and deployments behind TLS-terminating proxies. This guide explains what DPoP is, how the proof and the binding work, what it does and does not protect against, and how it compares with mTLS. It is written for architects, API and identity engineers, and security reviewers.

Key takeaways

  • DPoP turns bearer tokens into sender-constrained tokens. The authorisation server binds the token to the thumbprint of the client's public key, and every API call must carry a fresh proof signed with the matching private key.
  • It is the application-layer alternative to mTLS. RFC 8705 binds tokens to a TLS client certificate; DPoP binds them to a JWK and works through proxies, CDNs and in browsers where client certificates are painful.
  • Standards now expect sender-constraining. The OAuth 2.0 Security BCP (RFC 9700) says servers should sender-constrain access tokens, and FAPI 2.0 issues only mTLS or DPoP bound tokens.
  • Resource servers must enforce it, or it does nothing. An API that accepts a DPoP-bound token as a plain Bearer token, or skips the ath, htm and htu checks, loses the protection entirely.
  • DPoP does not stop code running inside the client. XSS or malware that can call the signing key can mint valid proofs; server nonces, short token lifetimes and non-extractable keys narrow that window.

What it is

DPoP is defined in RFC 9449, "OAuth 2.0 Demonstrating Proof of Possession (DPoP)", published by the IETF in September 2023 on the Standards Track. It adds three things to OAuth 2.0:

  • A proof JWT: a short-lived JWT the client signs with its private key and sends in a DPoP HTTP header on token requests and API calls. Its header has typ set to dpop+jwt and carries the client's public key in jwk.
  • A token binding: the authorisation server records the SHA-256 JWK thumbprint (RFC 7638) of that public key in the access token's confirmation claim, cnf.jkt, or returns it from token introspection.
  • A new token type and scheme: the token response returns token_type DPoP, and the client presents the token as Authorization: DPoP <token> rather than Bearer.

The key pair is generated by the client and never registered in advance, so DPoP also works for public clients (single-page apps, native apps) that cannot keep a client secret. For background on the base protocol, see the OAuth 2.0 and OpenID Connect Guide.

How it works

The proof JWT

FieldWherePurpose
typ = dpop+jwtJOSE headerExplicit typing so a proof cannot be confused with another JWT
algJOSE headerMust be an asymmetric algorithm; none and MAC algorithms (HS256) are not allowed
jwkJOSE headerThe client's public key; must not contain private key material
jtiClaimUnique identifier (at least 96 bits of randomness or a UUIDv4) so servers can detect replay
htmClaimHTTP method of the request the proof is for
htuClaimTarget URI without query or fragment
iatClaimCreation time; servers accept only a short window
athClaim (API calls)Base64url SHA-256 hash of the access token, tying the proof to that token
nonceClaim (when issued)Server-supplied value from the DPoP-Nonce header, limiting pre-generated proofs

The flow

  1. Key generation: the client creates an asymmetric key pair (commonly ECDSA P-256, ES256). In a browser the private key can be a non-extractable WebCrypto key; on mobile, a hardware-backed keystore key.
  2. Optional code binding: the client can send dpop_jkt (the key thumbprint) in the authorisation request, alongside PKCE, or with a pushed authorisation request (PAR), so the authorisation code can only be redeemed with that key (RFC 9449 Section 10).
  3. Token request: the client calls the token endpoint with a DPoP proof (htm POST, htu the token endpoint). All grant types, including refresh_token, carry a proof. An invalid proof returns invalid_dpop_proof.
  4. Binding: the authorisation server returns token_type: DPoP and binds the token with cnf.jkt. A response with token_type: Bearer means the token is not bound, and the client should treat that as a configuration fault if it expected binding.
  5. API call: for each request the client signs a new proof with htm, htu, a fresh jti, iat and ath, and sends it with Authorization: DPoP <token>.
  6. Verification: the resource server checks the proof (Section 4.3: one header, well-formed JWT, valid typ and alg, signature against jwk, matching htm and normalised htu, acceptable iat, nonce if issued), then checks that ath matches the token and the proof key thumbprint matches cnf.jkt.

Nonces and refresh tokens

  • Nonces: an authorisation server can reply HTTP 400 with error use_dpop_nonce and a DPoP-Nonce header; a resource server replies 401 with WWW-Authenticate: DPoP error="use_dpop_nonce". The client retries with the nonce in its proof. Once a server has issued a nonce it must not accept proofs without one.
  • Refresh tokens: for public clients, refresh tokens are bound to the DPoP key and must be presented with a proof from the same key. Confidential clients' refresh tokens are not DPoP-bound because client authentication already ties them to the client. This matters because RFC 9700 Section 2.2.2 requires public client refresh tokens to be sender-constrained or rotated.
  • Metadata: the authorisation server advertises dpop_signing_alg_values_supported; a client registered with dpop_bound_access_tokens: true has token requests without a DPoP header rejected.
  • Browsers: a cross-origin API must list DPoP-Nonce and WWW-Authenticate in Access-Control-Expose-Headers or the browser client cannot read the challenge.

DPoP compared with mTLS

AspectDPoP (RFC 9449)mTLS bound tokens (RFC 8705)
LayerApplication (HTTP header, signed JWT)Transport (TLS client certificate)
Binding claimcnf.jkt (JWK SHA-256 thumbprint)cnf.x5t#S256 (certificate SHA-256 thumbprint)
Key provisioningClient generates a key pair at runtime, no PKICA-issued (tls_client_auth) or registered self-signed (self_signed_tls_client_auth) certificates
Browser and SPA fitGood, with WebCrypto non-extractable keysPoor: client certificate prompts and management
TLS-terminating proxies and CDNsUnaffected, the proof travels in a headerCertificate must be forwarded to the app; RFC 8705 Section 6.5 leaves how to do this unspecified
Client authenticationNot a client authentication method; combine with private_key_jwt or a secret if neededCan also authenticate the client
Per-request costOne signature per request, verification on every callHandshake cost; no per-request signing
Replay windowBounded by iat window, jti tracking and noncesBound to the TLS session key; no proof replay concept
Typical fitPublic clients, SaaS APIs, AI agents calling third-party APIsService-to-service inside a service mesh or private PKI, open banking

Choose mTLS where you already run a workload PKI or service mesh and control both ends; choose DPoP where clients are browsers, mobile apps or third parties, or where TLS terminates before your application. FAPI 2.0 (Final, February 2025) accepts either. See the mTLS Guide and the OAuth 2.1, GNAP and FAPI Guide.

Rolling it out

  1. Confirm support: check the authorisation server's discovery document for dpop_signing_alg_values_supported and the client library's DPoP support. Pick ES256 unless a profile requires otherwise.
  2. Make APIs DPoP-aware first: resource servers accept both Bearer and DPoP schemes, validate proofs fully and log the scheme used. A token carrying cnf.jkt must always be rejected when presented as Bearer.
  3. Pilot one client: enable DPoP for a single public client, log invalid_dpop_proof and nonce retries, and watch clock skew failures on iat.
  4. Enforce per client: set dpop_bound_access_tokens: true so the authorisation server refuses unbound requests, then shorten access token lifetimes.
  5. Add nonces where risk is high: enable server nonces for high-value APIs and for clients running in exposed environments.
  6. Retire Bearer: once logs show no Bearer use for that audience, stop accepting the Bearer scheme. Rollback is per client: unset the enforcement flag, and resource servers keep accepting Bearer until you remove it.

Why it matters

Token theft is a routine attack path, not an edge case. MITRE ATT&CK tracks it as T1528 Steal Application Access Token, with replay of the stolen token as T1550.001 Application Access Token. Bearer tokens leak through browser storage, logs, debugging proxies, compromised SaaS integrations and developer machines. In the Salesloft Drift breach, OAuth tokens stored in the integration's cloud environment were taken and replayed against Salesforce APIs, with Google reporting over 700 potentially affected organisations. With sender-constrained tokens the attacker would also have needed the signing keys, which raises the bar considerably when those keys sit in a KMS or HSM rather than next to the tokens. The same logic applies to AI agents, which hold tokens for many APIs and run in environments that are hard to inspect.

Framework mapping

FrameworkReferenceHow DPoP helps
NIST SP 800-53 Rev. 5IA-2(8) Access to Accounts: Replay ResistantSigned, time-bound, unique proofs resist replay of captured credentials
NIST SP 800-53 Rev. 5SC-23 Session AuthenticityEach request proves possession of the key bound to the session's token
NIST SP 800-53 Rev. 5SC-8 Transmission Confidentiality and IntegrityDPoP complements but does not replace TLS (RFC 9449 Section 11)
MITRE ATT&CKT1528, T1550.001Stolen tokens cannot be used without the private key
IETF RFC 9700 (BCP 240)Sections 2.2.1, 2.2.2, 4.10.1Implements the recommended sender-constraining of access and refresh tokens
FAPI 2.0 Security ProfileSender-constrained tokensOne of the two permitted binding mechanisms

What to monitor

  • Bearer use of bound tokens: any token with cnf.jkt presented under the Bearer scheme is either a misconfigured client or a replay attempt. Alert on it.
  • Proof failures: spikes in invalid_dpop_proof by client, especially ath or key thumbprint mismatches, indicate token reuse with the wrong key.
  • Replayed jti: repeats within the acceptance window.
  • Metrics: percentage of API calls using DPoP-bound tokens per audience; number of clients with dpop_bound_access_tokens enforced; Bearer acceptance remaining per API; median access token lifetime for bound versus unbound clients; nonce retry rate (a health signal for client libraries).

Common misconceptions

  • "DPoP authenticates the client." It does not. The key is self-generated and proves continuity, not identity. Confidential clients still need client authentication, ideally private_key_jwt or mTLS.
  • "DPoP replaces TLS." It does not protect request bodies or most headers and relies on TLS for confidentiality. RFC 9449 is explicit that TLS is still required.
  • "DPoP stops XSS token theft." Malicious script running in the client can ask the browser to sign proofs. DPoP stops exfiltrated tokens being used elsewhere, which is valuable, but injected code acting in place is out of scope. Pair it with Content Security Policy and short lifetimes.
  • "The authorisation server did the work." Binding is only enforced where resource servers check it. A gateway that validates the JWT signature but ignores cnf and the proof gives no protection. See the JWT Security Guide.
  • "Proofs cannot be replayed." Without nonces, an attacker with temporary key access can pre-generate proofs with future iat values. Use nonces and avoid long-lived DPoP-bound tokens where that risk applies.
  • "A DPoP response is always bound." If the server returns token_type: Bearer the token is not bound; clients should not silently carry on.
  • mTLS certificate-bound tokens (RFC 8705): the transport-layer sibling of DPoP. See the mTLS Guide.
  • PKCE and PAR: protect the authorisation code; dpop_jkt extends that protection to the token. FAPI 2.0 requires PKCE with S256 and PAR.
  • Token exchange: when an agent or service exchanges a token downstream, the new token can be sender-constrained too. See the OAuth Token Exchange and Delegation Guide.
  • Token lifetime and session design: DPoP lets you keep tokens short without extra round trips per call. See the Token Lifetime Policy Design Guide and the Token and Session Security Guide.
  • API keys: static keys have no binding at all; moving to OAuth with DPoP is the stronger pattern. See the API Keys vs OAuth Tokens Guide.
  • Federation assurance: NIST SP 800-63C-4 FAL3 needs holder-of-key or bound authenticators, the same proof-of-possession principle applied to assertions. See the SAML vs OIDC Guide.

Practitioner checklist

  • Inventory OAuth clients and APIs and mark which tokens are still pure Bearer.
  • Confirm the authorisation server publishes dpop_signing_alg_values_supported and supports cnf.jkt in introspection.
  • Update resource servers to perform every RFC 9449 Section 4.3 and Section 7 check, including ath and key thumbprint.
  • Reject any DPoP-bound token presented under the Bearer scheme, and alert on it.
  • Generate DPoP keys as non-extractable or hardware-backed keys; never store private keys in browser storage.
  • Enable dpop_bound_access_tokens per client after a pilot, and use dpop_jkt with PKCE or PAR.
  • Turn on server nonces for high-value APIs and shorten access token lifetimes once binding is enforced.
  • Expose DPoP-Nonce and WWW-Authenticate via CORS for browser clients.
  • Track the metrics above and set a date to stop accepting Bearer for each API.

Standards and references

Related NHI Mgmt Group resources: OAuth 2.0 and OpenID Connect Guide · mTLS Guide · OAuth Token Theft Incident Playbook · API Keys vs OAuth Tokens Guide · Machine-to-Machine OAuth (Client Credentials) Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Researched and written by the NHI Mgmt Group editorial team using AI tools, under the editorial direction of Lalit Choda. Facts are drawn from the sources listed on this page and checked by our automated quality process. Last updated 26 October 2026. Spotted an error? Use our contact page.
NHI Mgmt Group, the independent authority on Non-Human Identity, IAM and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.