Join our Newsletter — 33% off our NHI Course
Home› Guides› mTLS Guide: Mutual Authentication Between Services
Guide Cloud & Workload Identity

mTLS Guide: Mutual Authentication Between Services

PDF for newsletter subscribers · free to read online

← All guides
By Lalit Choda, NHI Mgmt Group Updated 24 October 2026 17 min read
On this page

Mutual TLS only proves who is calling if every hop validates the client certificate properly, and most broken deployments fail at exactly that point. Ordinary TLS authenticates the server to the client; mTLS adds the reverse, so a service, pod, device or partner system proves its identity with an X.509 certificate and the private key behind it. That makes the certificate and key a non-human identity credential, with the same lifecycle, scoping and theft problems as any other. This guide covers the handshake, where to terminate mTLS, certificate identity and authorisation, mTLS in OAuth (RFC 8705), rollout, detection and the mistakes that quietly turn mTLS into plain TLS. It is written for platform, API and security engineers; for how mTLS compares with other machine authentication methods, see the NHI Authentication Guide.

Key takeaways

  • mTLS authenticates a key, not a workload. Whoever holds the private key is the identity, so key generation, storage and short lifetimes matter more than the handshake itself.
  • Authentication is not authorisation. A valid chain only proves the certificate came from a CA you trust; the server must still check the specific identity (SAN, SPIFFE ID or subject) against policy.
  • Termination points are where mTLS breaks. If a load balancer or proxy terminates TLS, how it passes the verified identity on, and whether anything else can reach the backend, decides whether mTLS means anything.
  • Permissive modes and default endpoints are bypasses. Istio PERMISSIVE, NGINX optional, and the AWS API Gateway default execute-api endpoint all accept callers without a client certificate unless you close them.
  • mTLS also hardens OAuth. RFC 8705 uses the client certificate to authenticate to the token endpoint and to bind access tokens to that certificate, so a stolen token is useless without the key.

How mutual TLS works

In both TLS 1.2 and TLS 1.3 the server asks for a client certificate by sending a CertificateRequest message; it only does so when client authentication is wanted. The client answers with its Certificate message and a CertificateVerify message signed with its private key, which proves possession of the key rather than just possession of the certificate. The server then validates the chain to a configured trust anchor, checks the validity period and key usage, and optionally checks revocation.

  • TLS 1.3 privacy: in TLS 1.3 (RFC 8446) every handshake message after ServerHello is encrypted, so the client certificate is not visible on the wire. Before TLS 1.3 the client certificate is sent in clear, which RFC 8705 notes allows tracking; prefer TLS 1.3 wherever both ends support it.
  • Hinting which CA to use: the certificate_authorities extension (RFC 8446 section 4.2.4) lets the server tell the client which CAs it accepts, which helps clients holding several certificates choose the right one.
  • Post-handshake authentication: TLS 1.3 clients can advertise post_handshake_auth (sections 4.2.6 and 4.6.2), letting a server request a certificate later in the connection. HTTP/2 does not allow this, so design for authentication at handshake time.
  • Where the identity lives: modern deployments put the identity in the Subject Alternative Name (DNS name, URI or SPIFFE ID), not the subject common name. The certificate should carry the clientAuth extended key usage when it is used as a client credential.

mTLS compared with other service authentication methods

MethodWhat proves identityReplay of stolen credentialBest fitMain weakness
mTLS (X.509 client certificate)Private key used in the TLS handshakeNot possible without the private keyEast-west service traffic, partner APIs, devices, OAuth clientsBreaks at TLS termination; certificate lifecycle and trust store management
Static API key or client secretA shared stringTrivial: anyone holding the string is the clientLow-risk integrations where nothing better is supportedLeaks in code, logs and images; long-lived
OAuth bearer tokenPossession of the tokenPossible until expiryAPIs needing scopes and central policyToken theft; needs sender constraint
OAuth with DPoP (RFC 9449)Token plus an application-layer proof signed with a client keyBlocked without the keyWhere TLS client certificates cannot be deployed end to endProof covers method and URI only; replay tracking across stateless servers is hard
Signed JWT from a workload identity providerShort-lived signed assertionPossible within the token lifetime and audienceCloud federation, crossing proxies that terminate TLSAudience and issuer validation errors

