Using multiple authentication providers giving error in Spring Boot application

I have user details maintained in different internal_users and external_users DB tables. For that I am creating two different authentication providers, for various flow of authentication. Below is the code that is giving error:

@Configuration
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
public class WebSecurityConfig {
    @Autowired
    private internalUserDetailsServiceImpl internalUserDetailsService;
    @Autowired
    private externalUserDetailsServiceImpl externalUserDetailsServiceImpl;

    @Autowired
    private AuthEntryPointJwt unauthorizedHandler;
    @Autowired
    private PasswordEncoder passwordEncoder;

    private static final String[] AUTH_WHITELIST = {
      "/api/auth/**",
      "/swagger-resources/**",
      "/swagger-ui/**",
      "/v3/api-docs",
      "/v2/api-docs",
      "/webjars/**"
    };

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }

    @Bean
    public DaoAuthenticationProvider externalUserauthenticationProvider() {
        DaoAuthenticationProvider externalUserAuthProvider = new DaoAuthenticationProvider();

        externalUserAuthProvider.setUserDetailsService(externalUserDetailsServiceImpl);
        externalUserAuthProvider.setPasswordEncoder(passwordEncoder);

        return externalUserAuthProvider;
    }

    @Bean
    public DaoAuthenticationProvider internalUserAuthenticationProvider() {
        DaoAuthenticationProvider internalUserAuthProvider = new DaoAuthenticationProvider();

        internalUserAuthProvider.setUserDetailsService(internalUserDetailsServiceImpl);
        internalUserAuthProvider.setPasswordEncoder(passwordEncoder);

        return internalUserAuthProvider;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers(AUTH_WHITELIST).permitAll()
                .antMatchers("/api/test/**").permitAll()
                .anyRequest().authenticated();

        http.authenticationProvider(internalUserAuthProvider())
         .authenticationProvider(externalUserAuthProvider());

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

I am getting below issue:

Handler dispatch failed; nested exception is java.lang.StackOverflowError

On further debugging I found that the controller, where below code is used, authenticationManager is showing an error as shown in image attached

Authentication authentication = authenticationManager.authenticate(
    new UsernamePasswordAuthenticationToken(authDTO.getUserName(), authDTO.getPassword()));
SecurityContextHolder.getContext().setAuthentication(authentication);

enter image description here

On commenting out any one of the authentication providers, the code is working, but not working with both authentication providers. Below is working code with one authentication provider

@Configuration
@EnableGlobalMethodSecurity(
        // securedEnabled = true,
        // jsr250Enabled = true,
        prePostEnabled = true)
public class WebSecurityConfig {
    @Autowired
    private internalUserDetailsServiceImpl internalUserDetailsService;
    @Autowired
    private externalUserDetailsServiceImpl externalUserDetailsServiceImpl;

    @Autowired
    private AuthEntryPointJwt unauthorizedHandler;
    @Autowired
    private PasswordEncoder passwordEncoder;

    private static final String[] AUTH_WHITELIST = {
      "/api/auth/**",
      "/swagger-resources/**",
      "/swagger-ui/**",
      "/v3/api-docs",
      "/v2/api-docs",
      "/webjars/**"
    };

    @Bean
    public AuthTokenFilter authenticationJwtTokenFilter() {
        return new AuthTokenFilter();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authConfig) throws Exception {
        return authConfig.getAuthenticationManager();
    }

   /*@Bean
    public DaoAuthenticationProvider externalUserauthenticationProvider() {
        DaoAuthenticationProvider externalUserAuthProvider = new DaoAuthenticationProvider();

        externalUserAuthProvider.setUserDetailsService(externalUserDetailsServiceImpl);
        externalUserAuthProvider.setPasswordEncoder(passwordEncoder);

        return externalUserAuthProvider;
    } */

    @Bean
    public DaoAuthenticationProvider internalUserAuthenticationProvider() {
        DaoAuthenticationProvider internalUserAuthProvider = new DaoAuthenticationProvider();

        internalUserAuthProvider.setUserDetailsService(internalUserDetailsServiceImpl);
        internalUserAuthProvider.setPasswordEncoder(passwordEncoder);

        return internalUserAuthProvider;
    }

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and().csrf().disable()
                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests().antMatchers(AUTH_WHITELIST).permitAll()
                .antMatchers("/api/test/**").permitAll()
                .anyRequest().authenticated();

        http.authenticationProvider(internalUserAuthProvider());
         //.authenticationProvider(externalUserAuthProvider());

        http.addFilterBefore(authenticationJwtTokenFilter(), UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }
}

Any clue what exactly I am missing.

  • I found the solution in this thread stackoverflow.com/questions/73322338/…

    – 

  • why are you using a JWT as a session, there is no such implementation because its insecure to do so, and you just dont care and write a custom jwtfilter

    – 

Leave a Comment