Foundations
Proof-of-possession (DPoP & mTLS)
A bearer token’s weakness is right there in its name, and sender-constrained tokens fix it. The token is bound to a key, and using it means proving you hold that key. Two standards do this, and Auth51 uses one of them, applied at a finer grain than either was originally aimed at.
The idea: bind the token to a key
Proof-of-possession (PoP) turns a token from “anyone holding this string wins” into “anyone holding this string and the matching private key wins.” The token carries a commitment to a public key; the caller proves possession of the corresponding private key at request time. A token copied out of a log is now a dead artifact. The attacker has the string but not the key.
Two standard ways to do it
mTLS binds the token to a client TLS certificate. It is strong, but it operates at the transport layer, needs certificate provisioning and management, and binds at the connection rather than the request. It says nothing about application-level intent or which agent inside a process is calling.
DPoP, Demonstrating Proof-of-Possession (RFC 9449), does it at the application layer with no PKI. The client holds an ephemeral keypair; the issued token carries a cnf (confirmation) claim naming the public key’s thumbprint, jkt. Each request carries a small signed DPoP proof. A resource server checks the proof’s key hashes to the token’s cnf.jkt, statelessly, with no callback.
Why Auth51 chose DPoP
Agents don’t have stable client certificates; they have short-lived processes that come and go, sometimes many to a host. DPoP fits that: a keypair is generated in the agent process, lives only as long as it’s needed, and never touches disk or the wire. Because the binding is application-layer, it composes cleanly with everything else in the token, the checksum and the intent claim, rather than living off to the side at the transport.
One caveat is worth stating outright. DPoP on its own doesn’t close the intent–execution gap. It proves the client application holds a key, but says nothing about which agent is acting or what the action is. Sender-constraint is one of three ingredients, not the whole answer, which is why Auth51 pairs it with agent identity and intent binding instead of leaning on it alone.
Bound per action, not per session
The other shift is grain. Classic PoP binds a long-lived session token to a key. Auth51 binds a token that’s good for one action and a few minutes. The key still never leaves the process, but the window in which any single token matters is tiny, so even a momentary key compromise buys an attacker almost nothing.
▶How this looks inside an intent token
In Auth51, the cnf.jkt lives right in the intent token alongside the identity and intent claims, and the DPoP proof is generated fresh per request. The Concepts page walks the exact mint-then-prove sequence with a diagram; this page is about the standard the sequence is built from.
One exception: tokens handed to an MCP server carry no cnf, because the server rather than the agent makes the downstream call, so the binding moves to the token the server mints. That’s covered under MCP governance. RFC 9449