StackOverflowError in Spring Boot Application during Authentication

I am currently developing a Spring Boot application with JWT authentication. However, I am encountering a java.lang.StackOverflowError during the authentication process and I’m not sure what’s causing it. Done lots of research to fix it but no use.

  • Using Spring boot version of : 3.1.3
  • My Spring Security version : 6.1.x

And I am thinking that there might be possibility of circular dependency throughout my classes :
let me explain brief,

In my application, I have defined several beans in a dedicated configuration class called BeanConfig, which includes beans like JwtUtilService, UserDetailsServiceImpl, JwtRequestFilter, and others. These beans are used for authentication and security purposes.

However, it seems that there is a circular reference among these beans, particularly involving the JwtRequestFilter, which depends on JwtUtilService, UserDetailsService, and BCryptPasswordEncoder, while UserDetailsService itself relies on some of these beans.

As a result, when the Spring application context tries to create these beans, it enters into an infinite loop, ultimately leading to a StackOverflowError. (This is just a guess but failed to find where this error occurred).

I am providing many classes from my project for better under standing and let me know when you need more inputs from me.

Pom.xml (only dependencies)

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
    </dependency>
    <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
    <version>3.18.0-GA</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-core</artifactId>
</dependency>

<!--  STARTER SECURITY !-->

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

<dependency>
    <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-core</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/io.springfox/springfox-boot-starter -->
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-boot-starter</artifactId>
    <version>3.0.0</version>
</dependency>
<dependency>
      <groupId>org.springdoc</groupId>
      <artifactId>springdoc-openapi-starter-webmvc-ui</artifactId>
      <version>2.2.0</version>
   </dependency>
<!-- https://mvnrepository.com/artifact/io.swagger.core.v3/swagger-core -->
<dependency>
    <groupId>io.swagger.core.v3</groupId>
    <artifactId>swagger-core</artifactId>
    <version>2.2.0</version>
</dependency>

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-api -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-api</artifactId>
    <version>0.11.5</version>
</dependency>

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-impl -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-impl</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt-jackson -->
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt-jackson</artifactId>
    <version>0.11.5</version>
    <scope>runtime</scope>
</dependency>

 <dependency>
        <groupId>org.apache.tomcat.embed</groupId>
        <artifactId>tomcat-embed-jasper</artifactId>
        <scope>provided</scope>
    </dependency>
    <dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.2.3</version>
</dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>   

BeanConfig.java

Configuration
public class BeanConfig {
    
    private UserRepo repo;

    @Bean
    public JwtUtilService jwtUtilService() {
        return new JwtUtilService();
    }

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

    @Bean
    public UserDetailsService userDetailsService() {
        return new UserDetailsServiceImpl(repo);
    }

    @Bean
    public JwtRequestFilter jwtRequestFilter() {
        return new JwtRequestFilter();
    }
    
    @Bean
    AuthenticationManager authenticationManager(AuthenticationConfiguration
        authenticationConfiguration) throws Exception {
      return authenticationConfiguration.getAuthenticationManager();
    }
    
    @Bean BCryptPasswordEncoder passEncoder() {
        return new BCryptPasswordEncoder();
    }

}

WebSecurityConfig.java

@Configuration
public class WebSecurityConfig {
    
    
  @Autowired 
  private JwtRequestFilter jwtRequestFilter;
  
  
    @Bean
    SecurityFilterChain web(HttpSecurity http) throws Exception {
      http
          .csrf().disable()
          .authorizeHttpRequests((authorize) -> authorize
              .requestMatchers(new AntPathRequestMatcher("/auth", "POST")).permitAll()
              .requestMatchers(new AntPathRequestMatcher("/attendancedetail/**","GET")).hasRole("USER")
              .anyRequest().authenticated()
          )
          .cors(withDefaults())
          .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class)
          .sessionManagement((session) -> session
              .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
          );
      ;
      
      return http.build();
    }
}

JwtUtilService.java

@Service
public class JwtUtilService {
    
    
  // [Base64] => (256bit secret key)
  private static final String JWT_SECRET_KEY = "my Key";

  public static final long JWT_TOKEN_VALIDITY = 1000 * 60 * 60 * (long) 8; // 8 Hours

