Authentication with Spring Boot and JWT
Today we are going to see how to authenticate a REST API with JWT and Spring Boot. We will explain how to generate the token and how to use that same token to access resources of the same API. Step by step we will see the key components to perform the complete example.
For the example we will use the following libraries:
- Spring Boot: 2.6.3: spring-boot-starter-security and spring-boot-starter-web
- java-jwt: 3.18.3
The first step will be to create the security configuration that will allow us to indicate the configuration of our API, based on the following components:
- @EnableWebSecurity: This allows us to enable security in our API.
- WebSecurityConfigurerAdapter: Allows us to override the default behavior of the security provided by Spring.
- CORS: We enable the default configuration that we can overwrite through the CorsFilter bean.
- SessionCreationPolicy: Defines the API as Stateless avoiding the creation of HTTPSession and we disable the use of cookies.
- CSRF: By configuring the API as stateless we do not need the use of cookies.
- Configure the API response in case of an authentication error.
- We declare as public the methods that allow the login and obtaining of JWT tokens. And we implement the security for the rest of the methods.
- We add the filter to check and validate if the request has a JWT token.
The next step will be to create the JWT filter that we have seen in the previous step. The filter will allow the calls made to our API that do not have the authentication header with the JWT token to be rejected and return error 401. In which the following steps will be performed:
- Obtain the token from the request and validate it with the JwtTokenUtil utility.
- Obtain the user’s data through the token itself.
- Associate the user’s data to the Spring Security context.
As we have indicated we are going to use the java-jwt library, although there are many others available. And all of them work in a similar way because they follow the RFC-7519 specification.
Let us remember that JWT is a token divided into three parts: Header, Body, and Signature. The third part is the encryption of the two previous ones. To perform this encryption it uses an algorithm that we indicate and encrypts the contents of the token with the help of a secret key. This secret key will be stored in our example in the jwt-secret file.
Another feature of the token itself is that it allows us to store information in the form of Claims. Which can contain information of different fields but is mainly associated with the user. In our case we will create a token with the following characteristics:
- issuer: default Claim associated to the identifier of our application.
- subject: Default token associated to the user’s name.
- id: User identifier
- roles: List of roles associated with the user.
- IssuedAt: Date on which the token has been generated.
- ExpireAt: Date after which the token will not be valid.
Now we only have to create the login method with which we can create the token through the user’s identification data. To obtain and store the user data, Spring provides a couple of interfaces, such as UserDetailsService and UserDetails. The information to be obtained will allow the authentication and authorization of the user. UserDetailsService will acquire the user’s data from a database or other source.
As a last clarification, we should point out that in the filter we will not need to go back to the data source to obtain the user’s data. Since as we have already indicated the JWT token already contains the information of the user and it is more efficient to obtain the data of the user of the own JWT.
As always, you can consult the code here.