MTS

Edge Authentication on Microservices

20 November, 2021

4 min read

Edge Authentication on Microservices

Give a boost to your identity propagation

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.

Classic structure

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:

  • Mobile App
  • Web site
  • API Gateway (Kubernetes Ingress)
  • Authentication provider (it performs also token validation)
  • Message Broker (Google PubSub)
  • Order microservice
  • Product microservice
  • Delivery microservice

*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.

Some thoughts

Token expiration

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.

User data changes

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.

Edge Authentication structure

The structure with Edge Authentication is similar to classic structure but is based on some principles:

  • We use two type of token: one public token (for clients) and one private token (for internal API calls and message broker);
  • Private token encapsulates all necessary data and doesn’t change in time: it’s a long-life token;
  • Private token is never used outside of backend;
  • The API Gateway validates public token against the Auth Provider who exchanges it with a private one;
  • Each microservice must unpack private token and handle his security context;

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:

  • Token can’t expires while saga is running (we will mark it invalid after that saga ends);
  • Current user data doesn’t changes and are attached to the request, so can be used easily;

Conclusions

  • Authorization is simplified;
  • We share an explicit and extensible identity model;
  • Microservices and Auth Provider are loosely coupled;
  • Reduced hops and API response time;
  • Reduced downstream system complexity;
  • Architecture is still technology-agnostic due to each service must handle his security context;
  • Development time is reduced and each development team can focus only on the microservice;

Bonus

I created a proof of concept here with this tech stack:

  • Kubernetes;
  • Spring Boot microservice;
  • NodeJS microservice;
  • NodeJS Auth provider;

See you space cowboy…

Related posts

Database per service, shared instance or shared database?

Database per service, shared instance or shared database?

Busting common metropolitan legends about databases in microservice architecture

18 May, 2022