  public String extractUsername(String token) {
    return extractClaim(token, Claims::getSubject);
  }

  public Date extractExpiration(String token) {
    return extractClaim(token, Claims::getExpiration);
  }

  public <T> T extractClaim(String token, Function<Claims, T> claimsResolver) {
    return claimsResolver.apply(extractAllClaims(token));
  }

  private Claims extractAllClaims(String token) {
      return Jwts
                .parserBuilder()
                .setSigningKey(getSignInKey())
                .build()
                .parseClaimsJws(token)
                .getBody();
  }

  private Boolean isTokenExpired(String token) {
    return extractExpiration(token).before(new Date());
  }

  public String generateToken(UserDetails userDetails) {
    Map<String, Object> claims = new HashMap<>();
    var rol = userDetails.getAuthorities().stream().collect(Collectors.toList()).get(0);
    claims.put("rol", rol);
    return createToken(claims, userDetails.getUsername());
  }

  private String createToken(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))
        .signWith(SignatureAlgorithm.HS256, JWT_SECRET_KEY)
        .compact();
  }
  
  private Key getSignInKey() {
        byte[] keyBytes = Decoders.BASE64.decode(JWT_SECRET_KEY);
        return Keys.hmacShaKeyFor(keyBytes);
      }

  public boolean validateToken(String token, UserDetails userDetails) {
    final String username = extractUsername(token);
    return (username.equals(userDetails.getUsername()) && !isTokenExpired(token));
  }
}

JwtRequestFilter.java

@Component
public class JwtRequestFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtUtilService jwtUtilService;

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

        final String authorizationHeader = request.getHeader("Authorization");

        String username = null;
        String jwt = null;

        if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) {
            jwt = authorizationHeader.substring(7);
            username = jwtUtilService.extractUsername(jwt);
        }


        if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {

            UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);

            if (jwtUtilService.validateToken(jwt, userDetails)) {

                UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
                        userDetails, null, userDetails.getAuthorities());
                authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
        chain.doFilter(request, response);
    }

}

UserServiceImpl.java

@Service
public class UserDetailsServiceImpl implements UserDetailsService {

    private final UserRepo userRepository;

    @Autowired
    public UserDetailsServiceImpl(UserRepo userRepository) {
        this.userRepository = userRepository;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Optional<User> userOptional = userRepository.findByEmail(username);

        if (userOptional.isEmpty()) {
            throw new UsernameNotFoundException("User not found with email: " + username);
        }

        User user = userOptional.get();

        // Create a UserDetails object using the retrieved user data
        return org.springframework.security.core.userdetails.User
            .withUsername(user.getEmail())
            .password(user.getPassword())
            .roles("ROLE_"+user.getRole()) // You can set roles here
            .accountExpired(false)
            .accountLocked(false)
            .credentialsExpired(false)
            .disabled(false)
            .build();
    }
}

AuthController.java

@RestController
public class AuthController {

    private Stack<String> callStack = new Stack<>();

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtUtilService jwtUtilService;

    @PostMapping("/auth")
    public ResponseEntity<TokenInfo> authenticate(@RequestBody AuthenticationReq authenticationReq) {
        callStack.push("authenticate()");

        //logger.info("Autenticando al usuario {}", authenticationReq.getUsuario());

        authenticationManager.authenticate(
            new UsernamePasswordAuthenticationToken(authenticationReq.getUsername(),
                authenticationReq.getPassword()));

        final UserDetails userDetails = userDetailsService.loadUserByUsername(
            authenticationReq.getUsername());

        final String jwt = jwtUtilService.generateToken(userDetails);

        callStack.pop();

        // Print the call stack to the console.
        System.out.println("Call stack:");
        for (String method : callStack) {
            System.out.println(method);
        }

        return ResponseEntity.ok(new TokenInfo(jwt));
    }

    public Stack<String> getCallStack() {
        return callStack;
    }
}

AttendanceController.java

@Tag(name = "Attencdance APIs", description = "This Attendance APIs are resposible for Managing Employees Attendance.")
@RestController
@RequestMapping(path="/attendancedetail")
public class AttendanceController {

    @Autowired
    AttendanceService attendanceservice;

