Why mTLS Might Be a Better Choice Than JWT for Internal APIs
Whenever I need to make an authenticated HTTP call to an internal microservice, I usually use JWT. But recently I came to know that JWT comes with some security concerns. Although JWT is the most common way to do authentication, we can't just ignore its security concerns.
Security Concerns in JWT:
Lack of Immediate Revocation: JWTs are validated based on their signature and expiry time. That means we can't revoke the JWT token before its expiry time.
Compromised Secret Key: JWT security relies on a secret key. If that secret key is compromised, the attacker can generate valid JWTs.
Data Exposure: JWTs are meant for integrity, not for encryption. That's why data inside JWT claims is just a base64-encoded string that can be decrypted without any key.
XSS Vulnerability: If the JWT token is stored in the local storage of the browser instead of an HTTP-only cookie, any malicious script can steal it.
So what's the solution?
While exploring other authentication alternatives, I came to know about mTLS—Mutual TLS. Which is an extended version of TLS. It is a cryptographic protocol that provides secure communication over a computer network—most commonly used in HTTPS.
Are TLS & SSL the same?
Yes, TLS is an evolved version of SSL. SSL was created by Netscape in 1999. SSL version 3.1 was renamed as TLS version 1.0 to indicate that it is no longer associated with Netscape.
In order to learn how mTLS works, we need to know how TLS works.
What is used in TLS instead of JWT secret keys?
Unlike JWT, TLS doesn’t rely on a secret key that you pass around or store in your config file. Instead, TLS—and especially mutual TLS (mTLS)—uses digital certificates and public-private key cryptography for authentication.
In a TLS setup, the server proves its identity to the client using an X.509 certificate issued by a trusted Certificate Authority (CA). This certificate includes the server’s public key. When a client connects, it verifies this certificate against its list of trusted CAs. No shared secret involved here.
Digital certificates aren’t something you generate randomly and expect everyone to trust. They need to be issued by a trusted Certificate Authority (CA)—an organisation that the internet (and your systems) already trusts.
Some of the most widely recognised certificate authorities include
DigiCert
GlobalSign
Sectigo (formerly Comodo)
Let's Encrypt (free and widely used)
Entrust
Amazon Certificate Manager (ACM)—often used inside AWS environments
How Digital Certificate look like?
The above image shows the digital certificate for substack.com, the same website that you are currently browsing. You can also see this certificate by following the below steps.
Click on the left icon in the address bar in Chrome.
Select "connection is secure."
Click on "Certificate is valid," and you will see this website certificate.
It contains issuer information and server public key that will be used for authentication later. Now we have this digital certificate; let's see how browsers authenticate it. Later on we will extend our approach to mTLS authentication.
How authentication actually happens?
When a browser connects to a server over HTTPS (which uses TLS), a TLS handshake takes place before any secure data is exchanged. Here’s a step-by-step breakdown of what happens:
1. Browser initiates a connection (Client Hello)
The browser (client) sends a ClientHello message to the server, including:
TLS version it supports (e.g., TLS 1.2, TLS 1.3)
Supported cipher suites (encryption algorithms)
A random number (used in key generation)
2. Server responds (Server Hello + Certificate)
The server replies with a ServerHello that includes:
TLS version and cipher suite chosen
Another random number
The server's digital certificate (X.509) issued by a trusted Certificate Authority (CA)
Optional: Server Key Exchange (in TLS 1.2), Certificate Request, etc.
The certificate contains:
Public key, Domain name, Expiry date, CA's digital signature
Browser verify the server
The browser checks:
Is the certificate signed by a trusted CA?
Is it expired or revoked?
Does the domain match?
If any check fails, the browser shows a security warning.
If the browser successfully validates the server certificate, it will do some additional steps to generate session keys, which will be used for encryption and decryption of data, and the connection will be set up successfully.
This is what the TLS process looks like.
What is mTLS and How Does it Work?
While traditional TLS ensures that the client can verify the server, it doesn’t verify the identity of the client. That’s where mutual TLS (mTLS) comes in.
In mTLS, both the client and the server present certificates to prove their identities. This is extremely useful when machines (like microservices or devices) need to securely communicate with each other.
Let’s break it down.
TLS vs mTLS – What's the Difference?
There is 1 additional step in mTLS of verifying the client certificate also. It ensures that only trusted clients can access a resource.
Common mTLS Use Cases in Internal Systems
Service-to-Service Authentication
Service A connects to Service B via HTTPS.
Both services present certificates.
mTLS ensures B only accepts requests from valid clients.
Zero Trust Networks
In a zero-trust setup, every service must prove its identity.
mTLS enforces identity at the network level.
Bye
I hope you found this post helpful. In the next post I might tell you how to actually write code for mTLS in Java Spring Boot and Golang. You can subscribe to this newsletter for free and get that post directly in your inbox.
Thanks, have a nice day.