Api Gateway Part 2: Handling Authentication with Spring Boot, Zuul, Spring Session and Spring Security

Nepal Brothers
5 min readMar 3, 2019

This blog is a part of building scalable Spring Boot microservices based project. It comprises of creating connecting microservices using Zuul, service discovery using Consul, security using Spring Security, distributed session using Spring Session and products such as MongoDB, Redis. Here is the chronological sequence of how I wrote article. https://medium.com/@nepalBrothers/web-development-scalable-web-app-using-spring-boot-and-spring-cloud-1f9960e1d61a

TL;DR Here’s the source code

Api Gateway

This is a microservice project. Therefore, we will need to spin up services the API-Gateway serves.

This is second part of the series of implementing Api-Gateway with Spring Boot. The previous part implemented API Gateway, but it allowed all sorts of traffic. It did not handle any authentication.

Architecture Design

  1. We will have API Gateway facing in the front. We can scale this in a way we want.
  2. We have an Account microservice handling all the account transaction. It means handling login and registration. We will use Spring Security, Spring Session for this.
  3. We have a Product microservice handling all the product transaction. This does not require user authentication. We will not need Spring Security or Spring Session here, as this microservice does not handle any user details.
  4. We also have WhoAmI microservice that given an authenticated session, responds to the user with “You are {username}” or if not, “You are anonymous”

Multi-Project development: Sharing common code in modules for applications to use

When Account microservice authenticates some user, that user information is stored in SecureUserProfile object. But, we will need to read the SecureUserPorfile in the WhoAmI microservice.

In this case, what we can do is extract SecureUserProfile as a module, and the use the same module for Account as well as WhoAmI microservices.

So, lets create Security Module: Shared Module

Well, this Security Module will need UserDetails object from Spring Security. So, we can initialize this as Spring Project with Spring Security as Dependency. We can do so by Spring Initializer.

Below is the SecureUserProfile class definition we need.

Now, we will need to import this module during compilation.

For the development purposes, we can import the module in IDE along with the projects that require this module. It can be done via maven, but for development purposes, IDE is better.

So, while building project, we will need to have these projects together.

  1. account and security

2. who-am-i and security

API Gateway

We implemented the API Gateway in the last part. But, API Gateway did not handle authentication properly.

For any authentication, we will delegate the job to Account microservice.

Modify bootstrap.yml file

In order for us to do that, we need to add the following in the bootstrap.yml file.

zuul:
routes:
product:
path: /product/**
url: http://localhost:8080
stripPrefix: true

account:
path: /**
url: http://localhost:8091
stripPrefix: false
sensitiveHeaders:

We are setting account service that will be proxied to localhost:8091. Notice that we are not passing anything in the sensitiveHeaders, which means that we want to send all the headers to the account service. This involves sending the session to the downstream services, which is how we will authenticate the users.

Modify the Post ZuulFilter

This is a little hack that I had to do in order to send traffic to the Account microservice. What basically happens is that when we try to access secure resource, such as /secure endpoint present in Account service without us logged in, it will prompt us to login but in the same port as the Account service is running. The reason for this is because the redirect response header will also contain the Location header which browser translates to send the request to that url.

API Gateway is designed to delegate the login to its port under Location Header. We overide the value using Post Zuul Filter

Lets add logic that will override the Location header.

Thats it. Doing this, we are delegating login mechanism to our Account microservice.

Lets prepare for test

Lets quickly develop whoAmI service that tells you who you are based on login details. If you are logged in, it will tell you “You are {username}” otherwise, it says, “You are anonymous”.

So, our architecture becomes:

The dependencies we would need for WhoAmI is

  1. Spring Security
  2. Spring Session
  3. Redis Session
  4. Web

Spring Boot configures pretty much everything for us, so we just need to do couple of things:

SecurityConfig

Controller

Configure application.properties

spring.application.name=whoAmI-service
server.port
=8092

Lets run test

The idea of the test is to authenticate via Account microservice, and then read the uer info from a different microservice, WhoAmI service.

At this point, we will need to have API-Gateway, Account and WhoAmI running. We can use IDE to do it for us, for use maven commandline command:

mvn spring-boot:run

Lets go to http://localhost:8090/whoAmI, we will see:

Lets login now with username = user, password = user ,

Now lets call http://localhost:8090/whoAmI

Awesome. We now have microservice architecture that

  1. has API Gateway to route the traffic to downstream services
  2. has multiple services functioning
  3. has some stateless microservice and some stateful microservice

Can we improve it more?

I believe so. We are calling microservices by the URL. If we were to scale our microservices, it will be hard to maintain as we are explicitly telling our API-Gateway to route the traffic to specific URL.

Next, we will use Consul, a service registry service, to discover our microservices using the serviceId, which is human readable. This way, whatever IP address microservices have, we wouldn’t care.

There is more to it than just calling microservice by serviceId in Consul. But, these all go to the next in the series.

--

--