Spring Security: Global AuthenticationManager without the WebSecurityConfigurerAdapter

Viewed 4621

Im trying to get rid of WebSecurityConfigurerAdapter. The AuthenticationManager is configured like the following:

@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true)
public static class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {

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

  @Override
  protected void configure(AuthenticationManagerBuilder auth) 
  throws Exception {
            auth.userDetailsService(userDetailsService())
                    .passwordEncoder(passwordEncoder());
        }

Now without the WebSecurityConfigurerAdapter i define the global AuthenticationManager like this:

    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled = true)
    public static class DefaultSecurityConfig  {

        @Bean
        public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth ) throws Exception {
            return auth.userDetailsService(userDetailsService())
                    .passwordEncoder(passwordEncoder()).and().build();
        }

And i get the error:

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through method 'setFilterChains' parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'defaultSecurityFilterChain' defined in class path resource [org/springframework/boot/autoconfigure/security/servlet/SpringBootWebSecurityConfiguration.class]: Unsatisfied dependency expressed through method 'defaultSecurityFilterChain' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception; nested exception is java.lang.IllegalStateException: Cannot apply org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration$EnableGlobalAuthenticationAutowiredConfigurer@536a79bd to already built object

Im using Spring Boot v2.6.4

I'm stuck here for a while i would appreciate any help

3 Answers

Replace

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationManagerBuilder auth ) throws Exception {
       return auth.userDetailsService(userDetailsService())
                  .passwordEncoder(passwordEncoder()).and().build();
    }

by

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

In my project, I needed to use the AuthenticationManager in the Controller, to make a custom login. Then I declare:

@RestController
@RequestMapping("/api/login")
@Slf4j
@RequiredArgsConstructor
public class LoginResource {

    private final AuthenticationManager authenticationManager;

    ....
}

In SecurityConfig:

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig  {

    private final JwtAuthenticationEntryPoint jwtAuthenticationEntryPoint;

    private final JwtRequestFilter jwtRequestFilter;

    private final UserDetailsService jwtUserDetailsService;

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.csrf().disable()
                .authorizeRequests()
                .antMatchers(HttpMethod.POST, "/api/login").permitAll()
                .anyRequest().authenticated()
                .and()
                .exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint).and().sessionManagement()
                .sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        // Add a filter to validate the tokens with every request
        http.addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);
        return http.build();
    }

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

    @Bean
    public AuthenticationManager authenticationManagerBean(HttpSecurity http) throws Exception {
        AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
        authenticationManagerBuilder.userDetailsService(jwtUserDetailsService).passwordEncoder(passwordEncoder());
        return authenticationManagerBuilder.build();
    }
}

Then Works fine to me!!

Replace your code with this section below.

Hope it works, working fine in my code

       @Bean
       public AuthenticationManager authenticationManagerBean(HttpSecurity http) throws Exception {
            AuthenticationManagerBuilder authenticationManagerBuilder = http.getSharedObject(AuthenticationManagerBuilder.class);
            authenticationManagerBuilder
                  .userDetailsService(jwtUserDetailsService)
                  .passwordEncoder(passwordEncoder());
            return authenticationManagerBuilder.build();
        }
Related