I’m working on a Spring Boot project where I’m implementing JWT-based authentication. However, I’m facing an issue where **currentAuthenticatedUser **is returning null in my JWT generate filter class. Here’s a brief overview of my setup:
JWT Generate Filter Class:
<code>package com.onlineBankingOperations.config.filter;
import com.onlineBankingOperations.config.filter.constant.JWTSecurityConstant;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.crypto.SecretKey;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.stream.Collectors;
public class JWTTokenGenerateFilter extends OncePerRequestFilter {
* @throws ServletException
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
System.out.println("JWTTokenGenerateFilter executed");
//first we need to load the current authentication object means current logged in user
Authentication currentAuthenticatedUser = SecurityContextHolder.getContext().getAuthentication();
//here we checking the user is present or not if yes then we have to generate the token if no then simple called the dofilter method
if(currentAuthenticatedUser != null){
SecretKey key = Keys.hmacShaKeyFor(JWTSecurityConstant.JWT_SECRET_DEFAULT_VALUE.getBytes(StandardCharsets.UTF_8));
String jwt = Jwts.builder()
.claim("username", currentAuthenticatedUser.getName())
.claim("authorities", currentAuthenticatedUser.getAuthorities()
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(",")))
.expiration(new Date(new Date().getTime() + 30000000))
response.setHeader(JWTSecurityConstant.JWT_HEADER, jwt);
System.out.println("JWT Token set in response header: " + jwt);
System.out.println("No authenticated user found");
filterChain.doFilter(request, response);
// if the shouldNotFilter method return true the above JWTTokeGenerateFilter method not execute for those ture condtion
//This filter only execute only once during the login operation if we fale the below method
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return !request.getServletPath().equals("/client/login");
<code>package com.onlineBankingOperations.config.filter;
import com.onlineBankingOperations.config.filter.constant.JWTSecurityConstant;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.crypto.SecretKey;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.stream.Collectors;
public class JWTTokenGenerateFilter extends OncePerRequestFilter {
/**
* @param request
* @param response
* @param filterChain
* @throws ServletException
* @throws IOException
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
System.out.println("JWTTokenGenerateFilter executed");
//first we need to load the current authentication object means current logged in user
Authentication currentAuthenticatedUser = SecurityContextHolder.getContext().getAuthentication();
//here we checking the user is present or not if yes then we have to generate the token if no then simple called the dofilter method
if(currentAuthenticatedUser != null){
SecretKey key = Keys.hmacShaKeyFor(JWTSecurityConstant.JWT_SECRET_DEFAULT_VALUE.getBytes(StandardCharsets.UTF_8));
String jwt = Jwts.builder()
.issuer("Online Bank")
.subject("JWT Token")
.claim("username", currentAuthenticatedUser.getName())
.claim("authorities", currentAuthenticatedUser.getAuthorities()
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(",")))
.issuedAt(new Date())
.expiration(new Date(new Date().getTime() + 30000000))
.signWith(key)
.compact();
response.setHeader(JWTSecurityConstant.JWT_HEADER, jwt);
System.out.println("JWT Token set in response header: " + jwt);
}else {
System.out.println("No authenticated user found");
}
filterChain.doFilter(request, response);
}
// if the shouldNotFilter method return true the above JWTTokeGenerateFilter method not execute for those ture condtion
//This filter only execute only once during the login operation if we fale the below method
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return !request.getServletPath().equals("/client/login");
}
}
</code>
package com.onlineBankingOperations.config.filter;
import com.onlineBankingOperations.config.filter.constant.JWTSecurityConstant;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.security.Keys;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.filter.OncePerRequestFilter;
import javax.crypto.SecretKey;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.stream.Collectors;
public class JWTTokenGenerateFilter extends OncePerRequestFilter {
/**
* @param request
* @param response
* @param filterChain
* @throws ServletException
* @throws IOException
*/
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
System.out.println("JWTTokenGenerateFilter executed");
//first we need to load the current authentication object means current logged in user
Authentication currentAuthenticatedUser = SecurityContextHolder.getContext().getAuthentication();
//here we checking the user is present or not if yes then we have to generate the token if no then simple called the dofilter method
if(currentAuthenticatedUser != null){
SecretKey key = Keys.hmacShaKeyFor(JWTSecurityConstant.JWT_SECRET_DEFAULT_VALUE.getBytes(StandardCharsets.UTF_8));
String jwt = Jwts.builder()
.issuer("Online Bank")
.subject("JWT Token")
.claim("username", currentAuthenticatedUser.getName())
.claim("authorities", currentAuthenticatedUser.getAuthorities()
.stream().map(GrantedAuthority::getAuthority).collect(Collectors.joining(",")))
.issuedAt(new Date())
.expiration(new Date(new Date().getTime() + 30000000))
.signWith(key)
.compact();
response.setHeader(JWTSecurityConstant.JWT_HEADER, jwt);
System.out.println("JWT Token set in response header: " + jwt);
}else {
System.out.println("No authenticated user found");
}
filterChain.doFilter(request, response);
}
// if the shouldNotFilter method return true the above JWTTokeGenerateFilter method not execute for those ture condtion
//This filter only execute only once during the login operation if we fale the below method
@Override
protected boolean shouldNotFilter(HttpServletRequest request) throws ServletException {
return !request.getServletPath().equals("/client/login");
}
}
Login Method:
public Client signInClient(LoginRequest loginRequest) {
Client existingClient = clientRepo.findByEmail(loginRequest.getUsername());
System.out.print("This is client for the login: " + existingClient);
if (existingClient == null) {
throw new UserNotFoundException("User is not found with this email: " + loginRequest.getUsername());
if (!isEmailAssociated(existingClient, loginRequest.getUsername())) {
throw new BadCredentialsException("The username you have entered is invalid!");
if (!isValidPassword(existingClient, loginRequest.getPassword())) {
throw new BadCredentialsException("The password you have entered is invalid!");
<code>
@Override
public Client signInClient(LoginRequest loginRequest) {
Client existingClient = clientRepo.findByEmail(loginRequest.getUsername());
System.out.print("This is client for the login: " + existingClient);
if (existingClient == null) {
throw new UserNotFoundException("User is not found with this email: " + loginRequest.getUsername());
}
if (!isEmailAssociated(existingClient, loginRequest.getUsername())) {
throw new BadCredentialsException("The username you have entered is invalid!");
}
if (!isValidPassword(existingClient, loginRequest.getPassword())) {
throw new BadCredentialsException("The password you have entered is invalid!");
}
return existingClient;
}
</code>
@Override
public Client signInClient(LoginRequest loginRequest) {
Client existingClient = clientRepo.findByEmail(loginRequest.getUsername());
System.out.print("This is client for the login: " + existingClient);
if (existingClient == null) {
throw new UserNotFoundException("User is not found with this email: " + loginRequest.getUsername());
}
if (!isEmailAssociated(existingClient, loginRequest.getUsername())) {
throw new BadCredentialsException("The username you have entered is invalid!");
}
if (!isValidPassword(existingClient, loginRequest.getPassword())) {
throw new BadCredentialsException("The password you have entered is invalid!");
}
return existingClient;
}
Security Configuration:
<code>package com.onlineBankingOperations.config;
import com.onlineBankingOperations.config.filter.JWTTokenGenerateFilter;
import com.onlineBankingOperations.config.filter.JWTTokenValidateFilter;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import java.util.Collections;
public class SecurityConfig {
public SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{
CsrfTokenRequestAttributeHandler csrfTokenRequestAttributeHandler = new CsrfTokenRequestAttributeHandler();
.sessionManagement(sessionConfig->sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//we don't want to create session for the user after login for the request the spring security don't have idea about the previous request
.cors(corsConfig->corsConfig.configurationSource(new CorsConfigurationSource() {
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedOrigins(Collections.singletonList("*"));
cors.setAllowedMethods(Collections.singletonList("*"));
cors.setAllowCredentials(true);
cors.setAllowedHeaders(Collections.singletonList("*"));
cors.setExposedHeaders(List.of("Authorization"));
.csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new JWTTokenValidateFilter(), BasicAuthenticationFilter.class) .addFilterAfter(new JWTTokenGenerateFilter(), BasicAuthenticationFilter.class)
.authorizeHttpRequests((request)-> request
.requestMatchers("/client/addEmail",
"/client/addMobileNumber",
"/client/editMobileNumber",
"/client/deleteMobileNumber",
"/client/transfer-money").authenticated()
.requestMatchers("/client/register",
"/webjars/**").permitAll()
).formLogin(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults())
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
<code>package com.onlineBankingOperations.config;
import com.onlineBankingOperations.config.filter.JWTTokenGenerateFilter;
import com.onlineBankingOperations.config.filter.JWTTokenValidateFilter;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import java.util.Collections;
import java.util.List;
@Configuration
@EnableWebMvc
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{
CsrfTokenRequestAttributeHandler csrfTokenRequestAttributeHandler = new CsrfTokenRequestAttributeHandler();
return http
.sessionManagement(sessionConfig->sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//we don't want to create session for the user after login for the request the spring security don't have idea about the previous request
.cors(corsConfig->corsConfig.configurationSource(new CorsConfigurationSource() {
@Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedOrigins(Collections.singletonList("*"));
cors.setAllowedMethods(Collections.singletonList("*"));
cors.setAllowCredentials(true);
cors.setAllowedHeaders(Collections.singletonList("*"));
cors.setExposedHeaders(List.of("Authorization"));
cors.setMaxAge(3600L);
return cors;
}
}))
.csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new JWTTokenValidateFilter(), BasicAuthenticationFilter.class) .addFilterAfter(new JWTTokenGenerateFilter(), BasicAuthenticationFilter.class)
.authorizeHttpRequests((request)-> request
.requestMatchers("/client/addEmail",
"/client/addMobileNumber",
"/client/editMobileNumber",
"/client/editEmail",
"/client/deleteMobileNumber",
"/client/deleteEmail",
"/client/search",
"/client/transfer-money").authenticated()
.requestMatchers("/client/register",
"/client/login",
"/v2/api-docs",
"/v3/api-docs/**",
"/swagger-resources/**",
"/swagger-ui.html",
"/swagger-ui/**",
"/webjars/**").permitAll()
).formLogin(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults())
.build();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
</code>
package com.onlineBankingOperations.config;
import com.onlineBankingOperations.config.filter.JWTTokenGenerateFilter;
import com.onlineBankingOperations.config.filter.JWTTokenValidateFilter;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.Customizer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.csrf.CsrfTokenRequestAttributeHandler;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import java.util.Collections;
import java.util.List;
@Configuration
@EnableWebMvc
public class SecurityConfig {
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http)throws Exception{
CsrfTokenRequestAttributeHandler csrfTokenRequestAttributeHandler = new CsrfTokenRequestAttributeHandler();
return http
.sessionManagement(sessionConfig->sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS))//we don't want to create session for the user after login for the request the spring security don't have idea about the previous request
.cors(corsConfig->corsConfig.configurationSource(new CorsConfigurationSource() {
@Override
public CorsConfiguration getCorsConfiguration(HttpServletRequest request) {
CorsConfiguration cors = new CorsConfiguration();
cors.setAllowedOrigins(Collections.singletonList("*"));
cors.setAllowedMethods(Collections.singletonList("*"));
cors.setAllowCredentials(true);
cors.setAllowedHeaders(Collections.singletonList("*"));
cors.setExposedHeaders(List.of("Authorization"));
cors.setMaxAge(3600L);
return cors;
}
}))
.csrf(AbstractHttpConfigurer::disable)
.addFilterBefore(new JWTTokenValidateFilter(), BasicAuthenticationFilter.class) .addFilterAfter(new JWTTokenGenerateFilter(), BasicAuthenticationFilter.class)
.authorizeHttpRequests((request)-> request
.requestMatchers("/client/addEmail",
"/client/addMobileNumber",
"/client/editMobileNumber",
"/client/editEmail",
"/client/deleteMobileNumber",
"/client/deleteEmail",
"/client/search",
"/client/transfer-money").authenticated()
.requestMatchers("/client/register",
"/client/login",
"/v2/api-docs",
"/v3/api-docs/**",
"/swagger-resources/**",
"/swagger-ui.html",
"/swagger-ui/**",
"/webjars/**").permitAll()
).formLogin(Customizer.withDefaults())
.httpBasic(Customizer.withDefaults())
.build();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
I’ve tried debugging the issue, but I can’t figure out why **currentAuthenticatedUser **is null. The user seems to be authenticated correctly since the login method works and returns the correct Client object. What could be causing this issue?
Additional Details:
<code>Spring Boot Version: 3.x.x
<code>Spring Boot Version: 3.x.x
</code>
Spring Boot Version: 3.x.x
This is my Json Body :
{
“username”:”[email protected]”,
“password”:”ram123″
}