mTLS and tokens are not alternatives so much as layers: many platforms use mTLS for the transport identity and an OAuth or JWT credential for application-level authorisation. See the Machine-to-Machine OAuth (Client Credentials) Guide and the Token and Session Security Guide.

Where to terminate mTLS: architecture choices

PatternHow it worksChoose it whenWatch for
Service mesh sidecar or node proxy (Istio, Linkerd)Proxies hold workload certificates issued by the mesh CA and handle mTLS transparentlyMany internal services in Kubernetes; you want mTLS without changing codePermissive modes, non-meshed workloads, skipped ports, trust anchor expiry
API gateway (for example AWS API Gateway, Azure API Management)Gateway validates client certificates against a trust store, then forwards to backendsExternal partners or devices calling a public APIRevocation support, default endpoints that bypass the gateway, header forwarding
Reverse proxy or load balancer (NGINX, Envoy, HAProxy)Proxy validates the certificate and forwards identity in headersExisting web tier; consistent policy for many appsSpoofable identity headers; backend reachable directly
In the applicationApplication TLS library verifies the certificate itselfPoint-to-point links, databases, message brokers, small estatesEvery team re-implements validation; inconsistent trust stores

Service mesh specifics

  • Istio: the PeerAuthentication resource sets mtls.mode to UNSET, DISABLE, PERMISSIVE or STRICT. With no policy at any level the effective behaviour is PERMISSIVE, which accepts plaintext as well as mTLS. A policy in the root namespace without a selector applies mesh-wide; namespace and workload-selector policies narrow it; portLevelMtls can exempt individual ports but only on a workload-selector policy. PeerAuthentication controls authentication only: pair STRICT with AuthorizationPolicy rules that name the allowed caller identities.
  • Linkerd: mTLS is on by default for TCP traffic between meshed pods, with each proxy certificate bound to the pod's Kubernetes ServiceAccount and the private key generated inside the pod. Proxy certificates expire after 24 hours and rotate automatically, but the default trust anchor and issuer certificate last a year and are not rotated for you. Traffic from non-meshed pods (including Kubernetes health checks) and traffic on skip ports is not protected, and plaintext from non-meshed sources is accepted unless authorisation policy forbids it.

See the Service Mesh Security Guide for mesh hardening beyond mTLS, and the SPIFFE and SPIRE Guide for issuing workload identities outside a mesh.

Gateway and proxy specifics

  • AWS API Gateway: mTLS is configured on a Regional custom domain with a trust store PEM file in S3 containing the full chain. It does not check revocation, so AWS recommends a Lambda authorizer for revocation and extra checks. The default execute-api endpoint bypasses mTLS until you disable it. Failed validation returns 403.
  • NGINX: ssl_verify_client takes on, off (the default), optional or optional_no_ca. ssl_verify_depth defaults to 1, which is too shallow for most private CA hierarchies with an intermediate. ssl_client_certificate lists trusted CAs and sends their names to clients; ssl_trusted_certificate trusts without advertising. Revocation is via ssl_crl or ssl_ocsp (1.19.0 and later). Errors 495 and 496 mean verification failed or no certificate was sent.
  • Envoy: the x-forwarded-client-cert (XFCC) header carries Hash, Cert, Chain, Subject, URI, DNS and Issuer fields. Envoy sanitises the header by default; SANITIZE_SET replaces any incoming value and APPEND_FORWARD appends to it. The Chain field is what the client sent, not a validated chain.

Certificate identity and authorisation

