Learning outcomes
- Explain why a bearer token is usable by any holder.
- Compare DPoP and mutual-TLS certificate-bound token mechanisms.
- Validate token-to-key binding and request proof at the resource server.
- Test token, proof, endpoint, method, nonce, and replay failure cases.
Protocol roles
The authorization server issues an access token. The client presents it. The resource server validates it and authorizes a request. With a bearer token, possession is the only proof needed to use the token. A sender-constrained token also identifies a key. The client must prove possession of that key when it uses the token.
RFC 9700 Section 4.10.1 describes two current mechanisms. RFC 8705 binds a token to the client certificate used for mutual TLS. RFC 9449 uses an application-layer DPoP proof signed by a client key. Audience restriction remains an independent control under RFC 9700 Section 4.10.2.
Message flow
For mutual-TLS binding, the client authenticates to the authorization server with a certificate or presents the binding certificate during the token request. The authorization server places or associates the certificate thumbprint with the access token. The client later establishes mutual TLS with the resource server using the same key. The resource server compares the observed certificate thumbprint with the token binding.
For DPoP, the client creates a key pair. It sends a signed DPoP proof to the token endpoint. The authorization server binds the access token to the public-key thumbprint. For each resource request, the client creates a new proof with the request method, target URI, issuance time, unique identifier, and access-token hash. The resource server validates both the access token and proof, then compares their key binding.
The proof is request data. The token still carries or references the granted authority. The resource server must validate both before it performs local permission checks.
Validation and failure cases
For both mechanisms, validate the token issuer, audience, time, status, type, and key confirmation. Then validate proof of possession from the same key.
For DPoP, verify the proof signature with the public key in its header, use an allowed asymmetric algorithm, compare the method and normalized target URI with the current request, enforce a short proof time window, reject a reused proof identifier, and compare the access-token hash. Apply an authorization-server or resource-server nonce when the deployment requires it.
For mutual TLS, validate the TLS client certificate under the route's trust policy, confirm private-key possession in the handshake, and compare the exact certificate thumbprint bound into the token. Define behavior across TLS terminators. A downstream service cannot validate the original client certificate if an intermediary does not preserve a trustworthy binding.
Test these failures:
- A stolen token without the bound key.
- The correct token with another key or certificate.
- A replayed DPoP proof.
- A proof for another HTTP method or target URI.
- A proof with an old time, duplicate identifier, wrong nonce, or wrong token hash.
- A certificate-bound token presented through a connection with another certificate.
- The correct token and key used at the wrong audience.
- Theft of both token and exportable private key.
Design tradeoffs and residual risk
DPoP works at the application layer and can support public clients. It requires canonical request handling, replay state, secure client-key storage, clock policy, and proof generation for each request. Mutual TLS can protect keys through the TLS stack or hardware and has mature transport support. It adds certificate provisioning and can be difficult through intermediaries.
Sender constraint reduces replay value when only a token leaks. It does not help when malware or script injection can use the key, when both token and key are copied, or when the legitimate client is controlled. It also does not grant object permission. Audience restriction, short lifetime, secure storage, local authorization, and detection remain necessary.
Pomerium boundary
Pomerium documents bearer tokens for programmatic access and can require client certificates on routes. Operators must verify whether a particular Pomerium and upstream flow implements standards-based token binding before they claim sender constraint. A TLS client-certificate policy alone does not convert an unrelated bearer token into a certificate-bound OAuth token.
Exercise
Choose one sensitive API client. Compare three designs: bearer, DPoP, and mutual-TLS-bound access tokens. Record client environment, key storage, proxy hops, proof validator, replay store, audience, rotation method, and compromise response.
Implement one sender-constrained test flow. Capture no token or private key. Record only hashes and outcomes. Replay the token without the key, the proof with another method, the proof twice, and the token at another audience. Each request must fail for the expected reason.
Evaluation checklist
- Can each verifier connect the access token to one exact public key or certificate?
- Does the resource server validate a fresh request-specific proof and the token itself?
- Are method, target URI, time, identifier, nonce, token hash, and audience checked where applicable?
- Does the design state what happens at TLS terminators and reverse proxies?
- Is the residual risk of token-and-key compromise explicit?
Next learning unit
Token Issuer and Audience
Accept a token only from a trusted issuer and only at the resource audience for which the token was issued.
