A certificate bound access token is tied to the TLS client certificate the partner used to get it. Your API checks that the certificate on the connection matches the one recorded in the token. If they differ, it rejects the call. A copied token is useless from another machine.
The idea in one paragraph
RFC 8705 defines two things: client authentication to the authorization server using mutual TLS, and access and refresh tokens bound to the client certificate. When the partner connects to the token endpoint with mutual TLS, the authorization server can bind the token it issues to that certificate. At the API, mutual TLS then serves purely as proof of possession.
How the check works
- The partner's server connects to the token endpoint over mutual TLS and presents its client certificate.
- The authorization server issues an access token and records a hash of the certificate. For a JWT access token, the hash goes in the cnf claim as x5t#S256, a base64url encoded SHA-256 hash of the certificate. For opaque tokens the API can learn it through token introspection.
- The partner calls your API over a mutually authenticated TLS connection using the same certificate, sending the token in the standard bearer header.
- Your API reads the client certificate from its TLS layer and compares its hash with the one tied to the token.
- On a mismatch the API rejects the call with HTTP 401 and the invalid_token error code, as RFC 8705 requires.
The check at step 4 is the whole point. The token is only half of the credential, and the certificate is the other half.
Design points for API owners
| Topic | What RFC 8705 says or implies | What to do |
|---|---|---|
| Advance knowledge | The resource server must know in advance that mutual TLS applies, since the token arrives after the TLS handshake | Serve bound resources on their own hostname or require it everywhere |
| Certificate types | Self signed or public key infrastructure certificates are both allowed | Pick one and document how partners enrol certificates |
| TLS termination | Proxies and load balancers may terminate TLS | Make sure the certificate reaches the component that checks it, through a trusted channel |
| Error response | 401 with invalid_token on mismatch | Return the same response for all token failures |
The termination point is where deployments go wrong. If a load balancer terminates TLS and passes the certificate to the API as a header, the API must trust that header only when it comes from that load balancer, and the load balancer must strip any copy sent by the client.
When to choose it
This approach fits server to server integrations where you can manage certificates with a small number of partners. It is less suited to browsers and mobile apps, where client certificate handling is awkward. For those, DPoP is the usual alternative, and RFC 9449 states this reasoning itself.
Operational notes
Certificates expire, so give partners a clear renewal process and an overlap window where two certificates are valid. Record which certificate each partner uses and when it was enrolled. Alert when a token is presented with an unknown certificate, since it could be a stolen token being tested.
Combine binding with the basics: short token lifetimes, narrow scopes, and an audience restriction so a token for one API cannot be used at another.
Safeguard's asset discovery helps you find API hosts and versions you may have lost track of, and its SBOM and dependency scanning shows which libraries ship in your builds. You can start with the free scan at gold.safeguard.sh/scan.
Quick check
Does the partner need a different certificate for each token?
No. The binding is to the certificate used at the token endpoint, which the partner keeps using for API calls until it renews.
What status code should a mismatch return?
RFC 8705 specifies HTTP 401 with the invalid_token error code.
Sources
- RFC 8705, OAuth 2.0 Mutual-TLS Client Authentication and Certificate-Bound Access Tokens
- RFC 9449, OAuth 2.0 Demonstrating Proof of Possession (DPoP)
Last reviewed: 19 October 2026.