Security
SecurityIntermediate

mTLS vs TLS Explained: Two Identities, One Connection

mTLS vs TLS explained through the handshake, certificate trust, authorization and proxy boundaries, with a reproducible local demo and eight checked outcomes.

Cover image: mTLS vs TLS Explained: Two Identities, One Connection
Contents

Your client checks the certificate, the connection is encrypted, and the API shows a reassuring padlock. None of that tells the API who is calling. A stranger can establish the same ordinary HTTPS connection and ask for the same endpoint. The application still needs to decide what to do with the request.

Mutual TLS adds a second identity check: the server asks the client to prove itself too. That is a useful boundary for services, devices and partner APIs. But the surprising part comes next: a client can present a perfectly valid certificate, complete mTLS, and still deserve 403 Forbidden. This article follows that distinction from the handshake to a working local example.

mTLS vs TLS: two identity passports face a separate access gate, illustrating mutual authentication and the authorization decision that follows.

What is mTLS?

mTLS is TLS with mutual certificate authentication, not a separate transport protocol. In the familiar certificate-based HTTPS case, the client authenticates the server. With mTLS, the server also requests and verifies a client certificate and proof that the client controls its private key. This is the meaning used in RFC 8705, section 1.2.

The qualification matters: TLS also has PSK and resumption modes. “TLS authenticates only the server” is a useful description of ordinary certificate-based HTTPS, not a definition covering every possible TLS handshake.

mTLS vs TLS: the key differences

mTLS vs TLS: the key differences
Question Ordinary server-authenticated TLS mTLS
Does the client authenticate the server? Yes Yes
Does TLS authenticate the client with a certificate? No Yes, when required and successfully verified
Does the client need its own certificate and private key? No Yes
Is application data encrypted? Yes Yes
Is the encryption automatically stronger? No No extra encryption layer is implied
Who decides whether /orders is allowed? Application or gateway policy Application or gateway policy
What must operations manage? Server credentials and trust Both sets of credentials, trust and client policy

A useful analogy is calling a business whose number you have verified. You know whom you reached; the person answering has not established who you are. mTLS adds the return identity check. It does not give the caller permission to approve a refund.

mTLS vs HTTPS: can an HTTPS API use mTLS?

Yes. HTTPS is HTTP communication secured with TLS, as described in RFC 9110. An HTTPS endpoint can additionally require client-certificate authentication: that is HTTPS using mTLS. They are not competing choices. The extra certificate establishes the connecting client’s identity; the application can still require a session or access token and enforce permissions.

The TLS 1.3 handshake: a certificate is only half the proof

A certificate is public. Copying client.crt does not copy the ability to authenticate as that client. The private key supplies the missing proof: CertificateVerify signs handshake material, binding possession of that key to this connection.

mTLS vs TLS handshake: both flows authenticate the server; the mutual flow adds CertificateRequest, client Certificate and client CertificateVerify before the client Finished.
A condensed full TLS 1.3 handshake. The extra client proof is inside the encrypted handshake.

In a full certificate-based TLS 1.3 handshake:

  1. ClientHello and ServerHello establish the parameters and key exchange.
  2. The server sends its encrypted handshake messages, including its certificate, proof and Finished. For mTLS it also sends CertificateRequest.
  3. The client verifies the server. If requested, it sends its certificate and CertificateVerify, followed by Finished.
  4. The server verifies the client before admitting it under the configured client-authentication policy.

TLS 1.3 encrypts the client-certificate exchange. In a typical initial TLS 1.2 handshake, that certificate was visible to a passive observer. If the client has no suitable certificate, it sends an empty certificate message; the server can abort or continue without certificate authentication. Required mTLS must actually reject the unauthenticated case.

The current TLS 1.3 specification is Eric Rescorla’s RFC 9846, published in July 2026 and obsoleting RFC 8446. The wire version remains TLS 1.3. Its publication is not a claim that every library has implemented every revision.

The picture shows a full handshake. Resumption and 0-RTT are separate cases; do not assume a fresh client certificate was checked for early data. Early data can also be replayed. For a sensitive API, keep it disabled unless the application deliberately implements an appropriate replay-safe design.

Three checks that should never collapse into one

Consider two services: checkout and reporting. Both have certificates from the same trusted issuer. Only checkout may submit orders.

Three checks that should never collapse into one
Check Question Example failure
Certificate validation Does this credential satisfy the configured trust, validity and purpose rules? Unknown issuer, expired certificate, wrong EKU
Peer identity Which identity or exact credential did the verified peer prove? Credential belongs to reporting, not checkout
Authorization May that peer perform this operation on this resource? Authenticated reporting calls a checkout-only endpoint
mTLS authorization: certificate verification, peer identity and request permission are three gates; a trusted reporting client passes TLS but receives HTTP 403 at the orders policy.
Trusting an issuer does not mean authorizing every certificate it issues.

