Spring Boot Jwt Authentication

By | | Updated : 2022-04-23 | Viewed : 110 times

Spring Boot Jwt Authentication

In this tutorial, we are going to learn Spring JWT Authentication with a simple example. The Spring application that we implement will use the JWT tokens. Using decoding of JWT Token, Spring application provides authentication and authorization.

Spring Security Terminology

Now, we will focus on the basic terminology of the spring security. Why does spring application require the security? To answer the question, to provide authentication and authorization, application should contain the security. Using the authentication and authorization with spring security, we can avoid the attacks/hacks on the application .

AuthenticationAuthentication is basically a process of user validation. In this process, the Spring security validates whether a user is valid by checking the credentials, such as username and password. In simple terms, authentication is nothing but the user’s validation through a process.

AuthorizationAuthorization is also a process and typically deals with user privileges on different resources, which means a process to check if a particular user has a privilege on a particular resource. For example, the admin may have a privilege used for special actions such as user manipulation, whereas the user does not have the same type of privileges.

Roles and Privileges 

Principle: specifies the current authenticated user

Role: specifies to the set of privileges of authenticated User

Granted Authority: specifies privileges of the authenticated User.

Now we will discuss the Spring Security authentication components and what they defined for.

Spring Security Authentication Components

WebSecurityConfigurerAdapter: It allows to configure HttpSecurity through the configure() method. HttpSecurity configurations contain the URLs, which are restricted to access. The users those who have authorization can access these URLs.

UserDetails Service: It contains authenticated UserDetails, i.e., user data. The DaoAuthenticationProvider use UserDetailsService class to gather user’s information whenever the Spring framework needed.

UsernamePasswordAuthenticationToken: The token contains usernames and passwords.

AuthenticationManager: It performs the authentication of the UsernamePasswordAuthenticationToken object of the user. It returns UsernamePasswordAuthenticationToken with credentials and granted privileges in a successful authentication.

AuthenticationEntryPoint: It performs the required steps when authorization fails.

OncePerRequestFilter: The filter executes once per request and dispatches the request to the remaining filters if conditions are okay.

We will discuss the entire Spring Security architecture in a separate tutorial with a simple explanation.

Spring Boot JWT Authentication Example

Now we will try to start the implement the JWT Authentication in Spring Boot.

Maven Dependencies

You need to download the project using spring initialized using this link, then add the below given dependencies to set up the spring JWT token based authentication project.

Spring Security Dependencies
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

In this project, we are using the Java 12. We need to set up JAXB dependencies separately. Please find the same dependencies for the same.

JAXB Dependencies For Java
<dependency>
	<groupId>jakarta.xml.bind</groupId>
	<artifactId>jakarta.xml.bind-api</artifactId>
	<version>2.3.3</version>
</dependency>
<dependency>
	<groupId>com.sun.xml.bind</groupId>
	<artifactId>jaxb-impl</artifactId>
	<version>2.3.3</version>
	<scope>runtime</scope>
</dependency>

This below dependency performs the decoding and encoding JWT tokens in java. In the current application, it performs the authentication and authorization using encoding of JWT token to validation of user and performing user authorization.

Now, we will look into implementing the Spring project for JWT token based authentication.

Implement Spring Security JWT Project

Write Code For WebSecurityConfig

Please see the below code snippet for WebSecurityConfig Class.

WebSecurityConfig allows for configuring security for specific resources. These configurations relate to users’ authentication and resource security based on roles and privileges. Please observe the below given coded class.

WebSecurityConfig.java
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Autowired
	private JwtUnauthorizedHandler jwtUnauthorizedHandler;

	@Autowired
	private UserDetailsService jwtUserDetailsService;

	@Autowired
	private JwtAuthenticationFilter jwtAuthenticationFilter;

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
	}

	@Bean
	public static PasswordEncoder passwordEncoder() {
		return new BCryptPasswordEncoder();
	}

	@Bean
	@Override
	public AuthenticationManager authenticationManagerBean() throws Exception {
		return super.authenticationManagerBean();
	}

	@Override
	protected void configure(HttpSecurity httpSecurity) throws Exception {
		httpSecurity.csrf().disable()
				.authorizeRequests().antMatchers("/jwt/validate/userToken","/jwt/validate/adminToken").permitAll()
				.anyRequest().authenticated().and()
				.exceptionHandling().authenticationEntryPoint(jwtUnauthorizedHandler).and().sessionManagement()
				.sessionCreationPolicy(SessionCreationPolicy.STATELESS);

		httpSecurity.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
	}
}

Write Code For JwtAuthenticationFilter