RFC 8705 warns that X.509 validation is error-prone and that implementers should use a well-tested library rather than writing their own. The bigger risk is usually not the chain check but what the server does after it.

  • Limit trust anchors: a server that trusts a large public or shared CA set accepts any certificate those CAs issue. Use a dedicated private CA (or SPIFFE trust domain) for client authentication and trust only that.
  • Match one identity field: authorise on an exact SAN or SPIFFE ID, not on "any certificate from our CA" and not on substring matches of the subject DN. The SPIFFE X.509-SVID standard requires exactly one URI SAN per certificate, and validators must reject certificates with more, because multiple identities complicate authorisation.
  • Check leaf properties: leaf certificates should have CA set to false and must not carry keyCertSign. X.509-SVIDs require a critical digitalSignature key usage and, when extended key usage is present, both serverAuth and clientAuth.
  • Constrain intermediates: name constraints can limit what a compromised intermediate can issue, but SPIFFE notes support for URI name constraints is limited, so test your libraries before relying on them.
  • Default deny: after STRICT mTLS, write allow rules per caller identity and per path or method. mTLS with no authorisation layer means every workload holding a mesh certificate can call every service.
Identity fieldExampleUse forNotes
URI SAN (SPIFFE ID)spiffe://prod.example.org/ns/payments/sa/apiWorkloads in Kubernetes and meshesEncodes trust domain, namespace and service account
DNS SANorders.internal.example.orgServices addressed by hostnameDo not reuse the server certificate as a client credential across many hosts
Subject DNCN=partner-a,O=Partner A LtdLegacy partners, RFC 8705 tls_client_auth_subject_dnCompare the full normalised DN exactly
Certificate thumbprintSHA-256 of the certificatePinned self-signed clients, RFC 8705 bound tokensChanges on every renewal, so plan re-registration

mTLS in OAuth: RFC 8705

RFC 8705 defines two things: using mTLS to authenticate an OAuth client to the authorisation server, and binding access tokens to the client certificate so they cannot be replayed by someone else. RFC 9700, the OAuth 2.0 Security Best Current Practice, recommends asymmetric client authentication such as mTLS or private_key_jwt over shared secrets (section 2.5) and recommends sender-constrained access tokens using mTLS or DPoP (section 2.2.1).

ElementValueWhat it does
PKI client authenticationtls_client_authServer validates the chain and matches exactly one registered value: tls_client_auth_subject_dn, _san_dns, _san_uri, _san_ip or _san_email
Self-signed client authenticationself_signed_tls_client_authClient registers its certificates via jwks or jwks_uri; no chain validation
Certificate-bound tokencnf claim with x5t#S256SHA-256 thumbprint of the client certificate in the JWT or introspection response
Resource server checkHTTP 401 invalid_tokenRejects the request if the TLS client certificate thumbprint does not match
Metadatatls_client_certificate_bound_access_tokensServer and client signal support for bound tokens (default false)
Endpoint aliasesmtls_endpoint_aliasesSeparate mTLS token, revocation and introspection endpoints so other clients are not prompted for certificates

Two operational consequences follow. A bound token stops working the moment the client renews its certificate, so clients must treat a thumbprint mismatch as an expired token and fetch a new one. And when TLS is terminated before the resource server, the proxy must pass the verified certificate on securely, which RFC 8705 explicitly leaves to implementers. Where certificates cannot be carried end to end, DPoP (RFC 9449) gives sender constraint at the HTTP layer instead. FAPI profiles build on both; see the OAuth 2.1, GNAP and FAPI Guide.

