Sender-constrained tokens: Why mTLS and DPoP exist, and what killed Token Binding
Bearer tokens prove nothing about who holds them. mTLS and DPoP fix that. Token Binding tried and failed, and the reason why matters more than the failure itself.
Bearer tokens are convenient and ubiquitous, but they carry a fundamental weakness: anyone who intercepts one can use it. The token itself proves nothing about who is presenting it. Sender-constraining is the family of techniques that fixes this by cryptographically binding a token to the client that legitimately holds it, so a stolen token is useless without the corresponding key material. Three RFCs have addressed this problem: Mutual TLS for OAuth (RFC 8705), Demonstrating Proof of Possession (RFC 9449), and Token Binding (RFC 8471). Only two of them are in active use today, and understanding why the third failed is as instructive as understanding how the surviving two work.
The problem they all set out to solve
OAuth 2.0 access tokens are bearer credentials. The specification itself draws an analogy to cash: whoever holds the token can spend it. This is fine when the channel is secure and tokens are short-lived, but it creates real risk at the edges: token leakage from logs, SSRF attacks that exfiltrate tokens from internal services, open redirects that redirect tokens to attacker-controlled servers, and token replay from compromised intermediaries.
Sender-constraining makes a stolen token worthless in isolation. The server that issued the token ties it to a specific public key. When the client presents the token, it must also prove possession of the corresponding private key. An attacker who intercepts the token but not the key cannot use it.