JwtAuthenticationFilter performs validation on the token by decoding the token. When the JWT token gets validated, then UsernamePasswordAuthenticationToken will be created from UserDetailsand and will be stored in the Security context. Please see the below code.

JwtAuthenticationFilter.java
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {

	@Autowired
	private UserService userService;

	@Autowired
	private JwtTokenUtils jwtTokenUtils;

	@Override
	protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
			throws ServletException, IOException {

		final String requestTokenHeader = request.getHeader("Authentication-Data");

		Optional<String> optionalJwtToken = jwtTokenUtils.getJwtFromRequest(request);
		if (optionalJwtToken.isPresent() && SecurityContextHolder.getContext().getAuthentication() == null) {

			String jwtToken = optionalJwtToken.get();
			Optional<Jws<Claims>> OptionalClaims = jwtTokenUtils.getClaimsFromJwtToken(jwtToken);
			if (OptionalClaims.isPresent()) {

				Jws<Claims> jwsClaims = OptionalClaims.get();
				Claims claimsBody = jwsClaims.getBody();
				String userName = (String) claimsBody.get("userName");
				String displayName = (String) claimsBody.get("displayName");
				String roleName = (String) claimsBody.get("roleName");
				String isEnabled = (String) claimsBody.get("isEnabled");
				String email = (String) claimsBody.get("email");
				String password = (String) claimsBody.get("password");

				UserDetails userDetails = this.userService.loadUser(userName,displayName,roleName,isEnabled,email,password);
				UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
						userDetails, null, userDetails.getAuthorities());
				usernamePasswordAuthenticationToken
						.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
				SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
			}
		}
		chain.doFilter(request, response);
	}

}

Write Code For JwtUnauthorizedHandler

JwtUnauthorizedHandler will be into the picture when an unauthorized role tried to access the resources.

JwtUnauthorizedHandler.java
@Component
public class JwtUnauthorizedHandler implements AuthenticationEntryPoint {

	@Override
	public void commence(HttpServletRequest request, HttpServletResponse response,
			AuthenticationException authException) throws IOException {
		response.sendError(HttpServletResponse.SC_UNAUTHORIZED, "Unauthorized User");
	}
}

Write Code For JwtAuthController

JwtAuthController.java
@RestController
@RequestMapping(value = "/jwt")
public class JwtAuthController {

	@Autowired
	private JWTAuthService jWTAuthService;

	@PreAuthorize("hasRole('USER')")
	@PostMapping(value = "/validate/userToken", produces = "application/json")
	public ResponseEntity<?> validateUserToken(@RequestBody ValidateTokenRequest validateTokenRequest) {
		return jWTAuthService.validateUserToken();
	}

	@PreAuthorize("hasRole('ADMIN')")
	@PostMapping(value = "/validate/adminToken", produces = "application/json")
	public ResponseEntity<?> validateAdminToken(@RequestBody ValidateTokenRequest validateTokenRequest) {
		return jWTAuthService.validateAdminToken();
	}

}

And there are other class files are need to be implemented. You can find the entire application code in the GitHub repo here Spring-boot-Jwt-without-Database. We now execute the about the requests to check the application is working fine or not.

Generate JWT Tokens For User And Admin

Please open the URL https://jwt.io/ and provide payload as given below.

JWT Payload For User
{
  "name": "1234567890",
  "userName": "docsconsoleUser",
  "roleType": "user",
  "isEnabled": "yes",
  "password":"testPassword",
  "email":"testuser@docsconsole.com"

}

Now you can see the token generated as below. So we are going to pass the same token for the user. In payload, you can change details as per your needs.

JWT Token For User
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiMTIzNDU2Nzg5MCIsInVzZXJOYW1lIjoiZG9jc2NvbnNvbGVVc2VyIiwicm9sZU5hbWUiOiJ1c2VyIiwiaXNFbmFibGVkIjoieWVzIiwicGFzc3dvcmQiOiJ0ZXN0UGFzc3dvcmQiLCJlbWFpbCI6InRlc3R1c2VyQGRvY3Njb25zb2xlLmNvbSJ9.8PIALnlkazjcZ5qpnLqfyU9_B3vkMElLp_g4JERNPbU

In the same way, we can create the JWT token for the admin role. If you want used regenerated JWT token, you can refer the project folder in GitHub.

Test Spring Boot JWT Token Based Authentication

We will test the project using the postman. You can find the Postman collection in the project itself. Please find the below given screenshots for the same.

Spring Boot JWT Authentication Postman Collection
Spring Boot JWT Authentication Postman Collection

Please find GitHub repo here Spring-boot-Jwt-without-Database

Leave A Reply