1

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

HNP
  • 35
  • 1
  • 7
  • 1
    Does this answer your question? [How to configure ldap in spring-security 5.7 while retaining basic form login](https://stackoverflow.com/questions/72534536/how-to-configure-ldap-in-spring-security-5-7-while-retaining-basic-form-login) – Eleftheria Stein-Kousathana Aug 11 '22 at 14:29
  • No, it doesn't. I'm using same way(register two provider) but just one of them is working. @EleftheriaStein-Kousathana – HNP Aug 11 '22 at 15:48
  • 1
    why are you not using the built in jwt filter that comes with spring security? – Toerktumlare Aug 11 '22 at 21:11
  • 1
    @HNP Are you sure, that you are using the right `AuthenticationManager`? There is a global one and probably a local one. See: https://stackoverflow.com/questions/71281032/spring-security-exposing-authenticationmanager-without-websecurityconfigureradap – dur Aug 11 '22 at 21:32
  • it sends AuthenticationManager in addFilter method. There is no way to access correct AuthenticatonManager in Controller? @dur – HNP Aug 12 '22 at 04:20
  • can you give me documentation about that? @Toerktumlare – HNP Aug 12 '22 at 04:22
  • 1
    Its in the docs on spring securitys webpage under docs – Toerktumlare Aug 12 '22 at 06:50

2 Answers2

2

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();
}
Brice Roncace
  • 10,110
  • 9
  • 60
  • 69
  • it doesnt work with oauth2login https://stackoverflow.com/questions/73766385/spring-security-5-how-to-implement-custom-daoauthenticationprovider-for-form-l – Feroz Siddiqui Sep 18 '22 at 21:55
1

@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())
        ...
Sunil
  • 11
  • 1