Spring boot JWT Authentication

Spring boot is a good option for me when I need to build an API or microservices. Like every good developer, we need to secure API endpoint to prevent lots of security issues.

In one of my project, I decided to uses JWT Authentication to secure API that is exposed to a mobile application, besides the normal username/password to secure web controller

Why JWT

  1. JWT is sessionless, so server don’t need to create and store session, which saves resources
  2. JWT is secure. That much is undenied
  3. JWT can be used to store data that saves the server time to query the data. This is useful especially if the data is often queried with every API call (for instance to store the user entity details so that server don’t have to query data to populate loggedUser)

Authentication and Authorization

For those who’s still unclear, authentication and authorization is two different process and goals.

Authentication is process to validate username and password and give the user a session/token so user can proceed to the next activity. Authentication is a login process.

Authorization is process to validate whether a user has permission to access the requested action. Authorization is process in every API request.

The implementation

Lot’s of ways to implement JWT authentication and authorization. This is how I do it in my projects. Basically we add new security configuration in springboot (things called ‘filter’) to inform it on how the authentication process should be done, and how the authorization process is.

For creating and parsing the JWT, I uses third party library

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>

First, let’s look on to the security configuration. This will make sure that our /api/** endpoint is going to be secured.

We already told springboot that to authenticate, please use JWTAuthenticationFilter and to authorize, please use JWTAuthorizationFilter. For both classes, we pass authenticationManager to help in validating the username and password

Result of a successful authentication is a 200 response, but we add a certain header (in this case is Authorization) that stores the token. The mobile app will then receive this response, find the Authorization header and store the value. The value is a string Bearer appended with the token.

Why not just token? Why use a custom string? No reason. I just like to add that.

For every API request that’s done by the mobile, it will have to add the Authorization key in the header, and put the authorization value that it stored before (the Bearer appended with token). Without this header, the boot will response with 403 Forbidden.

Let’s see how the authorization is processed.

With this, we only need to check the validity of the JWT, whether it is untampered with, or if token is not expired. Then we collect all data we stored in the JWT to create authenticationToken that can be accessed from SecurityContextHolder anywhere in the code. For example, I can retrieve the username using SecurityContextHolder.getContext().getAuthentication().getName(). The ‘name’ can be filled with everything your system need, like email, username, userId, userUUID, etc.