There are several references of multiple authentication providers in spring security, but no example in Java config could be located.
The following link gives the XM
May be this will help you :-
@Configuration
@EnableWebSecurity
@Profile("container")
public class XSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationProvider authenticationProvider;
@Autowired
private AuthenticationProvider authenticationProviderDB;
@Override
@Order(1)
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
}
@Order(2)
protected void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProviderDB);
}
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/scripts/**","/styles/**","/images/**","/error/**");
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/rest/**").authenticated()
.antMatchers("/**").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication a) throws IOException, ServletException {
//To change body of generated methods,
response.setStatus(HttpServletResponse.SC_OK);
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(
HttpServletRequest request,
HttpServletResponse response,
AuthenticationException ae) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
}
})
.loginProcessingUrl("/access/login")
.and()
.logout()
.logoutUrl("/access/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(
HttpServletRequest request,
HttpServletResponse response,
Authentication a) throws IOException, ServletException {
response.setStatus(HttpServletResponse.SC_NO_CONTENT);
}
})
.invalidateHttpSession(true)
.and()
.exceptionHandling()
.authenticationEntryPoint(new Http403ForbiddenEntryPoint())
.and()
.csrf()//Disabled CSRF protection
.disable();
}
}
In Spring Boot this worked for me:
Each Authentication provider is tested in order. If one passes, then its following Authentication providers are skipped
auth.userDetailsService(userDetailsService)...
then:
auth.ldapAuthentication()....
@EnableRedisHttpSession
@Configuration
@EnableWebMvcSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
public void configAuthentication(AuthenticationManagerBuilder auth) throws Exception {
//each Authentication provider is tested in order
//if one passes then its following Authentication providers are skipped
//DataBase Authentication
auth.userDetailsService(userDetailsService).passwordEncoder(passwordencoder());
LdapContextSource ldapContextSource = new LdapContextSource();
ldapContextSource.setUrl("ldap://192.168.XXX.XXX:389");
ldapContextSource.setBase("dc=companyname,dc=com");
ldapContextSource.setUserDn("cn=user,cn=testgroup,ou=Test,dc=companyname,dc=com");
ldapContextSource.setPassword("user1234");
ldapContextSource.afterPropertiesSet();
//LDAP Authentication
auth.ldapAuthentication()
//The {0} in the (uid={0}) will be replaced by the username entered in the form.
.userSearchBase("ou=Group")
.userSearchFilter("uid={0}")
//.userDnPatterns("uid={0},ou=people")//does the same thing
//Specifies where the search for Roles start
//.groupSearchBase("ou=mathematicians")
//in groups we search for member
//.groupSearchFilter("member={0}")
//.contextSource().ldif("classpath:test-server.ldif");
.contextSource(ldapContextSource);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/hello").access("hasRole('ROLE_ADMIN')")
.antMatchers("/index").fullyAuthenticated()
.antMatchers("/").fullyAuthenticated()
.antMatchers("/home").fullyAuthenticated()
.anyRequest().permitAll()
.and()
.formLogin()
.loginPage("/login")
.permitAll()
.usernameParameter("username").passwordParameter("password")
.and()
.logout()
.logoutSuccessUrl("/login?logout")
.permitAll()
.and()
.exceptionHandling()
.accessDeniedPage("/403")
.and()
.csrf()
.disable();
}
@Bean(name = "passwordEncoder")
public PasswordEncoder passwordencoder() {
return new BCryptPasswordEncoder();
}
}
This is a successful configuration which helps configure multiple authentication providers in java config. Thanks a lot ojus for your inputs. It did help in nailing down the issue. The key is to have
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
auth.authenticationProvider(authenticationProviderDB);
}
Full code below
@Configuration
@EnableWebSecurity
public class XSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private LDAPAuthenticationProvider authenticationProvider;
@Autowired
private DBAuthenticationProvider authenticationProviderDB;
@Override
public void configure(WebSecurity web) throws Exception {
web
.ignoring()
.antMatchers("/scripts/**","/styles/**","/images/**","/error/**");
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(authenticationProvider);
auth.authenticationProvider(authenticationProviderDB);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/","/logout").permitAll()
.antMatchers("/admin").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/index")
.loginProcessingUrl("/perform_login")
.usernameParameter("user")
.passwordParameter("password")
.failureUrl("/index?failed=true")
.defaultSuccessUrl("/test",true)
.permitAll()
.and()
.logout().logoutUrl("/logout")
.logoutSuccessUrl("/index?logout=true").permitAll()
.and()
.exceptionHandling().accessDeniedPage("/error");
}
}