Mutual TLS (mTLS) Certificate Guide

Mutual TLS requires both server and client to present X.509 certificates. Learn mTLS certificate requirements, server configuration, service mesh SPIFFE SVIDs, and debugging.

ZERO UPLOAD · ALL LOCAL
  1. Paste PEM text into the textarea or drop a certificate file (.crt, .pem, .cer, .der) onto the drop zone.
  2. Each certificate in the chain renders as a separate card, ordered leaf-first. The leaf is expanded; intermediates and root are collapsed.
  3. Coloured badges flag expired certificates, expiring-soon certificates, weak RSA keys, SHA-1 signatures, and wildcard SANs.
  4. Use the Copy button on any field row to copy its value to the clipboard.
  5. Enter a domain name (e.g. example.com) in the "Fetch from domain" field and click Fetch to inspect its live TLS certificate.

What this page covers

  • Server EKU TLS Web Server Authentication, OID 1.3.6.1.5.5.7.3.1
  • Client EKU TLS Web Client Authentication, OID 1.3.6.1.5.5.7.3.2
  • SPIFFE SVID a URI SAN of the form spiffe://trust-domain/path, typically 24-hour validity

Drop .crt / .pem / .cer / .der here

or click to browse

── or paste PEM below ──

── or fetch from domain ──

Parsing certificate…

Mutual TLS (mTLS) Certificate Guide: Setup, Debugging, and SPIFFE

Mutual TLS (mTLS) requires both the server and the client to present X.509 certificates during the TLS handshake, providing bidirectional cryptographic authentication. In standard TLS, only the server presents a certificate; the client verifies the server's identity but the server has no cryptographic proof of the client's identity. In mTLS, the server sends a CertificateRequest message during the handshake, the client responds with its own certificate, and the server verifies that certificate against its configured CA trust store. Consequently, only clients holding a certificate signed by a trusted CA can complete the handshake at all, regardless of any credentials in the request body. mTLS is widely used in service mesh architectures like Istio and Linkerd, zero-trust network designs, and B2B API integrations that require stronger authentication than API keys or OAuth tokens.

mTLS certificate requirements versus server certificates

Client certificates for mTLS share the same X.509 structure as server certificates but differ in their Extended Key Usage extension. A server certificate includes the TLS Web Server Authentication OID (1.3.6.1.5.5.7.3.1) in its Extended Key Usage extension. A client certificate for mTLS includes the TLS Web Client Authentication OID (1.3.6.1.5.5.7.3.2)1.

The Subject distinguished name typically identifies the client rather than a domain name: for example, a client certificate for a microservice might have CN=payment-service, or a client certificate for a B2B partner might have O=Acme Corp, CN=partner-api. Furthermore, the CA that issues client certificates may be different from the CA that issues server certificates; many mTLS deployments use a private internal CA for client certificates while using a publicly trusted CA for server certificates. Inspecting a client certificate in the CapyToolkit Certificate Inspector confirms its Extended Key Usage OIDs, the Issuer, and the validity window, so you can verify the EKU before deployment.

How EKU OIDs decide which purpose a certificate can serve

Extended Key Usage is not a suggestion; it is a constraint that compliant TLS libraries enforce. Server-only certificates that lack the Client Authentication OID cannot be presented during a CertificateRequest without the peer rejecting them, and client-only certificates that lack the Server Authentication OID fail when accidentally configured on a web server. Software PKI tooling sometimes issues certificates with both OIDs to allow dual use, but that weakens the separation between client and server roles and makes a compromised client certificate usable for impersonating a server. When you generate a client certificate for mTLS, checking the EKU field before deployment catches misconfigured templates before they cause handshake failures in production.

A related check is to confirm the CA that issued the client certificate is the one the server actually trusts. mTLS fails in subtle ways when the client certificate chains to a different internal CA than the server's trust list expects, even when the certificate is otherwise valid. The CapyToolkit Certificate Inspector shows the Issuer and the chain for any client certificate, so you can compare it against the CA bundle the server is configured to verify before rolling out the connection.

Setting up and verifying mTLS in server configuration

Configuring mTLS on a server requires setting up client certificate verification against a specified CA trust list. In nginx, the ssl_client_certificate directive points to the CA certificate bundle that signed client certificates, and ssl_verify_client on enables verification2. In Node.js, the tls.createServer options object accepts ca (an array of CA certificates) and requestCert: true plus rejectUnauthorized: true3. The server uses the ssl_verify_depth or equivalent setting to limit the number of intermediates in the client certificate chain it will validate. Consequently, a misconfigured ssl_verify_depth that is too shallow causes valid client certificates signed through an intermediate to fail validation even when the chain is otherwise correct. The CapyToolkit Certificate Inspector can parse the client certificate to show its Issuer and Extended Key Usage OIDs, confirming the certificate carries the correct authentication purpose before configuring the server.