An issuer can legitimately sign credentials for hundreds of workloads. Accepting every one as an administrator would be an application-policy mistake, even if all cryptography were correct. A certificate’s identity also needs an agreed meaning: an expected SAN, a registered credential, or a workload identity whose issuer and trust domain you control. Reading a plausible common name from an arbitrary certificate is insufficient.

This is also why “mTLS blocks malicious API requests” is too broad. It can reject clients that cannot satisfy the certificate policy. A compromised client with a valid key can still send harmful requests. Input validation, authorization, rate limits and containment remain necessary.

A valid certificate answers a trust question. Permission to read another customer’s order is a different question.

A local mTLS example with eight checked outcomes

The complete demo uses Node.js built-ins and the installed OpenSSL CLI. It creates separate temporary server and client CAs, issues test certificates, binds only to 127.0.0.1, runs the cases and removes the temporary keys afterward. No npm dependencies or production credentials are needed.

Download the source, inspect it, and run it in an empty working directory:

Terminal window
node --version
openssl version
node demo.mjs

The core server configuration is small:

demo.mjs — TLS verification
const server = https.createServer({
key: serverKey,
cert: serverCertificate,
ca: clientCa,
requestCert: true,
rejectUnauthorized: true,
minVersion: 'TLSv1.3',
maxVersion: 'TLSv1.3',
}, handler);

requestCert asks for the client credential. rejectUnauthorized makes verification failures fatal. The custom ca identifies the client issuer trusted by this server; the client separately trusts the server CA and checks the server’s hostname. These are independent directions of trust. Node.js TLS options.

Then the handler makes a deliberately narrow authorization decision:

demo.mjs — application authorization
const allowed = new X509Certificate(approvedClientPem).fingerprint256;
function handler(req, res) {
const permitted = req.method === 'GET' && req.url === '/orders' &&
req.socket.authorized &&
req.socket.getPeerCertificate().fingerprint256 === allowed;
res.writeHead(permitted ? 200 : 403);
res.end(permitted ? 'orders accepted\n' : 'access denied\n');
}

This lab pins one exact leaf certificate to make the second decision visible. It is not a general identity directory: renewing that certificate requires updating the pin. Production workload policies usually map an established identity to permissions instead of maintaining leaf fingerprints by hand.

The following outcomes were reproduced on November 4, 2026, with Node.js 24.22.2 and 26.13.0, using OpenSSL CLI 4.1.0:

A local mTLS example with eight checked outcomes
Case Observed result Where it stops
Approved client, correct server name HTTP 200 Request accepted
Approved client requests /admin HTTP 403 Application resource policy
No client certificate Connection rejected TLS client authentication
Certificate from an untrusted client CA Connection rejected TLS certificate validation
Trusted issuer, but only serverAuth EKU Connection rejected TLS certificate purpose validation
Valid client certificate not on the application allowlist HTTP 403 Application authorization
Same unapproved client adds a forged Client-Cert header HTTP 403 Application still uses the TLS peer, not the header
Approved client connects using the wrong server name Connection rejected Client’s server-identity check

The success and 403 cases negotiated TLS 1.3. The rejected connections produced no application response. Error strings vary by runtime; for example, the client saw ECONNRESET for some server-side verification failures while the server reported a TLS verification error. The script checks those failures rather than counting any timeout as success.

These are functional checks, not a throughput benchmark. They demonstrate the boundary between a failed handshake and a denied authenticated request. The forged-header case uses a direct server that ignores such headers; it does not simulate or certify a production proxy deployment.

The reverse-proxy trap: where does mTLS end?

A load balancer changes the story. If the client completes mTLS with the edge, the edge authenticated the client. A new TLS connection from edge to application proves something about that second peer. It does not automatically transport the original client’s identity.

mTLS reverse proxy trust boundary: the client authenticates to the edge, a separate protected connection reaches the application, and direct access or forged certificate headers must be blocked.
TLS termination creates an identity handoff. The application must trust the handoff's sender and its processing rules.

An application that accepts Client-Cert: admin from any reachable caller has turned a proof of private-key possession into a user-controlled string.

There is an IETF specification for this handoff: RFC 9440, Client-Cert HTTP Header Field, published in 2023 as an Informational RFC. It defines Client-Cert and Client-Cert-Chain; it does not make arbitrary headers trustworthy. The proxy removes or overwrites incoming instances, validates the client under its policy and supplies the verified certificate information. The origin needs a trustworthy relationship with that proxy and protection against bypassing it. RFC 9440, processing rules and security considerations.

For an actual deployment, establish three properties together:

  • The application is reachable through the intended proxy path; alternate ingress cannot inject an identity.
  • The proxy-to-origin connection and peer are appropriately protected and authenticated.
  • Identity headers come from the proxy’s validated connection state, with client-supplied values removed or rejected.

“HTTPS on both hops” alone does not establish these properties. Inspect the selected product’s forwarding format and trust configuration; X-Forwarded-Client-Cert conventions are not interchangeable with RFC 9440’s encoding.

mTLS vs OAuth and JWT: different jobs, useful together

