Patterns in Microservices Authentication with Client Certificates
For companies working within a microservices architecture, authenticating microservices can be a challenge. Luckily, there are well-established microservice authentication patterns that can help.
In this blog, we give a quick overview of microservices, break down microservices authentication, and discuss a proven pattern for secure authentication between microservices.
- What Are Microservices?
- What Is a Certificate of Microservices Authentication?
- Challenges With Microservices Authentication
- Why Microservices Authentication Is Important
- How to Secure Authentication Between Microservices
What Are Microservices?
Microservices are a pattern, or architecture, that is focused around small, loosely-coupled services that comprise a greater application.
Microservices enable teams to create small, siloed pieces of functionality where each team owns their whole stack. They each do a little piece and then all those small pieces add up to be the whole.
What Is a Certificate of Microservices Authentication?
Authentication between microservices can be achieved using mutual TLS certificate. In these scenarios, a certificate is generated for each microservice. The microservices then use each other's certificate to authenticate.
However, there are challenges in microservices that need to be addressed — especially security.
Challenges With Microservices Authentication
Recently, I was working with a customer on an issue involving a Wildfly 16 microservices mesh. The customer had multiple Wildfly containers running disparate workloads in standalone mode. If you’re a Java EE developer who’s familiar with some of these technologies, you can think of this as a heavy, EE-based way of doing a Spring Boot microservices mesh, complete with access to EJB, MDB, transactions, caching, JSF, WebSockets, management features, and other patterns — all out of the box.
One of the challenges this customer was facing was working with machine accounts, specifically calling from one Wildfly instance to another, to ensure secure microservices authentication. They wanted to show they could securely prove the identity of an individual Wildfly container to make machine-account-style calls against other APIs. We accomplished this by using Wildfly Elytron to enable client certificate authentication via Mutual Transport Layer Security (Mutual TLS or MTLS).
How to Secure Authentication Between Microservices
Securing authentication between microservices can be challenging. In our recent white paper, we provide a step-by-step tutorial for mutual TLS.
Why Microservices Authentication Is Important
If you’ve never written a microservice-style application before, the best way to describe the necessity of machine-account (or service-account) API-call credentials is through an example.
Let’s say we’re working on a microservice where the domain is related to the User and Group objects. Users have properties like names, IDs, passwords, and profile pictures, and are added to groups that have similar properties. I might write services in the microservice app that create, read, update, and delete from a database, or table, with credentials specific to my microservice.
What happens when a user needs to, for example, check out equipment from the equipment microservice? What if there needs to be a utility method written for the profile page that lists each user’s checked-out equipment? Even more complicated, which group has which equipment checked out, and who is the manager of that group as a point of contact?
Keep Business Logic on the Back-End
Suddenly, the architecture team is being asked to make a call:
Do I push my business logic to the single page application, and keep my microservices “pure?”
After all, it would be so easy to just “do this in Angular.” The correct architectural decision for authentication between microservices is keeping business logic on the back-end, away from the front-end developers, who genuinely want to worry more about CSS and less about business needs as rendered in RxJS.
I would also argue that it’s not muddying the waters or “impure” to have microservices calling other microservices from the back-end. In fact, it’s a well-known pattern across the enterprise, and it’s why we have terms like machine account and service account.
How to Secure Authentication Between Microservices
So, how do you secure authentication between microservices? One way is to utilize the existing token architecture that you’re probably already using on your front-end: JSON Web Tokens (JWT).
They’re cryptographically secure, easy to work with, and hey, you’re already using them! Why not just grant a special privilege in your code to machine01@internal with a special password on your authentication service, and just give it a really long timeout so that it’s not constantly hammering the login system?
One reason for this is that your authentication library probably doesn’t have a usable way of revoking a JWT after it’s been granted without a stop-the-world systems disruption. This is why there’s a strong preference for MTLS as an identity provider for machine accounts accessing HTTPS resources.
Ensure Secure Authentication Between Microservices
Need to ensure secure authentication between microservices? We know it can be challenging That's why we recently put together a white paper to make it easier: Secure Your Container-Based Microservices with Client Certificate Authentication.
Get the white paper to learn:
- About your options for authentication between microservices, including Mutual Transport Layer Security (Mutual TLS), Transport Layer Security (TLS), or JSON Web Tokens (JWT).
- When it can be advantageous to use Mutual TLS for client certificate authentication instead of TLS or JWT.
- A step-by-step tutorial for implementing Mutual TLS authentication.
- How to manage certificates with Wildfly Elytron Client SSL Contexts.