When ssl_verify_depth silently rejects valid client certificates

A deployment that switches from a direct CA issuance pattern to an intermediate CA often keeps the ssl_verify_depth setting at its default value of 1, which only validates client certificates signed directly by a trusted CA. Client certificates that chain through the new intermediate then fail validation even though every certificate in the chain is valid and signed correctly, because the verifier does not traverse deeply enough to reach a trusted root. The fix is to set ssl_verify_depth to at least 2 when an intermediate CA sits between the client certificate and the trust store, or higher when the chain has additional issuing layers. A quick way to detect this failure mode is to inspect the client certificate chain in the Certificate Inspector and count the intermediates between the leaf and the trusted root, then configure the depth to match.

mTLS in service mesh architectures and SPIFFE SVIDs

Service meshes like Istio and Linkerd use mTLS as the default authentication mechanism between services, issuing short-lived client and server certificates automatically via their control planes. Istio's istiod component issues SPIFFE-format X.509 SVIDs (SPIFFE Verifiable Identity Documents) to each workload, embedding the workload's identity as a URI SAN in the SPIFFE format: spiffe://cluster-id/ns/namespace/sa/service-account4. These certificates typically have 24-hour validity and rotate automatically. Consequently, mTLS in a service mesh eliminates the need to manage certificates manually for service-to-service communication, while still providing cryptographic proof of each service's identity. The CapyToolkit Certificate Inspector can parse SPIFFE certificates: paste the PEM and look for the URI SAN entry containing the SPIFFE ID in the Extensions section of the expanded card.

How short-lived SVIDs trade validity windows for revocation-free operation

Service meshes can afford一小时 validity because the control plane reissues certificates without operator intervention and workloads receive new credentials before the old ones expire. A shorter validity window limits the damage from a leaked private key, since a stolen certificate becomes useless within hours regardless of whether it has been revoked. Traditional revocation mechanisms like CRLs and OCSP introduce network latency and caching concerns that are unacceptable when every service connects to every other service dozens of times per second. By pairing short lifetimes with automated issuance, service meshes sidestep the revocation problem entirely while still maintaining strong cryptographic identity for every connection.

When to use this

Use this guide when implementing service-to-service authentication in a microservices architecture, when setting up mTLS for a B2B API integration that requires stronger authentication than shared secrets, or when troubleshooting mTLS handshake failures. It also applies when designing the certificate issuance workflow for client certificates: unlike server certificates, client certificates for mTLS require a private CA or managed PKI service rather than a publicly trusted CA, and the Extended Key Usage extension must carry the Client Authentication OID. Furthermore, use this guide when migrating from API key authentication to mTLS, since the migration requires changes on both the server side and all clients before the cutover to avoid downtime. Building on this, apply the SPIFFE section whenever you are evaluating service mesh options, since understanding how Istio and Linkerd manage certificate lifecycles affects your choice of mesh and your observability requirements for certificate rotation events.

Examples

mTLS handshake failure: certificate required

The server requests a client certificate but the client is not configured to present one. Verify that the client TLS configuration includes the client certificate and private key files. In curl: add --cert client.pem --key client.key to the command.

mTLS failure: certificate verify failed — certificate not trusted

The server's client CA trust store does not include the CA that signed the client certificate. Add the client certificate's issuing CA to the server's ssl_client_certificate (nginx) or ca option (Node.js). Inspect the client certificate Issuer field in the Certificate Inspector to identify the correct CA to add.

Verifying SPIFFE certificate identity in a service mesh

Paste the workload certificate PEM into the Certificate Inspector. Look for a URI SAN entry in the Extensions section. A valid SPIFFE ID follows the format spiffe://trust-domain/path, for example spiffe://example.com/ns/default/sa/frontend.

Sources
  1. 1.

    Cooper, D., Santesson, S., Farrell, S., Boeyen, S., Housley, R., and Polk, W., "Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile," RFC 5280, IETF, September 2008. https://www.rfc-editor.org/info/rfc5280

  2. 2.

    NGINX Project, "Module ngx_http_ssl_module," nginx.org, accessed June 2026. https://nginx.org/en/docs/http/ngx_http_ssl_module.html

  3. 3.

    Node.js Project, "TLS (SSL)," nodejs.org, accessed June 2026. https://nodejs.org/api/tls.html

  4. 4.

    SPIFFE Project, "X509-SVID," spiffe.io, accessed June 2026. https://spiffe.io/docs/latest/spiffe-specs/x509-svid/

FAQ