JWT authentication and role-based authorization in Springboot

Ankitha Gowda
4 min readMar 3, 2022

--

Photo by FLY:D on Unsplash

Hey There, as you might also feel configuring authentication and authorization is always been the most confusing task in java. It involves many classes and a person will get lost till he reaches the end. Let's look at JWT authentication in the Springboot application in a simpler way.

Background:

Authentication: Check if you are allowed to access the application

Authorization: Decide what part of the application you can access based on your role.

Different ways to authenticate include: basic authentication(username and password), token-based authentication, API key, O-Auth and others. For more information about JWT authentication, you can refer here.

Simple Springboot Application:

Create a simple Springboot application with endpoints to access or update University data (stored in the “University” table). And, we want these endpoints to be accessed only with the correct token. For JWT we will have a separate table ( stored in the “UserData” table) to store credentials and roles. The overall implementation looks something like below:

We will follow below steps:

Step1: Enable security in the Springboot application

Step2: Setup the in-memory H2 database tables with SQL scripts

Step3: Implement JWT authentication

Step4: Extend it to consider role-based access (optional)

Step1: Enable security in the Springboot application

First of all, we need Spring security jars. Include the below dependency in the pom.xml file.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>

In this jar, we have one abstract class WebSecurityConfigurerAdapter, using which we can configure the security of the whole application. By default, authentication is disabled. To enable it we need to customize the implementation of methods in this class. You can refer to available options in the official documentation.

Extend the class WebSecurityConfigurerAdapter and override the methods

  1. authenticationManagerBean() — to get Bean of AuthenticationManager
  2. configure(HttpSecurity httpSecurity) — To allow or restrict any endpoint for authentication.

In the above code snippet, the annotation @EnableWebSecurity is used to enable the security of the Application. As you might guess, we need not authenticate the endpoint used to get the token (“/authenticate”). Also, since we are using the H2 database, we have to allow access to it as well (“/h2-console/*).

Optional configurations:

  1. Since this application will be used by non-browser clients, we can disable csrf.
  2. In case of unauthorized access, we can customize the error message in response by implementing an interface AuthenticationEntryPoint.
  3. If we do not want to store user state, we can make it a stateless session.

For each request to the application, token validation and setting the authentication in context will be done in a customized filter JwtRequestFilter.java added before UsernamePasswordAuthenticationFilter

Step2: Setup the in-memory H2 database tables with SQL scripts

In application.properties or application.yml file, include H2 database connection details, JWT secret and port number:

Let's have some tables be loaded once the application starts. As mentioned above we will have two tables. So, include the below SQL scripts in the resources folder:

schema.sql :

To have some initial data in tables:

data.sql:

Also, create corresponding POJO classes(UserData.java and UniversityDB.java) and interfaces(UserDataRepo.java and UniversityRepo.java) implementing JpaRepository to perform DAO operations.

Note: For more details on sql script execution on application start-up refer Spring documentation

As mentioned above, let us have one POST endpoint (“/authenticate”) for authentication purposes, which accepts username and password. If they are genuine, it returns the token. The returned token could be used to access university endpoints of the application till gets expired(if configured to expire within some specified time).

The credentials passed in the authentication endpoint will be validated in UserDetailsService bean as below:

In the above code, we can pass an empty list if role-based authorization is not required while creating a User object.

Step3: Implement JWT authentication

Create an endpoint “/authenticate” which accepts login credentials in the body. Authenticate the username and password. Fetch all details about a user from the H2 database and generate a token using jwt-secret from properties file. Send the token as a response.

The token generation can be customized as below:

In the above code, we customized the token to expiration time to 5 hours.

The above token validation is invoked as part of filter JwtRequestFilter:

The main business API endpoint calls:

You will be able to get the response after providing the token in above API calls.

Step4: Extend it to consider role-based access(Optional)

Now, the user has been authenticated to access the application. Based on his role, he will get access to parts of the application. For example, only admin can access the DELETE endpoints, users with EDITOR role can only call POST endpoints and other normal users can only see the data i.e, invoke only GET endpoints. Just an example :-).

Note: Spring security adds the prefix “ROLE_” by default to user roles.

To include the user roles in token generated, uncomment the code in generateToken() of JwtTokenUtil.java class.

To consider roles while accessing university endpoints,

Now, only the user with a specified role can access the endpoints.

Thank you for reading. Happy exploring!!!

The complete code with role-based authorization can be found on GitHub here

--

--