Some time ago I read this awesome article in Netflix Tech Blog about their use of an edge authentication in a Microservices Architecture. The interesting thing about this implementation is how it grants a plenty of benefits: this service grants an agnostic identity propagation and boosts the performance of the entire architecture, improving decoupling of microservices and reducing API response time and, at same time,improving security.
Inspiring to Netflix’s article I implemented a similar solution into a project at my work. In this article I will explain how I implemented this solution.
Usually there is a microservice in charge to check identity and validate token, and this service is used by clients and the others microservices.
Talking about a real case, imagine you have an Online Shop deployed in Google Kubernetes Engine* with these actors:
*you could have a simple K8s cluster or Spring Cloud infrastructure. The Edge Authentication is agnostic technology, in my case I used GKE.
When an user place an order this is a possible scenario of the Saga Pattern:
Order Microservice receives new order via API, before each operation it validates the token against the Auth Provider, if successes then asks user info andthen save data of the order, at the end requests to Product Microservice some info via API.
Product Microservice validates again the token against the Auth Provider, ask s user info, performs his actions and, finally, returns the response to Order. Then Order Microservice sends a new request to Delivery Microservice to place a delivery status, and again: Delivery Microservice must validates token and so on.
So basically each microservice asks to the Auth Provider to validates token and asks user info, even if API requests are internals and not from outside. This is means that for each internal request the service that received it must validates the token and asks user info to the Auth Provider.
In the previous structure the token expiration is a serious problem: it’s a best practice token expiration, but inside a saga is wrong. A saga is a distributed action and each part of it should be considered as a piece of a unique operation.
The same scenario in a Monolithic architecture is a unique transaction and in a Microservices architecture is the same things, the only difference is that there isn’t a physical transaction.
Like token expiration, user data shouldn’t changes while a saga is running because we risk that some steps aren’t consistent and there is the chance of wrong state, even security breach.
The structure with Edge Authentication is similar to classic structure but is based on some principles:
So the previous schema become:
In this way each public API call is validated in advance from Kubernetes Ingress against the Auth Provider: if the public token is expired or is invalid the request is rejected, otherwise the token is exchanged with a private token (like a JWT).
Kubernetes Ingress attach the private token and routes the API request to the matched microservice. From now all internal API requests are authenticated with the private token. Even messages of Google PubSub could be authenticated.
With this structure each microservice, when API request arrives, don’t validates the token any more neither asks for user info, instead he has the responsibility to unpack incoming token and handle his security context with the info inside the token. So we are sure that:
I created a proof of concept here with this tech stack:
See you space cowboy…
Busting common metropolitan legends about databases in microservice architecture