Certificate lifecycle for mTLS identities

  • Generate keys where they are used: Linkerd generates proxy keys inside the pod and never moves them; follow the same rule elsewhere. Use hardware or platform key stores (TPM, HSM, cloud KMS, secure enclave) for devices and high-value clients.
  • Short lifetimes and automation: mesh workload certificates of hours or a day remove most of the need for revocation. For partner and device certificates, automate renewal (ACME, SCEP, EST or the vendor's agent) and alert well before expiry.
  • Track trust anchors and intermediates: leaf rotation is usually automated; root and issuer rotation often is not. An expired mesh trust anchor stops all service-to-service traffic at once.
  • Rotate trust stores with overlap: add the new CA to every trust store before any client presents a certificate from it, then remove the old CA after the last old certificate has expired.
  • Plan revocation honestly: some platforms do not check revocation (AWS API Gateway, for example), and many internal stacks never fetch CRLs. If you cannot revoke, keep lifetimes short and remove the identity from authorisation policy as the kill switch.

See the Machine Identity, PKI and Certificate Lifecycle Guide and the Certificate Expiry Outages and 47-Day TLS Certificates Guide.

Rolling out mTLS without outages

  1. Inventory callers: list every client of the service, including health checks, batch jobs, monitoring and partner systems. Non-meshed or legacy callers are what break when you go strict.
  2. Stand up the CA and identity scheme: choose a private CA or SPIFFE trust domain, define the SAN or SPIFFE ID naming pattern, and decide lifetimes before issuing anything.
  3. Run in permissive or optional mode with logging: Istio PERMISSIVE or NGINX ssl_verify_client optional, logging $ssl_client_verify and the subject for every request. This shows which callers already present valid certificates.
  4. Fix the stragglers: onboard or retire each caller that still arrives without a certificate. Exempt health check ports explicitly and narrowly rather than leaving the whole service permissive.
  5. Enforce per service or namespace: move to STRICT or ssl_verify_client on one ring at a time (test, internal low-risk, production), watching handshake failure rates.
  6. Add authorisation: introduce allow rules per caller identity, first in audit or dry-run mode where the platform supports it, then enforced.
  7. Close bypasses: disable default endpoints, block direct access to backends behind the proxy with network policy or security groups, and strip incoming identity headers at the edge.
  8. Roll back safely: keep the previous policy as a versioned manifest; rolling back means reverting STRICT to PERMISSIVE for the affected scope only, never disabling mTLS mesh-wide. Record every rollback as an incident with an owner and a date to re-enforce.

Decision guidance

  • Mesh versus gateway: use the mesh for east-west traffic inside clusters and a gateway or proxy for north-south traffic from partners and devices. Do not extend a mesh CA to external partners; give them certificates from a separate CA with its own trust store.
  • mTLS versus DPoP for OAuth: choose RFC 8705 when clients are servers you control and certificates already flow end to end; choose DPoP when TLS is terminated by infrastructure you cannot change or clients cannot hold certificates.
  • Small organisations: a managed gateway or a single proxy tier with a small private CA covers most needs; avoid running a mesh only to get mTLS for a handful of services.
  • Large organisations: standardise one identity format (usually SPIFFE IDs), one or a few issuing CAs with automated rotation, and central authorisation policy. Treat CA operations as a privileged service.

Where identity fits

Every mTLS client certificate is a non-human identity: it needs an owner, an inventory record, a purpose, a lifetime and a removal date. Private keys copied into container images, shared across environments, or reused by several services are the mTLS equivalent of a shared service account password. ATT&CK covers theft of the key material as T1552.004 Private Keys and theft or forgery of certificates as T1649 Steal or Forge Authentication Certificates; a compromised issuing CA lets an attacker mint identities at will. Store client keys in a secrets manager or key store, never in repositories. See the Secrets Management Guide and the Cloud Workload Identity Guide.

Detection and measurement

  • Log the verified identity: record client certificate subject or SPIFFE ID, issuer, serial, verification result and TLS version per connection (NGINX $ssl_client_verify, $ssl_client_s_dn, $ssl_client_v_remain; mesh access logs with peer identity).
  • Alert on plaintext where STRICT is expected: mesh telemetry showing non-mTLS connections, or any request to a default endpoint that should be disabled.
  • Alert on unknown issuers and identities: certificates from unexpected CAs, new SPIFFE IDs calling sensitive services, or one identity appearing from many source networks.
  • Watch handshake failures: spikes in 495/496 or TLS alert rates often precede an expiry outage or reveal scanning with stolen or invalid certificates.
  • Track certificate issuance: issuance volume per identity and per CA; a sudden rise can indicate key misuse or a compromised enrolment path.
MetricTargetWhy it matters
Share of service-to-service traffic using mTLS in strict modeClose to 100% for production namespacesPermissive traffic is unauthenticated traffic
Services with identity-based authorisation rules, not just mTLSAll services handling sensitive datamTLS without authorisation lets any workload call anything
Median client certificate lifetimeHours to days for workloadsShorter lifetimes reduce reliance on revocation
Trust anchors and intermediates with automated rotation and an expiry alert100%Root or issuer expiry causes estate-wide outages
Exempted ports and permissive scopes, with owner and expiry dateFalling every quarterExceptions become permanent bypasses

Common failure patterns

  • Stuck in permissive: rollouts start in PERMISSIVE mode and never move on, so an attacker inside the network simply connects without a certificate. Set a date per namespace to go STRICT.
  • Trust the header, skip the check: a backend reads an identity header such as X-Client-DN but is reachable directly or the edge does not strip incoming copies, so any caller can set it. Strip at the edge and lock backends to the proxy.
  • "Any certificate from our CA": authorisation stops at chain validation, so every workload with a mesh certificate can reach the payment service. Authorise on exact identities.
  • Default endpoints and side doors: the AWS API Gateway execute-api endpoint, a node port, or a second listener without client verification bypasses the mTLS listener completely.
  • Shallow or wrong verification: ssl_verify_depth 1 rejecting valid chains leads teams to switch to optional_no_ca "temporarily"; certificate checks disabled in client libraries to get past a test failure ship to production.
  • Forgotten trust anchors: leaf certificates rotate daily but the mesh root expires after a year and takes down every service at once.

Framework mapping

FrameworkReferenceHow mTLS applies
NIST SP 800-53 Rev. 5IA-9 Service Identification and Authentication; IA-3 Device Identification and AuthenticationServices and devices authenticate before connections are established
NIST SP 800-53 Rev. 5IA-5(2) Public Key-based Authentication; SC-17 Public Key Infrastructure CertificatesCertificate path validation, private key protection, CA management
NIST SP 800-53 Rev. 5SC-8 Transmission Confidentiality and Integrity; SC-23 Session AuthenticityEncrypted, authenticated channels between services
NIST CSF 2.0PR.AA-03; PR.DS-02Services and hardware are authenticated; data in transit is protected
ISO/IEC 27001:2022 Annex AA.8.5 Secure authentication; A.8.24 Use of cryptographyAuthentication technology and key management rules
MITRE ATT&CK v20T1557 Adversary-in-the-Middle; T1040 Network Sniffing; T1552.004; T1649mTLS counters interception and impersonation; key and certificate theft defeats it
MITRE D3FENDD3-CBAN Certificate-based Authentication; D3-CERO Certificate Rotation; D3-CP Certificate PinningDefensive techniques that mTLS deployments implement

Practitioner checklist

  • Inventory every caller of each service, including health checks and batch jobs, before enforcing mTLS.
  • Use a dedicated private CA or SPIFFE trust domain for client authentication and trust only that anchor.
  • Prefer TLS 1.3 so client certificates are encrypted in the handshake.
  • Move every production scope from permissive or optional to strict, with dated, owned exceptions only.
  • Authorise on exact SAN or SPIFFE ID per service and method; default deny.
  • Disable default and side-door endpoints and block direct access to backends behind proxies.
  • Strip identity headers such as XFCC at the edge and set them only from verified connections.
  • Automate rotation of leaf, issuer and root certificates and alert on expiry well in advance.
  • Bind OAuth tokens to client certificates (RFC 8705) or DPoP keys for high-value APIs.
  • Log verified identity, issuer, serial and verification result for every connection.

Standards and references

Related NHI Mgmt Group resources: NHI Authentication Guide · Service Mesh Security Guide · SPIFFE and SPIRE Guide · Machine Identity, PKI and Certificate Lifecycle Guide · Token and Session Security Guide

PDF for subscribers

Take this guide with you

Every section, table and checklist in one PDF, with links to the sources and related guides. Subscribe to our weekly NHI & AI Identity Journal and we’ll email you a download link.

Free weekly newsletter

Subscribe to the NHI & AI Identity Journal

The latest on NHI and Agentic AI security – articles, research, breaches, news and events every week.

Bonus 33% off our NHI Course when you subscribe.

NHIMG Editorial Note
Written and reviewed by Lalit Choda, NHI Mgmt Group. Last updated 24 October 2026.
NHI Mgmt Group — the #1 independent authority on Non-Human Identity, IAM, and Agentic AI security. nhimg.org

PDF Downloads for Newsletter Subscribers

Get the guide

Enter your details and we’ll email you a download link.

The full guide is free to read online. The PDF is a thank you for subscribing.

Fill in all fields marked * and tick the PDF box to continue.