Introduction

Mutual TLS (mTLS) requires both the server and client to present valid certificates during the TLS handshake. When the client certificate's Common Name (CN) or Subject Alternative Name (SAN) does not match the identity expected by the authentication server, the connection is rejected. This is common when certificates are issued with incorrect subject fields, when hostname resolution differs from certificate SANs, or when the identity mapping configuration on the server is outdated.

Symptoms

  • TLS handshake fails with:
  • `
  • openssl s_client -connect api.example.com:443 -cert client.pem -key client-key.pem
  • SSL handshake error: tlsv1 alert unknown ca
  • `
  • Server logs show:
  • `
  • mTLS authentication failed: certificate CN 'client-staging.example.com'
  • does not match expected identity 'client-prod.example.com'
  • `
  • Or:
  • `
  • 403 Forbidden: Client certificate identity not mapped to any authorized user
  • `
  • Certificate is valid and trusted but identity mapping fails

Common Causes

  • Certificate CN does not match the expected client identifier
  • SAN field missing or contains wrong DNS names
  • Certificate issued to a different environment (staging cert in production)
  • Identity mapping rules on the server reference outdated CN values
  • Intermediate CA not included in the client certificate chain
  • Server expects SAN but client certificate only has CN

Step-by-Step Fix

  1. 1.Inspect the client certificate details:
  2. 2.```bash
  3. 3.# View certificate subject and SAN
  4. 4.openssl x509 -in client.pem -noout -subject -ext subjectAltName

# Expected output: # subject=CN = client-prod.example.com, O = MyOrg, C = US # X509v3 Subject Alternative Name: # DNS:client-prod.example.com, DNS:api-client.example.com ```

  1. 1.Verify the full certificate chain:
  2. 2.```bash
  3. 3.# Check the chain
  4. 4.openssl verify -CAfile ca-chain.pem client.pem

# If it fails, check each certificate in the chain openssl x509 -in client.pem -noout -issuer # Should match the intermediate CA subject openssl x509 -in intermediate-ca.pem -noout -subject # Should match the root CA issuer openssl x509 -in root-ca.pem -noout -subject ```

  1. 1.Test mTLS connection manually:
  2. 2.```bash
  3. 3.openssl s_client \
  4. 4.-connect api.example.com:443 \
  5. 5.-cert client.pem \
  6. 6.-key client-key.pem \
  7. 7.-CAfile ca-chain.pem \
  8. 8.-servername api.example.com \
  9. 9.-state -debug 2>&1 | grep -A5 "subject="
  10. 10.`
  11. 11.Fix the certificate identity mapping on the server:

For Nginx: ```nginx server { listen 443 ssl; ssl_client_certificate /etc/ssl/ca-chain.pem; ssl_verify_client on;

location /api { # Map client certificate CN to application user set $client_cn $ssl_client_s_dn_legacy; # Or use SAN: # set $client_san $ssl_client_s_dn;

# Verify the CN matches expected pattern if ($client_cn !~ "^CN=client-prod\.example\.com") { return 403; }

proxy_pass http://backend; proxy_set_header X-Client-CN $client_cn; } } ```

sed 's/.*=//;s/://g'

# This hash should match the "cnf" claim in the access token # {"cnf":{"x5t#S256":"abc123def456..."}} ```

  1. 1.Re-issue the certificate with correct SAN:
  2. 2.```bash
  3. 3.# Create an OpenSSL config for SAN
  4. 4.cat > san.cnf << 'EOF'
  5. 5.[req]
  6. 6.distinguished_name = req_distinguished_name
  7. 7.req_extensions = v3_req
  8. 8.prompt = no

[req_distinguished_name] CN = client-prod.example.com O = MyOrg C = US

[v3_req] subjectAltName = DNS:client-prod.example.com, DNS:api-client.example.com EOF

# Generate CSR with SAN openssl req -new -key client-key.pem -out client.csr -config san.cnf

# Submit CSR to your CA for signing # Or self-sign for testing: openssl x509 -req -in client.csr -signkey client-key.pem \ -out client.pem -days 365 -extensions v3_req -extfile san.cnf ```

Prevention

  • Always include SAN (Subject Alternative Name) in client certificates
  • Use a certificate management system (HashiCorp Vault, AWS ACM PCA, step-ca)
  • Implement certificate pinning with automated rotation
  • Monitor certificate expiration dates with automated alerts
  • Test mTLS in staging with production-like certificate identity mapping
  • Document expected CN/SAN patterns for each client application