In this lesson, you will learn how to secure communication between microservices using mutual TLS (mTLS) and service-to-service authentication.
While JWTs are excellent for passing user identity through a chain of services, they don't solve the "who are you" problem between the services themselves. If a malicious internal service gains access to your network, it could attempt to spoof requests to other services. To prevent this, we use mutual TLS (mTLS).
How mTLS Works
In standard TLS, only the client verifies the server's certificate. In mTLS, both parties must present a certificate signed by a common Trusted Certificate Authority (CA). The server rejects any incoming connection that does not provide a valid certificate issued by your internal CA. This ensures that only services you have explicitly provisioned can talk to each other.
Implementing in C#
When using HttpClient in your services, you configure the client to present a client certificate. In your Program.cs or Startup.cs, you can define a HttpClient that loads a certificate from your local machine store or a secure key vault:
builder.Services.AddHttpClient("SecureServiceClient", client => {
client.BaseAddress = new Uri("https://internal-service/");
})
.ConfigurePrimaryHttpMessageHandler(() => {
var handler = new HttpClientHandler();
var cert = new X509Certificate2("path/to/client-cert.pfx", "password");
handler.ClientCertificates.Add(cert);
return handler;
});
Strengthening with Service-to-Service Authentication
Even with mTLS, you often want an extra layer of authorization. You can treat the service's identity as a "machine principal." By using a client credentials flow (concept #24), your service requests an access token from your OIDC provider, using its own client ID and secret.
When Service A calls Service B, it presents:
- The mTLS connection to prove network-level trust.
- An Access Token in the
Authorizationheader to prove service-level permissions.
By combining these, you ensure that even if an attacker breaks into the network, they cannot impersonate a service without the private key of the certificate and the registered credentials for the OIDC provider.
Key Takeaway: Use mutual TLS to establish a trusted, encrypted tunnel between services, and layer service-specific tokens on top to enforce granular, identity-based authorization.