Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

spring security 5.7 - multiple authentication provider without WebSecurityConfigurerAdapter

I'm using spring security 5.7 and WebSecurityConfigurerAdapter is deprecated. I want use multiple Authentication Provider(Ldap and Dao) but ldap provider not working and spring security just call DaoAuthenticationProvider.

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfiguration {

@Autowired
private JWTTokenFilter jwtTokenFilter;

@Autowired
private LdapAuthProvider ldapAuthProvider;

@Autowired
private UserService userService;

@Bean
public DaoAuthenticationProvider authenticationProvider() {
    DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
    authProvider.setUserDetailsService(userService);
    authProvider.setPasswordEncoder(passwordEncoder());
    return authProvider;
}

@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    http
            .cors()
            .and().csrf().disable()
            .headers().frameOptions().disable()
            .and().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and().authorizeRequests().antMatchers("/api/test/**", "/auth/**", "/h2-console/**").permitAll()
            .and().authorizeRequests().anyRequest().authenticated()
            .and().addFilterBefore(jwtTokenFilter, UsernamePasswordAuthenticationFilter.class);
    http.authenticationProvider(ldapAuthProvider);
    http.authenticationProvider(authenticationProvider());
    return http.build();
}

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

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

@Bean
public CorsFilter corsFilter() {
    UrlBasedCorsConfigurationSource source =
            new UrlBasedCorsConfigurationSource();
    CorsConfiguration config = new CorsConfiguration();
    config.setAllowCredentials(true);
    config.addAllowedOrigin("*");
    config.addAllowedHeader("*");
    config.addAllowedMethod("*");
    source.registerCorsConfiguration("/**", config);
    return new CorsFilter(source);
}

}

when remove DaoAuthenticationProvider then LdapAuthProvider is work. what's the problem?

edit: i want use exposed AuthenticationManager in whole app like this:

@Autowired
private AuthenticationManager authenticationManager;

@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody AuthRequest authRequest) {


    if(authRequest.getUsername() == null || authRequest.getPassword() == null) {
        return ResponseEntity.badRequest().build();
    }


    Authentication authenticate = null;
    try {
        authenticate = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(
                authRequest.getUsername(),
                authRequest.getPassword()));
    } catch (Exception e) {

        e.printStackTrace();
        return ResponseEntity.status(401).build();
    }

but this AuthenticationManager not contain my custom AuthenticationProvider

like image 438
HNP Avatar asked Sep 07 '25 00:09

HNP


2 Answers

Below is an example of using two authentication providers (Ldap and Dao) in Spring Security 5.7. This is in the context of a traditional web application using form login. The trick was to explicitly set the AuthenticationManager to use (i.e. ProviderManager) in the filter chain and reference both authentication providers:

@Bean
public ActiveDirectoryLdapAuthenticationProvider getAdAuthProvider(CustomLdapUserDetailsMapper customLdapUserDetailsMapper) {
  ActiveDirectoryLdapAuthenticationProvider authProvider = new ActiveDirectoryLdapAuthenticationProvider(domain, urls);
  authProvider.setSearchFilter("(&(objectClass=user)(sAMAccountName={1}))");
  authProvider.setUserDetailsContextMapper(customLdapUserDetailsMapper);
  return authProvider;
}

@Bean
public DaoAuthenticationProvider getDaoAuthProvider(CustomDatabaseUserDetailsService customDatabaseUserDetailsService) {
  DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
  provider.setUserDetailsService(customDatabaseUserDetailsService);
  provider.setPasswordEncoder(new BCryptPasswordEncoder());
  return provider;
}

@Bean
public SecurityFilterChain filterChain(HttpSecurity http, ActiveDirectoryLdapAuthenticationProvider adAuthProvider, DaoAuthenticationProvider dbAuthProvider) throws Exception {
  http.authorizeRequests()
    .antMatchers("/").permitAll()
    ...
    .anyRequest().hasAuthority("ADMIN")
    .and().formLogin().loginPage("/login").permitAll()
    .and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout")).permitAll()
    .and().authenticationManager(new ProviderManager(List.of(adAuthProvider, dbAuthProvider)));

  return http.build();
}
like image 90
Brice Roncace Avatar answered Sep 11 '25 13:09

Brice Roncace


@Brice Roncace's answer above worked for me too. Just to add on to that, since you want the AuthenticationManager exposed as a bean, this is what I did:

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return new ProviderManager(List.of(authenticationProvider1(), authenticationProvider2()));
    }

and then wire this bean into the config:

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
        .authenticationManager(authenticationManager())
        ...
like image 29
Sunil Avatar answered Sep 11 '25 13:09

Sunil