    @PostMapping(path = "/addAttendance")
    @ResponseBody
    public ResponseEntity<?> addAttendanceDetails(@RequestBody AttendanceDetail attendancedetail) {
        HttpHeaders headers = new HttpHeaders();
        try {
            return ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.addUser(attendancedetail));
        } catch (Exception e) {
            headers.add("Message", "false");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body("Failed to add Attendance");
        }

    }

    @GetMapping(path = "/findAllatten")
    @ResponseBody
    public ResponseEntity<?> findAllAttendance() {
        HttpHeaders headers = new HttpHeaders();
        try {
            return ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.findAllUser());
        } catch (ResourceNotFoundException ex) {
            throw new ResourceNotFoundException("employee Attendance not found");
        }

    }

    @GetMapping(path = "/findbyempidatten")
    @ResponseBody
    public List<ResponseEntity<?>> findByempid(@RequestParam int employeeId) {
        HttpHeaders headers = new HttpHeaders();

        try {
            return Collections.singletonList(ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.findByempid(employeeId)));
        } catch (ResourceNotFoundException ex) {
            throw new ResourceNotFoundException("Required Employee attendance not found");
        }

    }

    @GetMapping(path = "/findbyDandm")
//  @CrossOrigin
    @ResponseBody
    public ResponseEntity<?> countByDepartmentIdAndMonth(@RequestParam int departmentid, @RequestParam String month) {
        HttpHeaders headers = new HttpHeaders();

        try {
            return ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.countByDepartmentIdAndMonth(departmentid, month));
        } catch (Exception e) {
            headers.add("Message", "false");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body("Required Employee attendance not found");
        }
    }

    @GetMapping(path = "/findbyEandDandm")
//  @CrossOrigin
    @ResponseBody
    public ResponseEntity<?> countByEmployeeIdAndDepartmentIdAndMonth(@RequestParam int employeeid, @RequestParam int departmentid, @RequestParam String month) {
        HttpHeaders headers = new HttpHeaders();

        try {
            return ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.countByEmployeeIdAndDepartmentIdAndMonth(employeeid, departmentid, month));
        } catch (Exception e) {
            headers.add("Message", "false");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body("Required Employee attendance not found");
        }
    }

    @GetMapping(path = "/findbyEandDandD")
//  @CrossOrigin
    @ResponseBody
    public ResponseEntity<?> countByEmployeeIdAndDepartmentIdAndDate(@RequestParam int employeeid, @RequestParam int departmentid, @RequestParam String date) {
        HttpHeaders headers = new HttpHeaders();

        try {
            return ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.countByEmployeeIdAndDepartmentIdAndDate(employeeid, departmentid, date));
        } catch (Exception e) {
            headers.add("Message", "false");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body("Required Employee attendance not found");
        }
    }

    @GetMapping(path = "/findbyEandD")
//  @CrossOrigin
    @ResponseBody
    public ResponseEntity<?> countByEmployeeIdAndDepartmentId(@RequestParam int employeeid, @RequestParam int departmentid) {
        HttpHeaders headers = new HttpHeaders();

        try {
            return ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.countByEmployeeIdAndDepartmentId(employeeid, departmentid));
        } catch (Exception e) {
            headers.add("Message", "false");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body("Required Employee attendance not found");
        }
    }

    @GetMapping(path = "/findbyEandDandA")
//  @CrossOrigin
    @ResponseBody
    public ResponseEntity<?> countByEmployeeIdAndDepartmentIdAndAvailable(@RequestParam int employeeid, @RequestParam int departmentid, @RequestParam Boolean available) {
        HttpHeaders headers = new HttpHeaders();
        try {
            return ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.countByEmployeeIdAndDepartmentIdAndAvailable(employeeid, departmentid, available));
        } catch (Exception e) {
            headers.add("Message", "false");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body("Required Employee attendance not found");
        }


    }
    @GetMapping(path = "/findbydepidatten")
//  @CrossOrigin
    @ResponseBody
    public ResponseEntity<?> findBydeptid(@RequestParam int departmentId) {
        HttpHeaders headers = new HttpHeaders();

        try {
            //System.out.println("en da ipdi "+employeeid+employeeservice.findByempid(employeeid));
            return ResponseEntity.status(HttpStatus.OK).headers(headers).body(attendanceservice.findBydeptid(departmentId));
        }catch (Exception e) {
            headers.add("Message", "false");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body("Required Employee attendance not found");
        }


    }

    @GetMapping(path = "/findbydate")