mTLS can establish the calling service’s identity. OAuth can describe delegated access, and a JWT may carry user or permission claims. An order placed by a checkout service on behalf of a customer needs both stories: which service connected, and what that request is allowed to do for that customer. The JWT explainer covers the token’s verification side.

Merely adding mTLS to a token endpoint does not make every access token resistant to theft. RFC 8705 defines certificate-bound access tokens. The resource server must enforce the binding to the certificate presented on its connection, using cnf.x5t#S256 for the JWT thumbprint representation. Authentication at the token endpoint and binding the resulting token are distinct features. Certificate changes must also be coordinated with bound tokens. RFC 8705, sections 3 and 6.3.

For a public browser application, ordinary HTTPS with suitable session or OAuth handling is often the practical choice. Managed devices and machine-to-machine clients are a more natural fit for client certificates. For webhook delivery, transport identity can be an additional check alongside the provider’s request signature; see webhook authentication and reliable delivery.

Certificate operations: the part a handshake diagram hides

The CA is where the identity story starts. Decide who may enroll, which workload or partner receives which identity, and what the verifier is allowed to trust. Giving every environment the same broad trust bundle makes it easier to accept a valid credential in the wrong place.

A useful production checklist is concrete:

Certificate operations: the part a handshake diagram hides
Decision Operational question
Enrollment What evidence allows a workload to obtain this identity?
Purpose Does the leaf permit the intended client or server authentication usage?
Key custody Which process can access the private key, and what happens if it is stolen?
Rotation Can a replacement key, certificate and trust bundle arrive without an outage?
Emergency withdrawal How do you stop an identity now, including active sessions and resumption policy?
Authorization Which identity may call which method and resource?

Short lifetimes reduce the exposure window. They do not instantly revoke a stolen credential, and certificate expiry is not a timer that necessarily tears down an already established application session. Plan policy withdrawal and connection handling, not just renewal alerts.

SPIFFE gives workload identity a defined form; an X.509-SVID carries a SPIFFE ID within a trust domain. That is useful when workloads are shorter-lived than machines. It still needs a trusted issuance and validation system. SPIFFE concepts.

In Istio, PeerAuthentication controls whether peers must use mTLS; PERMISSIVE accepts both mTLS and plaintext, while STRICT requires mTLS in its applicable scope. AuthorizationPolicy supplies the request-access rules. Enabling strict peer authentication is not itself a checkout-only allowlist. PeerAuthentication, AuthorizationPolicy. The Cilium vs Calico comparison covers where this fits alongside network encryption and policy.

A change that can break a working certificate setup

Let’s Encrypt ended issuance with the clientAuth EKU on July 8, 2026; the default classic profile had removed it on February 11. Its server certificates remain useful for authenticating servers. If a deployment reused them as client credentials, it needs a suitable replacement on the client side. Let’s Encrypt’s announcement and updated schedule.

This is not a ban on every client-authentication certificate from every CA. An internal service fleet commonly uses a private PKI because it controls enrollment and trust. The server certificate and client certificate can come from different issuers, as the demo demonstrates.

Which setup fits your system?

Which setup fits your system?
Situation Starting point
Public website with arbitrary browsers Server-authenticated TLS plus application sessions or OAuth
Internal services with controlled workload identities mTLS plus explicit service and request authorization
Partner API with a defined client population mTLS with a clear enrollment, renewal and incident process
Delegated API access where token theft matters Evaluate certificate-bound tokens and enforce the resource-side binding
Application behind a TLS-terminating edge Design and verify the identity handoff before trusting forwarded claims

The useful question is not whether another certificate makes a connection look more secure. It is which identity is established, who trusts the issuer, where that identity survives termination, and which action it authorizes. If the answer stops at “the handshake succeeded,” the access-control design is unfinished.

Frequently asked questions

What is the difference between mTLS and TLS?

In the usual certificate-based HTTPS setup, TLS authenticates the server to the client. Mutual TLS also authenticates the client to the server using a client certificate and proof of private-key possession. The encrypted transport is still TLS.

Is mTLS more encrypted than TLS?

No. The difference is client authentication, not a second encryption layer. With the same TLS version and negotiated algorithms, adding a client certificate does not make the application-data cipher stronger.

Does mTLS replace OAuth or JWT?

Not generally. mTLS can establish a machine identity while OAuth conveys delegated permissions or user context. RFC 8705 additionally defines certificate-bound access tokens, whose binding the resource server must enforce.

Can Let's Encrypt certificates still be used for mTLS?

A Let's Encrypt certificate can still authenticate the server. Let's Encrypt ended issuance with the clientAuth EKU on July 8, 2026; use a suitable client credential from a PKI your server explicitly trusts for the client side.

Why does a valid client certificate get HTTP 403?

A valid chain and proof of key possession establish authentication. The application can still deny the requested operation. The demo deliberately trusts two client certificates but authorizes only one.

From the community

Discussion on Mastodon & Bluesky

Replies to this article from the open web, pulled in live. No ads, no tracking scripts.

Loading replies …
Reply on MastodonReply on Bluesky

Reply there — it shows up here automatically.

ENDE