cd /news/ai-agents/what-is-dpop-rfc-9449-sender-constra… · home › topics › ai-agents › article
[ARTICLE · art-159622] src=contextiq.trango-compute.com ↗ pub= topic=ai-agents verified=true sentiment=· neutral

What Is DPoP (RFC 9449)? Sender-Constrained Tokens for AI Agents Explained

DPoP, the sender-constraining mechanism defined in RFC 9449, binds OAuth 2.0 access tokens to a client-held private key so that a leaked token cannot be used without a matching proof JWT, addressing a risk the RFC's explainer says is acute for AI agents whose tokens pass through prompts, tool outputs, transcripts and telemetry. Each request carries a proof in a DPoP header containing a jti with at least 96 bits of randomness, the htm method, the htu target URL, an iat timestamp and, for API calls, an ath claim holding the base64url SHA-256 hash of the access token; the authorization server ties the token to the key via the cnf.jkt confirmation claim and returns token_type "DPoP". Servers can demand a nonce, replying with HTTP 400 and the use_dpop_nonce error plus a DPoP-Nonce header (401 from a resource server), and Personal Agent Protocol Draft 0.1 binds its short-lived session tokens to a DPoP key while allowing bearer tokens only for MCP servers, which it flags as less secure.

by read5 min views27 publishedOct 9, 2026

DPoP (RFC 9449) ties an OAuth access token to a key so a stolen token fails: proof JWTs, cnf jkt, server nonces, and how PAP, FAPI 2.0 and MCP servers use it.

DPoP, short for Demonstrating Proof of Possession, is defined in RFC 9449. The RFC's abstract calls it "a mechanism for sender-constraining OAuth 2.0 tokens via a proof-of-possession mechanism on the application level." In plain terms: an access token stops being a password-like string that works for whoever holds it, and becomes a token that only works together with a private key the legitimate client keeps.

The problem: bearer tokens #

A normal OAuth access token is a bearer token. Anyone who gets a copy can use it until it expires. Tokens leak through logs, error reports, URLs, browser extensions and compromised servers. This is a particular concern for AI agents, whose tokens can pass through prompts, tool outputs, transcripts and telemetry. DPoP does not stop a leak. It makes a leaked token far less useful.

How it works, step by step #

  1. The client makes a key pair and keeps the private key.
  2. For each request, it signs a short proof (a JWT) and sends it in aDPoP header.
  3. The authorization server binds the token to the key. The token response hastoken_type: "DPoP" , and the access token is tied to the public key through a confirmation claim,cnf.jkt , which is a thumbprint of that key (RFC 9449 section 6.1).
  4. The client calls the API withAuthorization: DPoP <token> plus a fresh proof.
  5. The resource server checks that the proof is valid, that its key matches the one the token is bound to, and that the proof matches this request.

A thief with only the token cannot create a valid proof, so the token fails.

What is inside a proof #

The proof is a JWT with a header and claims (RFC 9449 section 4.2):

Part Value Why
Header typ dpop+jwt Marks it as a DPoP proof
Header alg An asymmetric algorithm, never none The signature type
Header jwk The client's public key Lets the server verify the signature and compute the thumbprint
jti A unique ID with at least 96 bits of randomness Lets servers reject a replayed proof
htm The HTTP method Ties the proof to this request type
htu The target URL, without query or fragment Ties the proof to this endpoint, so it cannot be reused elsewhere
iat Creation time Keeps proofs fresh
ath Base64url SHA-256 hash of the access token Present when calling an API; ties the proof to one token
nonce A server-provided value Present when the server asks for one

An illustrative decoded proof for an API call (all values fictional):

{
  "header": { "typ": "dpop+jwt", "alg": "ES256", "jwk": { "kty": "EC", "crv": "P-256", "x": "…", "y": "…" } },
  "claims": {
    "jti": "f3a9c1d2-7b64-4e0a-9d55-2c8b1e7a0001",
    "htm": "GET",
    "htu": "https://api.example.test/orders/1042",
    "iat": 1791555000,
    "ath": "fUHyO2r2Z3DZ53EsNrWBb0xWXoaNy59IiKCAqksmQEo"
  }
}

Server nonces #

A client can sign proofs ahead of time, or an attacker who controls the client can generate them for the future. To prevent that, a server may require a nonce it chooses. The RFC describes the flow: an authorization server replies with HTTP 400, the error use_dpop_nonce and a DPoP-Nonce header (a resource server uses a 401 challenge instead); the client retries with that value in the proof's nonce claim (section 8). Invalid proofs get invalid_dpop_proof.

Where DPoP appears in the agent world #

  • Personal Agent Protocol. The PAP Draft 0.1specification makes its short-lived session tokens bound to a DPoP key. Its one exception is MCP servers, where it allows bearer tokens and flags them as less secure. Seewhat PAP is .
  • FAPI 2.0. The OpenID Foundation'sFAPI 2.0 Security Profile requires sender-constrained access tokens, using either mutual TLS (RFC 8705) or DPoP. SeeFAPI and agent checkout .
  • OAuth metadata. A server advertises support withdpop_signing_alg_values_supported in its authorization server metadata (RFC 9449 section 5.1). A protected resource can publishdpop_bound_access_tokens_required in its RFC 9728 metadata to say it always requires DPoP-bound tokens.

DPoP vs plain bearer vs mutual TLS #

Bearer token DPoP Mutual-TLS-bound token
Stolen token alone is usable Yes No No
Binding is to Nothing A key held by the client A client certificate
Works at application level Yes Yes Needs TLS-level client certificates
Server field to look for none dpop_signing_alg_values_supported tls_client_certificate_bound_access_tokens

What DPoP does not do #

The RFC is direct about limits:

  • It is "not a substitute for a secure transport" and must always be used with HTTPS.
  • It does not protect a client whose private key is stolen, or malicious code running inside the client. Code in the client's context can create proofs, including future-dated ones, and pre-generated proofs are possible. Server-chosen nonces help.
  • It does not protect request integrity. A proof covers the method and URL, not the body or other headers (section 11.7).

How to check a server #

Look at what an authorization server publishes. The OIDC Inspector has a "FAPI 2.0 Metadata Signals" card that reports whether dpop_signing_alg_values_supported and tls_client_certificate_bound_access_tokens are published. For an OAuth-protected MCP server, the Agent Protocol Inspector shows the same signals for its authorization server. Two cautions: a field that is not published does not prove the capability is missing, and a published field is a claim, not proof the server enforces it. Neither tool tests DPoP behaviour or performs a conformance check.

Sources #

Follow Trango Compute on LinkedIn

We post updates on new tools, context engineering patterns, and LLM cost research.

Follow on LinkedIn

── more in #ai-agents 4 stories · sorted by recency
── more on @dpop 3 stories trending now
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
→ Live at https://your-agent.zahid.host ✓
Get free account → Pricing
from €0/mo · no card required
LIVE [news/what-is-dpop-rfc-944…] indexed:0 read:5min 2026-10-09 · —