Implementing code to return JWT Token once the user in Authenticated | Spring Security Authorization using JWT Token
Experienced Spring Boot Developer with over 3+ years of expertise in developing scalable and high-performance web applications and microservices. Proficient in Java and Spring Boot frameworks, with hands- on experience in RESTful APIs and Microservices architecture. Adept at building secure, database-driven applications and integrating various third- party services. Strong problem-solving skills with a focus on delivering clean, maintainable, and efficient code.
Previously we implemented code to implement Authentication using BCryptPasswordEncoder.
Let’s implement JWT Token base authorization now.
Step 1 → Add dependencies.
<!-- JWT -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-jackson</artifactId>
<version>0.11.5</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>0.11.5</version>
<scope>runtime</scope>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.30</version>
<scope>provided</scope>
</dependency>
Step 2 → Implement “JwtAuthenticationEntryPoint“ class.
This class will act as an Exception Handler.
The method “commence“ on this class just checks is the user trying to access the resource is Authorized to access that resource or not. If not, the it throws an exception with error message.
package com.Demo.SpringSecurityDemo.Security;
import java.io.PrintWriter;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.io.IOException;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class JwtAuthenticationEntryPoint implements AuthenticationEntryPoint {
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException, java.io.IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
PrintWriter writer = response.getWriter();
writer.println("Access Denied !! " + authException.getMessage());
}
}
Step 3 → Implement “JwtHelper” class.
It has everything regarding JWT Token like -
Token generation
Validate token
Fetch data from token
Check if token is expired
Contains Secret Key
etc.
package com.Demo.SpringSecurityDemo.Security;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
@Component
public class JwtHelper {
//requirement :
public static final long JWT_TOKEN_VALIDITY = 5 * 60 * 60;
// public static final long JWT_TOKEN_VALIDITY = 60;
private String secret = "afafasfafafasfasfasfafacasdasfasxASFACASDFACASDFASFASFDAFASFASDAADSCSDFADCVSGCFVADXCcadwavfsfarvf";
//retrieve username from jwt token
public String getUsernameFromToken(String token) {
return getClaimFromToken(token, Claims::getSubject);
}
//retrieve expiration date from jwt token
public Date getExpirationDateFromToken(String token) {
return getClaimFromToken(token, Claims::getExpiration);
}
public <T> T getClaimFromToken(String token, Function<Claims, T> claimsResolver) {
final Claims claims = getAllClaimsFromToken(token);
return claimsResolver.apply(claims);
}
//for retrieveing any information from token we will need the secret key
private Claims getAllClaimsFromToken(String token) {
return Jwts.parser().setSigningKey(secret).parseClaimsJws(token).getBody();
}
//check if the token has expired
private Boolean isTokenExpired(String token) {
final Date expiration = getExpirationDateFromToken(token);
return expiration.before(new Date());
}
//generate token for user
public String generateToken(UserDetails userDetails) {
Map<String, Object> claims = new HashMap<>();
return doGenerateToken(claims, userDetails.getUsername());
}
//while creating the token -
//1. Define claims of the token, like Issuer, Expiration, Subject, and the ID
//2. Sign the JWT using the HS512 algorithm and secret key.
//3. According to JWS Compact Serialization(https://tools.ietf.org/html/draft-ietf-jose-json-web-signature-41#section-3.1)
// compaction of the JWT to a URL-safe string
private String doGenerateToken(Map<String, Object> claims, String subject) {
return Jwts.builder().setClaims(claims).setSubject(subject).setIssuedAt(new Date(System.currentTimeMillis()))
.setExpiration(new Date(System.currentTimeMillis() + JWT_TOKEN_VALIDITY * 1000))
.signWith(SignatureAlgorithm.HS512, secret).compact();
}
//validate token
public Boolean validateToken(String token, UserDetails userDetails) {
final String username = getUsernameFromToken(token);
return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
}
}
Step 3 → Implement “JwtAuthenticationFilter“ class.
Here we are implementing a filter which -
Separates Token and Username from the Authentication Header.
Gets user details using username.
Then validates the token. If successfully validated then the access is granted.
package com.Demo.SpringSecurityDemo.filter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;
import com.Demo.SpringSecurityDemo.Security.JwtHelper;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.io.IOException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
@Component
public class JwtAuthenticationFilter extends OncePerRequestFilter {
private Logger logger = LoggerFactory.getLogger(OncePerRequestFilter.class);
@Autowired
private JwtHelper jwtHelper;
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException, java.io.IOException {
//Getting header data in requestHeader variable
String requestHeader = request.getHeader("Authorization");
logger.info(" Header : {}", requestHeader);
String username = null;
String token = null;
//Code to get token in token variable by removing "Bearer " from the front.
//Once we have the token we fetch username form it using "JwtHelper" class and put username in usnername variable.
if (requestHeader != null && requestHeader.startsWith("Bearer")) {
token = requestHeader.substring(7);
try {
username = this.jwtHelper.getUsernameFromToken(token);
} catch (IllegalArgumentException e) {
logger.info("Illegal Argument while fetching the username !!");
e.printStackTrace();
} catch (ExpiredJwtException e) {
logger.info("Given jwt token is expired !!");
e.printStackTrace();
} catch (MalformedJwtException e) {
logger.info("Some changed has done in token !! Invalid Token");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
} else {
logger.info("Invalid Header Value !! ");
}
//Once we have username, we now validate the user
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
//Fetching user detail from username
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
//Asking JwtHelper to validate token
Boolean validateToken = this.jwtHelper.validateToken(token, userDetails);
if (validateToken) {
//set the authentication
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
SecurityContextHolder.getContext().setAuthentication(authentication);
} else {
logger.info("Validation fails !!");
}
}
filterChain.doFilter(request, response);
}
}
Step 4 → Implementing “SecurityConfig“ and “AppConfig” class.
In SecurityConfig we define -
Cors
Request Matchers (Defining which resource/urls can be accessed by which Role)
Exception Handling entry point Class
etc
package com.Demo.SpringSecurityDemo.Config;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import com.Demo.SpringSecurityDemo.Security.JwtAuthenticationEntryPoint;
import com.Demo.SpringSecurityDemo.filter.JwtAuthenticationFilter;
@Configuration
public class SecurityConfig {
@Autowired
private JwtAuthenticationEntryPoint point;
@Autowired
private JwtAuthenticationFilter filter;
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable())
.cors(cors->cors.disable())
.authorizeHttpRequests(auth->
auth.requestMatchers("/test/**").authenticated()
.requestMatchers("/auth/login").permitAll().anyRequest().authenticated())
.exceptionHandling(ex -> ex.authenticationEntryPoint(point))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
}
In AppConfig we define in-memory users.
package com.Demo.SpringSecurityDemo.Config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
@Configuration
@EnableWebSecurity
public class AppConfig {
@Bean
public UserDetailsService userDetailsService() {
UserDetails userDetails1 = User.builder()
.username("DURGESH@temp.com")
.password(passwordEncoder().encode("DURGESH"))
.roles("ADMIN")
.build();
UserDetails userDetails2 = User.builder()
.username("pratt@email.com")
.password(passwordEncoder().encode("pratt"))
.roles("USER")
.build();
return new InMemoryUserDetailsManager(userDetails1, userDetails2);
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration builder) throws Exception {
return builder.getAuthenticationManager();
}
}
Step 5 → Implement models “JwtRequest“ and “JwtResponse” Java classes.
package com.Demo.SpringSecurityDemo.Models;
import lombok.*;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class JwtRequest {
private String username;
private String password;
}
package com.Demo.SpringSecurityDemo.Models;
import lombok.*;
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString
public class JwtResponse {
private String jwtToken;
private String username;
}
Step 6 → Implement “AuthController”.
It does -
Get Request data in JwtRequest, then passes email and password to “doAuthenticate“ method, for user details to be authenticated.
“doAuthenticate“ method uses “AuthenticationManager“ to Authenticate user details.
Once user is authenticated, it generates JWT token for the user using JwtHelper class. Then it returns JWT Token and username as response.
package com.Demo.SpringSecurityDemo.Controllers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.Demo.SpringSecurityDemo.Models.JwtRequest;
import com.Demo.SpringSecurityDemo.Models.JwtResponse;
import com.Demo.SpringSecurityDemo.Security.JwtHelper;
@RestController
@RequestMapping("/auth")
public class AuthController {
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationManager manager;
@Autowired
private JwtHelper helper;
private Logger logger = LoggerFactory.getLogger(AuthController.class);
@GetMapping("/hello")
public String sayHello() {
return "Hello, World!";
}
@PostMapping("/login")
public ResponseEntity<JwtResponse> login(@RequestBody JwtRequest request) {
this.doAuthenticate(request.getUsername(), request.getPassword());
UserDetails userDetails = userDetailsService.loadUserByUsername(request.getUsername());
String token = this.helper.generateToken(userDetails);
JwtResponse response = JwtResponse.builder()
.jwtToken(token)
.username(userDetails.getUsername()).build();
return new ResponseEntity<>(response, HttpStatus.OK);
}
private void doAuthenticate(String email, String password) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(email, password);
try {
manager.authenticate(authentication);
} catch (BadCredentialsException e) {
throw new BadCredentialsException(" Invalid Username or Password !!");
}
}
@ExceptionHandler(BadCredentialsException.class)
public String exceptionHandler() {
return "Credentials Invalid !!";
}
}
Step 7 → Properties file - Nothing as such important to be added in the properties file.
spring.application.name=SpringSecurityDemo
server.port=8020
Using POST Request we can now get out user authenticated and get JWT Token as response.

Using this generated JWT Token we can now access other resources/api whose access has been granted to our user.