//  @CrossOrigin
    @ResponseBody
    public ResponseEntity<?> findBydate(@RequestParam String date) {
        HttpHeaders headers = new HttpHeaders();

        try {
            //System.out.println("en da ipdi "+employeeid+employeeservice.findByempid(employeeid));
            return ResponseEntity.status(HttpStatus.CREATED).headers(headers).body(attendanceservice.findBydate(date));
        }catch (Exception e) {
            headers.add("Message", "false");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).headers(headers).body("Required Employee attendance not found");
        }

    }


Error console :

2023-09-15T15:37:34.319+05:30 ERROR 6456 --- [nio-8080-exec-2] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed: java.lang.StackOverflowError] with root cause

java.lang.StackOverflowError: null
    at java.base/java.lang.Exception.<init>(Exception.java:103) ~[na:na]
    at java.base/java.lang.ReflectiveOperationException.<init>(ReflectiveOperationException.java:90) ~[na:na]
    at java.base/java.lang.reflect.InvocationTargetException.<init>(InvocationTargetException.java:67) ~[na:na]
    at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.11.jar:6.0.11]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:237) ~[spring-aop-6.0.11.jar:6.0.11]
    at jdk.proxy2/jdk.proxy2.$Proxy132.authenticate(Unknown Source) ~[na:na]
    at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.11.jar:6.0.11]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:237) ~[spring-aop-6.0.11.jar:6.0.11]
    at jdk.proxy2/jdk.proxy2.$Proxy132.authenticate(Unknown Source) ~[na:na]
    at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.11.jar:6.0.11]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:237) ~[spring-aop-6.0.11.jar:6.0.11]
    at jdk.proxy2/jdk.proxy2.$Proxy132.authenticate(Unknown Source) ~[na:na]
    at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.11.jar:6.0.11]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:237) ~[spring-aop-6.0.11.jar:6.0.11]
    at jdk.proxy2/jdk.proxy2.$Proxy132.authenticate(Unknown Source) ~[na:na]
    at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-**6.0.11.jar:6.0.11]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:237) ~[spring-aop-6.0.11.jar:6.0.11]
    at jdk.proxy2/jdk.proxy2.$Proxy132.authenticate(Unknown Source) ~[na:na]
    at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-6.0.11.jar:6.0.11]
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:237) ~[spring-aop-6.0.11.jar:6.0.11]
    at jdk.proxy2/jdk.proxy2.$Proxy132.authenticate(Unknown Source) ~[na:na]
    at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:343) ~[spring-aop-
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:237) ~[spring-aop-6.0.11.jar:6.0.11]
    at jdk.proxy2/jdk.proxy2.$Proxy132.authenticate(Unknown Source) ~[na:na]
    at jdk.internal.reflect.GeneratedMethodAccessor35.invoke(Unknown Source) ~[na:na]**

   ***This is repeated many times in console***

I am Expecting an simple authentication where I get data from Data Base. Here in my case Password Encoded using BcryptPasswordEncoder class.
but throwed error after sending request in postman with headers of username and password throwed 403 but expected 200.

  • 1

    we need more of the logs, you have provided no context, we need what happens before, FULL debug logs, not your intepretation of the logs. Also im going to point out, handing out JWTs to browsers is called an implcit flow and is deprecated by oauth2 and comes with risks. Thats why there is no such implementation in spring security, because it is insecure. I suggest that you dont use this code, because this is not how you build a secure login. JWTs are used to authenticate between microservices, not with browsers.

    – 




  • @Toerktumlare Thanks for your reply and valuable suggestion so I won’t implement JWT in my project instead can you suggest another way to approach Authentication in springboot 3.1.x ?? I can consider 3.1.x below too. If possible, provide some source 🙂

    – 

  • i would suggest you read the official spring security documentation on their webpage and try to implement form login. Read this to understand all the components of spring security docs.spring.io/spring-security/reference/servlet/authentication/… then read this docs.spring.io/spring-security/reference/servlet/authentication/…

    – 

Leave a Comment