
mTLS vs JWT for Service-to-Service Auth
A comparison of mTLS and JWT for service-to-service authentication, examining transport-level security versus request-level identity in modern architectures.
In modern distributed systems, securing communication between services is rarely a binary choice between two competing technologies. It is a question of scope. Two protocols dominate this space: Mutual Transport Layer Security (mTLS) and JSON Web Tokens (JWT). Engineers often confuse them because both provide "authentication," but they operate at fundamentally different layers of the OSI model and serve distinct security goals. mTLS secures the transport layer, ensuring the pipe is safe, while JWT secures the request layer, ensuring the actor is authorized.
mTLS authenticates the channel. It ensures that Service A is talking to Service B over an encrypted connection, verifying that both endpoints possess valid cryptographic identities. It is a transport-level guarantee.
JWT authenticates the actor. It carries a signed assertion about who initiated the request, passing that identity through multiple hops, even across networks where the transport itself might be untrusted or terminated. It is a request-level guarantee.
Understanding the mechanism of each is critical for platform engineers designing secure internal architectures. Treating them as substitutes leads to either over-engineering or security gaps.
The Mechanism of mTLS: Securing the Pipe
mTLS is an extension of the standard TLS handshake used in HTTPS. In standard TLS, the client verifies the server's certificate. In mTLS, both parties verify each other's certificates.
The Handshake Mechanism
When Service A connects to Service B, the following occurs at the mechanism level:
- Certificate Exchange: Service A sends its X.509 certificate to Service B. Service B sends its certificate to Service A.
- Verification: Both sides check the certificate chain against a trusted Certificate Authority (CA). This CA is often internal to the organization (e.g., Istio's istiod or cert-manager).
- Key Exchange: Using asymmetric cryptography, they derive a shared symmetric session key.
- Encryption: All subsequent traffic is encrypted using this session key.
# Example: Verifying an mTLS connection via OpenSSL
openssl s_client -connect service-b:443 -cert client.crt -key client.key -CAfile root-ca.crtWhat mTLS Solves
- Confidentiality: Data in transit is encrypted. Eavesdroppers cannot read payloads.
- Endpoint Authentication: Service B knows it is receiving traffic from a valid Service A, not an imposter.
- Integrity: Tampering with the data stream is detected via message authentication codes (MACs).
What mTLS Does Not Solve
mTLS stops at the edge of the service. Once Service B decrypts the traffic, it sees the raw HTTP request. It does not inherently know which user triggered this request. If Service A is acting on behalf of User X, Service B only sees Service A as the caller. mTLS cannot convey user-level context without additional metadata injection.
Furthermore, mTLS is brittle across administrative boundaries. If Service A (owned by Team Alpha) calls Service B (owned by Team Beta), establishing a shared PKI (Public Key Infrastructure) can be operationally complex. mTLS trusts the network location and identity, not the business intent.
The Mechanism of JWT: Carrying Identity
JWT (RFC 7519) is a compact, URL-safe means of representing claims to be transferred between two parties. It is a self-contained token that carries information about the user or service.
The Structure
A JWT consists of three parts, separated by dots:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. // Header
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ. // Payload
SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c // Signature- Header: Specifies the signing algorithm (e.g., RS256).
- Payload: Contains claims (data). Standard claims include
sub(subject),iss(issuer),exp(expiration), and custom fields likeuser_idordepartment. - Signature: Ensures the token hasn't been tampered with. The issuer signs the header and payload using a private key.
The Flow
- Issuance: An Identity Provider (IdP) issues a JWT to Service A after authenticating User X.
- Propagation: Service A includes the JWT in the
Authorization: Bearer <token>header when calling Service B. - Verification: Service B validates the signature using the IdP's public key. It checks expiration and issuer.
- Authorization: Service B reads the claims (e.g.,
user_id) to decide whether to allow the action.
What JWT Solves
- Statelessness: Service B does not need to query a database to verify the token. It validates the signature locally.
- Cross-Boundary Trust: Any service that trusts the IdP can validate the JWT, regardless of whether it shares a PKI with the caller.
- Fine-Grained Context: The token carries specific identity attributes (roles, scopes, user ID) that enable policy-based access control.
What JWT Does Not Solve
JWTs are not encrypted by default. Claims are base64-encoded, meaning anyone can read them. While this allows intermediaries to inspect the payload, the signature integrity protection ensures that no one can tamper with the claims without detection. You must use JWE (JSON Web Encryption) for confidentiality, but this is rare in internal service communication due to performance overhead.
Crucially, JWTs do not secure the transport. If a JWT is sent over plain HTTP, it can be stolen via man-in-the-middle attacks. JWTs assume the transport is secure or that the risk of theft is mitigated by other controls.
Convergence: The Service Mesh Pattern
Modern architectures rarely use mTLS and JWT in isolation. The prevailing pattern, implemented by service meshes like Istio, Linkerd, and Consul Connect, combines both.
How It Works
- mTLS for Transport: The service mesh sidecar proxies (Envoy) enforce mTLS between all services. This creates a secure, encrypted network fabric. Developers do not need to manage certificates manually; the mesh automates rotation and distribution.
- JWT for Identity: Within this secure tunnel, services exchange JWTs to convey user identity. The sidecar may extract the JWT from the HTTP header and inject it into the gRPC metadata or pass it to the application.
- Policy Enforcement: The mesh or the application uses the JWT claims to enforce fine-grained access control.
# Istio RequestAuthentication example: Enforcing JWT validation
apiVersion: security.istio.io/v1beta1
kind: RequestAuthentication
metadata:
name: jwt-example
spec:
selector:
matchLabels:
app: reviews
jwtRules:
- issuer: "https://example.com"
jwksUri: "https://example.com/.well-known/jwks.json"Why Both?
- Defense in Depth: mTLS prevents eavesdropping and spoofing of the network connection. JWT prevents unauthorized access based on business logic.
- Operational Separation: Network teams manage mTLS certificates. Application teams manage JWT scopes and claims.
- Auditability: mTLS logs show who connected. JWT logs show what they did and why (via claims).
Decision Framework
When designing your architecture, ask these questions:
- Do you need encryption?
- Yes → Use mTLS. JWT alone does not encrypt data in transit.
- Do you need to know the end-user identity?
- Yes → Use JWT. mTLS only tells you the calling service, not the user.
- Are services in different administrative domains?
- Yes → Prefer JWT. Establishing a shared PKI for mTLS across organizations is difficult. JWTs issued by a common IdP are easier to manage.
- Is low latency critical?
- Yes → Be cautious with mTLS. Certificate handshakes add latency, though session resumption mitigates this. JWT validation is computationally cheap if using asymmetric keys and caching.
Common Pitfalls
- Assuming JWT Confidentiality: Storing sensitive PII (Personally Identifiable Information) in JWT claims is dangerous because they are readable by any intermediary. Always use mTLS to protect the transport, and avoid putting secrets in JWTs.
- Ignoring Certificate Rotation: mTLS requires strict certificate lifecycle management. Forgetting to automate rotation leads to service outages when certificates expire.
- Over-Reliance on Network Policies: Assuming mTLS alone is sufficient for authorization. mTLS proves the service identity, but not the user's permissions. You must still enforce RBAC/ABAC based on JWT claims.
Takeaways
- Transport vs. Request: mTLS secures the network channel; JWT secures the business context within that channel.
- Complementary, Not Competitive: They solve different problems. Use both for a robust zero-trust architecture.
- Scope of Trust: mTLS trusts the infrastructure; JWT trusts the identity provider. Align your trust model with your organizational boundaries.
FAQ
Can I use JWT without mTLS? Technically yes, but it is insecure. JWTs are not encrypted by default. If sent over HTTP, they can be intercepted. Best practice is to always use mTLS to protect JWTs in transit.
Does mTLS replace the need for JWTs?
No. mTLS authenticates the service-to-service connection, but it does not convey user-level context (like user_id or roles). You still need JWTs or similar mechanisms for fine-grained authorization.
Which is better for cross-cloud communication? JWT is generally easier for cross-cloud scenarios because it relies on a shared Identity Provider (IdP) rather than a shared PKI, which is difficult to manage across different cloud providers or on-premises environments.
Conclusion
mTLS and JWT are not competitors; they are collaborators. mTLS secures the pipe; JWT populates the pipe with meaningful identity.
For platform engineers, the recommendation is clear: Implement mTLS everywhere for transport security. Then, implement JWT for services that require user-level authorization or cross-boundary trust. Ignoring either layer leaves your microservices architecture exposed to either network-level attacks or authorization bypasses.
The future of service security is hybrid. As zero-trust architectures become standard, the combination of strong transport encryption (mTLS) and granular identity assertions (JWT) will remain the gold standard for internal service communication.
Next Steps: Audit your current service mesh configuration to ensure mTLS is enforced for all internal traffic. Simultaneously, review your JWT claim structure to ensure it contains sufficient context for your authorization policies.
Related posts
How to Revoke a JWT: Denylist & Expiry Strategies
Learn how to revoke a JWT you already issued using denylists and token invalidation strategies for secure backend authentication.
JWT vs Opaque Tokens: The Architecture of Trust
An examination of JWT and opaque token architectures, comparing introspection, revocation, and security trade-offs for backend systems.
API Gateway OIDC: Kong and Friends
Implement OIDC authentication in Kong API Gateway, covering JWT validation, JWKS caching, and upstream header propagation.