Mutual TLS (RFC 8705)
Mutual TLS, sometimes written mTLS, extends the standard TLS handshake by requiring the client to present a certificate, not just the server. RFC 8705 defines two mechanisms for using this in OAuth:
- PKI-bound tokens associate the access token with the client's certificate using the certificate's SHA-256 thumbprint (the
cnf.x5t#S256claim in the token). The authorization server records this thumbprint when issuing the token. At the resource server, the TLS layer exposes the client certificate, and the resource server verifies that the thumbprint in the token matches the certificate presented. - Self-signed certificate-bound tokens follow the same pattern but allow the client to generate its own certificate without involving a certificate authority. The thumbprint of the self-signed certificate becomes the binding claim. This is substantially easier to operate and is the more common deployment pattern.
The appeal of mTLS is that the binding happens entirely at the transport layer. Application code does not need to change to issue or verify proof-of-possession. The TLS stack handles key negotiation; the resource server only needs to read the certificate from the connection and compare a hash. This makes mTLS straightforward to retrofit onto existing infrastructure, particularly in environments that already enforce mutual TLS for service-to-service communication (zero-trust network architectures, for example).

The drawbacks are equally obvious. mTLS requires end-to-end TLS termination at the resource server, which conflicts with architectures that terminate TLS at a load balancer or API gateway. Certificate management at scale is operationally demanding, and rotating compromised client certificates requires coordination. mTLS is also entirely unsuitable for browser-based clients: browsers do not expose the TLS client certificate to JavaScript, so a single-page application cannot use mTLS-bound tokens without a backend component.
mTLS-bound tokens are widely deployed in high-assurance, backend-to-backend contexts: financial APIs, open banking platforms, and regulated industries where strong client authentication is already a compliance requirement. The FAPI (Financial-grade API) security profiles mandate mTLS as one of their two acceptable binding mechanisms.
DPoP (RFC 9449)
DPoP, or Demonstrating Proof of Possession, takes a different architectural approach. Rather than binding at the TLS layer, DPoP binds at the application layer using a proof JWT that the client generates and attaches to each request as an HTTP header.
The flow works like this. The client generates an asymmetric key pair. When it requests an access token, it sends a DPoP header containing a signed JWT (the DPoP proof). This JWT includes the public key, the HTTP method and URI of the current request, a timestamp, and a unique nonce to prevent replay. The authorization server verifies the proof, extracts the public key, and embeds a hash of that key in the issued access token as a cnf.jkt claim.
On every subsequent request to a resource server, the client again attaches a fresh DPoP proof header. The resource server validates the proof: it checks the signature against the public key in the token, verifies the method and URI match the current request, confirms the timestamp is recent, and checks the nonce. If all of these pass, the token is accepted.
Because DPoP operates entirely over HTTP headers, it works regardless of how TLS is terminated. A request can traverse a load balancer, an API gateway, and several microservices; as long as the DPoP header travels with the Authorization header, the binding is intact. This also means DPoP works in browsers: JavaScript can generate and hold an asymmetric key pair (using the Web Crypto API), sign DPoP proofs, and attach them to fetch requests. No native browser capabilities beyond standard cryptography are needed.
DPoP is somewhat more complex to implement than mTLS. Clients must generate key pairs and sign a new proof JWT on every request. Servers must verify the proof, enforce nonce freshness (which requires coordination in distributed deployments), and handle clock skew. The nonce mechanism in particular requires either a stateful check or a short-lived, server-issued nonce, both of which have implementation costs.

Despite this, DPoP has seen rapid adoption since its standardisation in 2023. It is supported in FAPI 2.0 alongside mTLS, and is the preferred binding mechanism for browser-based clients, mobile applications, and any architecture where TLS is not end-to-end at the application server.
Token Binding (RFC 8471)
Token Binding was designed to solve the same problem, and on paper it was elegant. The idea was to bind tokens (and indeed any security token, not just OAuth tokens) to the underlying TLS connection using a key that was derived from and pinned to that specific TLS session. The binding was transparent to application code: the TLS stack negotiated the binding key as part of the handshake, and the browser or client would automatically attest to it via a Sec-Token-Binding HTTP header.
RFC 8471 defined the core Token Binding protocol. RFC 8472 extended it for transport-layer security, and RFC 8473 defined its application to OAuth. The IETF working group was active, the specifications were thorough, and at one point Microsoft and Google were both actively championing the approach.
It never shipped.
Why Token Binding failed
The architectural appeal of Token Binding was also its fatal flaw. Because the binding lived inside the TLS layer, the entire ecosystem had to participate for it to work. The TLS implementation in the client had to support the Token Binding extension. The TLS implementation on the server had to support it. Load balancers and proxies that terminated or forwarded TLS had to understand it, either terminating and re-binding or passing the bound key through. Application-layer tokens were tied to the infrastructure layer in a way that made incremental deployment nearly impossible.
Google shipped Token Binding support in Chrome 65 in 2018, but removed it entirely in Chrome 130 in 2024, citing insufficient adoption and maintenance cost. No other browser shipped it. Firefox and Safari never implemented it. Without browser support, Token Binding could not serve as a mechanism for browser-based OAuth clients.

The server side was equally sparse. IIS added experimental support. A small number of servers implemented it, but no major open-source TLS library made it a default feature. CDNs and load balancers, which sit at the TLS termination layer where Token Binding lives, almost universally ignored it.
The fundamental lesson is about protocol layering. Token Binding required simultaneous buy-in from browser vendors, server libraries, load balancer vendors, and application developers. DPoP and mTLS, by contrast, require only that the application layer cooperate: you can deploy DPoP with any TLS stack, any load balancer, and any browser that supports standard Web Crypto. The complexity is higher at the application level, but it can be deployed incrementally, which is the only realistic path for any security mechanism to achieve adoption.
Comparing the three mechanisms
Choosing between mTLS and DPoP
The short answer: use mTLS for machine-to-machine flows where you already control both endpoints and certificate management is feasible; use DPoP for browser-based clients, mobile applications, or any architecture where TLS terminates before the application server.
In practice, many platforms need both. A financial services platform might use mTLS-bound tokens for backend service calls between internal systems and DPoP-bound tokens for the mobile and web clients facing customers. FAPI 2.0 explicitly accommodates this by allowing either mechanism, selected at the client registration level.
The operational difference that most often determines the choice is TLS termination. If your API gateway terminates TLS and proxies requests to backend services, mTLS-bound tokens require the gateway to extract the client certificate thumbprint and pass it downstream, either via a header or by re-establishing mutual TLS to each backend. This is solvable but requires gateway configuration that many teams do not already have. DPoP travels as a plain HTTP header and requires no special gateway behaviour.
What Token Binding taught us
Token Binding is not a failure of specification quality; the RFCs are well written and the security properties were sound. It is a failure of deployment realism. Security protocols that require coordinated ecosystem upgrades across browser vendors, TLS libraries, and network infrastructure face an adoption barrier that application-layer protocols simply do not. DPoP and mTLS both accepted the constraint that they had to work with existing infrastructure rather than requiring it to change.
This is worth remembering when evaluating future sender-constraining proposals. A mechanism with slightly weaker theoretical properties but broad, incremental deployability will protect more tokens in practice than a theoretically superior mechanism that never ships.
Conclusion
Sender-constrained tokens represent a meaningful improvement in OAuth security posture, and the two mechanisms worth deploying today are mTLS and DPoP. mTLS is the right choice when you have backend services, controlled infrastructure, and existing certificate management. DPoP is the right choice when you need to support browser or mobile clients, or when your architecture includes TLS-terminating intermediaries. Token Binding, despite its promise, is a useful case study in how good cryptography alone is not enough: adoption requires incremental deployability, and Token Binding had none.