| Internet-Draft | TLS-Session-Bound-Tokens | March 2026 |
| Krishnan, et al. | Expires 20 September 2026 | [Page] |
This document defines a mechanism for binding OAuth 2.0 access tokens to a specific mutual TLS (mTLS) session. The binding is achieved through a per-request proof token that incorporates the TLS Exporter value {{!RFC5705}} derived from the current session and an access token hash, signed by the client's private key corresponding to its mTLS certificate. This mechanism prevents stolen bearer tokens from being replayed on a different TLS connection. While applicable to any OAuth 2.0 access token presented over mTLS, this specification is primarily motivated by the Token Exchange protocol {{!RFC8693}}, where multi-hop delegation chains in autonomous, agent-driven architectures create elevated replay risk.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 20 September 2026.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
OAuth 2.0 access tokens are typically bearer tokens: any party in possession of the token can use it to access protected resources, regardless of the presenter's identity or the communication channel. This is a known risk addressed by the OAuth 2.0 Security Best Current Practice {{!I-D.ietf-oauth-security-topics}}.¶
The Token Exchange protocol {{!RFC8693}} amplifies this risk by enabling chained delegation across service boundaries. Each exchange produces a new bearer token, and a compromise at any point in the chain exposes downstream tokens.¶
Existing mitigations address parts of this problem:¶
None of these mechanisms provide TLS-connection-level binding for OAuth 2.0 access tokens in mTLS environments.¶
The rise of autonomous AI agents dramatically amplifies the bearer token replay risk. Unlike traditional OAuth flows where a human initiates discrete requests, agentic AI systems:¶
These characteristics make bearer token replay a first-order threat in agentic AI architectures. This document addresses this gap by binding access tokens to the mTLS connection on which they are presented.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 {{!RFC2119}} {{!RFC8174}} when, and only when, they appear in all capitals, as shown here.¶
This document uses the following terms:¶
This specification defines a proof-of-possession mechanism that binds OAuth 2.0 access tokens to the mTLS connection on which they are presented. While applicable to any OAuth 2.0 access token, it is primarily designed for tokens issued via the Token Exchange protocol {{!RFC8693}}, where multi-hop delegation creates elevated replay risk. The mechanism operates as follows:¶
A token that requires session binding includes a confirmation method claim (tls_exp) containing the TLS Exporter label, which signals to the resource server that the Session-Binding Proof MUST be presented and verified.¶
Both the client and resource server MUST derive the TLS Exporter value using the following parameters:¶
For TLS 1.3, the exporter is derived as specified in Section 7.5 of {{!RFC8446}}. For TLS 1.2, the exporter is derived as specified in {{!RFC5705}}. TLS 1.3 is RECOMMENDED because TLS 1.2 abbreviated handshakes (session resumption) may reuse the same master secret across connections, weakening the binding.¶
Note: By binding to the TLS Exporter rather than the application traffic keys, the binding remains valid across TLS 1.3 KeyUpdate operations. Standard key rotation refreshes traffic keys but does not change the exporter master secret, avoiding unnecessary re-proof cycles while maintaining strong connection binding.¶
The Session-Binding Proof is a JWT with the following structure:¶
{
"typ": "tls-binding-proof+jwt",
"alg": "ES256",
"x5t#S256": "<base64url SHA-256 thumbprint of client certificate>"
}
¶
The alg value MUST match the key type of the client's mTLS certificate. The x5t#S256 value MUST be the base64url-encoded SHA-256 thumbprint of the DER-encoded client certificate, as defined in {{!RFC8705}}.¶
{
"jti": "<unique identifier>",
"ath": "<base64url SHA-256 hash of the access token>",
"ekm": "<base64url TLS Exporter value>",
"iat": 1710820000,
"htm": "POST",
"htu": "/api/resource"
}
¶
The payload claims are defined as follows:¶
An authorization server that supports TLS-session-bound access tokens MUST include a cnf (confirmation) claim in the issued access token (when the token is a JWT) or in the token introspection response. The cnf claim MUST contain:¶
{
"cnf": {
"x5t#S256": "<cert-thumbprint>",
"tls_exp": "EXPORTER-oauth-tls-session-bound"
}
}
¶
cnf members which carry key/binding material rather than boolean flags (see {{!RFC7800}}).¶
The mechanism for requesting and issuing TLS-session-bound tokens is as follows:¶
cnf claim with tls_exp set to the exporter label in the issued token.¶
tls_exp requirement.¶
The following diagram illustrates the complete flow:¶
Client (with cert C) Resource Server
| |
|--- mTLS handshake (client cert C) --------------->|
| |
| Both sides derive: |
| EKM = TLS-Exporter( |
| "EXPORTER-oauth-tls-session-bound", |
| "", 32) |
| |
| Client constructs proof JWT: |
| header = { typ, alg, x5t#S256 } |
| payload = { |
| jti: <unique-id>, |
| ath: SHA256(access_token), |
| ekm: EKM, |
| iat: <unix_timestamp>, |
| htm: "POST", |
| htu: "/api/resource" |
| } |
| sig = Sign(C.privateKey, header || payload) |
| |
|--- HTTP Request --------------------------------->|
| Authorization: Bearer <access_token> |
| Session-Binding-Proof: <proof_jwt> |
| |
| Server verifies: |
| 1. sig matches C.publicKey from mTLS |
| 2. ath matches SHA256(access_token) |
| 3. ekm matches server-derived EKM |
| 4. iat within acceptable skew window |
| 5. htm/htu match actual request |
| 6. jti not previously seen |
| |
|<-- 200 OK ----------------------------------------|
¶
When the client presents the access token to a resource server:¶
The client sends the HTTP request with:¶
The resource server performs the following verifications:¶
a. Standard mTLS verification: Verifies the client certificate as part of the TLS handshake.
b. Token validation: Validates the access token (signature, expiration, audience, etc.).
c. Certificate binding: Verifies that the x5t#S256 in the token's cnf claim matches the presented client certificate.
d. TLS binding required: Checks that cnf.tls_exp is present and a Session-Binding Proof is present.
e. Proof signature: Verifies the proof JWT signature against the public key in the client certificate.
f. Exporter match: Derives the TLS Exporter value for the current session and confirms it matches the ekm claim in the proof.
g. Token hash: Computes SHA-256 of the presented access token and confirms it matches the ath claim.
h. Timestamp: Confirms iat is within the acceptable skew window.
i. Method and URI: Confirms htm and htu match the actual request.
j. Uniqueness: Confirms the jti has not been seen before within the token's validity period.¶
If all verifications succeed, the resource server processes the request. If any verification fails, the resource server MUST reject the request as specified in Section 3.5.¶
When token introspection {{!RFC7662}} is used, the introspection response MUST include the cnf claim with the tls_exp field. This allows resource servers that do not have direct access to the token's claims (e.g., opaque tokens) to determine whether session binding is required.¶
When verification of the Session-Binding Proof fails, the resource server MUST respond with HTTP 401 and include a WWW-Authenticate header with the following error codes:¶
WWW-Authenticate: Bearer error="invalid_proof", error_description="description of failure"¶
The following error code values are defined:¶
iat, and htm/htu mismatch.¶
cnf.tls_exp claim is present) but no Session-Binding-Proof header was provided. This error signals to the client that it must construct and present a proof.¶
The resource server SHOULD include an error_description parameter with a human-readable explanation of the specific verification failure.¶
This specification extends RFC 8705 by adding session-level binding on top of certificate binding. The x5t#S256 claim from RFC 8705 is reused. Deployments MAY support both mechanisms simultaneously: RFC 8705 provides certificate binding, while this specification adds per-request session binding.¶
DPoP and this specification address similar goals (proof-of-possession) but use different mechanisms and binding targets:¶
In environments where both mTLS and DPoP are available, this specification provides stronger security guarantees because it binds to both the client identity (certificate) and the transport session (exporter).¶
The WIMSE Workload Identity Token (WIT) and Workload Proof Token (WPT) defined in {{!I-D.ietf-wimse-s2s-protocol}} provide a similar proof-of-possession mechanism for workload-to-workload communication. This specification is compatible with WIMSE and can be used in conjunction with WIT/WPT when mTLS-based session binding is required for tokens obtained via RFC 8693 exchange.¶
The Transitive Attestation profile {{!I-D.draft-mw-wimse-transitive-attestation}} addresses a complementary problem: binding an identity to a verified execution environment ("Proof of Residency"). While this specification binds tokens to a TLS session to prevent network-level replay, Transitive Attestation binds identities to a hardware-rooted host to prevent credential export. In high-assurance deployments, both mechanisms MAY be combined: Transitive Attestation ensures the token is used from the correct host, and TLS session binding ensures it is used on the correct connection.¶
This specification does not modify the token exchange protocol itself. The authorization server's token exchange endpoint continues to operate as specified in {{!RFC8693}}. The session binding is applied to the resulting access token through the cnf claim. While this specification is applicable to any OAuth 2.0 access token, RFC 8693 Token Exchange is a primary motivator: each hop in a delegation chain produces a new bearer token, and session binding contains the blast radius of any single token compromise to the specific TLS connection on which it was issued.¶
In deployments where TLS is terminated at the application server (pass-through mode), this specification works without modification. Both the client and server have direct access to the TLS Exporter value.¶
When a TLS-terminating proxy (e.g., a load balancer or API gateway) sits between the client and the resource server, the proxy MUST forward the following information to the backend:¶
A new HTTP header is defined for conveying the exporter value:¶
TLS-Exporter: <base64url-encoded exporter value>¶
The proxy MUST derive the exporter using the label and parameters specified in Section 2.2 from the client-facing TLS session, and forward it in this header over a trusted, integrity-protected connection to the backend.¶
The backend resource server MUST use the forwarded exporter value (instead of its own locally-derived value) when verifying the Session-Binding Proof.¶
Security Warning: The TLS-Exporter header contains security-sensitive material. The connection between the proxy and backend MUST be integrity-protected (e.g., via a separate mTLS connection or a trusted network). The backend MUST NOT accept this header from untrusted sources.¶
This section addresses security considerations in addition to those described in the OAuth 2.0 Security Best Current Practice {{!I-D.ietf-oauth-security-topics}}.¶
The TLS Exporter value is cryptographically derived from the TLS handshake transcript and is unique per TLS connection. An attacker who intercepts a bearer token cannot replay it on a different TLS connection because the exporter value will not match.¶
The Session-Binding Proof is signed with the client's mTLS private key. An attacker on a different host cannot produce a valid proof without possessing the private key.¶
Even if an AI agent's bearer token is exfiltrated via prompt injection, tool-call side channels, or log leakage, the attacker cannot produce a valid Session-Binding Proof because they lack both the client's private key and the ability to derive the TLS Exporter value from the legitimate session.¶
Each hop in a delegation chain (A→B→C→D) uses a distinct mTLS session with a distinct exporter value. A token stolen at any point in the chain is bound to that specific session and cannot be replayed on a different hop.¶
Within the same TLS session, an attacker with access to the channel (e.g., a compromised middleware component) could observe and replay requests. This risk is mitigated by:¶
If the client's mTLS private key is compromised, the attacker can produce valid proofs. This risk is mitigated by:¶
The TLS-Exporter header introduces a trust dependency on the proxy. A compromised proxy could forge exporter values. Mitigations include mutual authentication between proxy and backend, and restricting the header to trusted network segments.¶
This specification registers the following confirmation method in the IANA "OAuth Token Confirmation Methods" registry established by {{!RFC7800}}:¶
This specification registers the following client metadata value:¶
This specification registers the following HTTP header fields:¶