Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom Authentication Provider Not Being Called

Tags:

I'm trying to setup a customer AuthenticationProvider with Spring Security but not having much luck getting it working. I'm using Java configuration so I'm probably missing something simple but as most the learning material is XML config based, it's not jumping out at me.

This is using Spring v4.0.1.RELEASE but with Spring Security v3.2.2.RELEASE. Version number clash perhaps?

As far as I could tell, all I had to do was create my provider:

public class KBServicesAuthProvider implements AuthenticationProvider {   @Autowired   private ApplicationConfig applicationConfig;    @Autowired   private SessionServiceClient sessionServiceClient;    @Override   public Authentication authenticate(Authentication authentication) throws AuthenticationException {     String email = (String) authentication.getPrincipal();     String password = (String) authentication.getCredentials();      try {       KBSessionInfo sessionInfo = sessionServiceClient.login(applicationConfig.getKbServicesPresenceId(), email,           password);        List<GrantedAuthority> grantedRoles = new ArrayList<>();       for (KBRoleMembership role : sessionInfo.getAuthenticatedUser().getRoleMemberships()) {         grantedRoles.add(new SimpleGrantedAuthority(role.getRoleId()));       }        return new UsernamePasswordAuthenticationToken(email, password, grantedRoles);     } catch (InvalidSessionException e) {       throw new AuthenticationCredentialsNotFoundException("Username or password was not accepted", e);     }   }    @Override   public boolean supports(Class<?> authentication) {     return authentication.equals(UsernamePasswordAuthenticationToken.class);   } } 

And then setup a class to describe my security setup. This class links in my provider:

@Configuration @EnableWebMvcSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {    @Autowired(required = true)   SessionServiceClient sessionServiceClient;    @Override   protected void configure(HttpSecurity http) throws Exception {     http.authorizeRequests().antMatchers("/").permitAll().anyRequest().authenticated();     http.formLogin().loginPage("/login").permitAll().and().logout().permitAll();   }    @Override   protected void configure(AuthenticationManagerBuilder auth) throws Exception {     auth.authenticationProvider(getKBServicesAuthenticationProvider());   }    @Bean   protected AuthenticationProvider getKBServicesAuthenticationProvider() {     return new KBServicesAuthProvider();   } } 

But I'm not seeing anything in the logs & none of my debug points are being hit. The app acts as it's unsecured (so I can reach various URLs etc. still).

Any ideas on what I should be checking?

like image 591
Lee Theobald Avatar asked Mar 17 '14 11:03

Lee Theobald


People also ask

How do Authentication providers work?

Authentication is the mechanism by which callers prove that they are acting on behalf of specific users or systems. Authentication answers the question, "Who are you?" using credentials such as username/password combinations.

What is difference between Authentication Manager and Authentication Provider?

Authentication Provider calls User Details service loads the User Details and returns the Authenticated Principal. Authentication Manager returns the Authenticated Object to Authentication Filter and Authentication Filter sets the Authentication object in Security Context .

When do I need to define a custom authentication provider?

For example, when authenticating against some external, third party service (such as Crowd) – both the username and the password from the authentication request will be necessary. For these, more advanced scenarios, we'll need to define a custom Authentication Provider:

What is the authentication provider in Salesforce?

The Authentication Provider. The standard and most common implementation is the DaoAuthenticationProvider – which retrieves the user details from a simple, read-only user DAO – the UserDetailsService. This User Details Service only has access to the username in order to retrieve the full user entity – and in a large number of scenarios,...

How do you authenticate a user in spring?

As shown in the spring security architecture diagram, the AuthenticationProvider is the one responsible for the logic of authentication. The AuthenticationManager receives a request from the HTTP filter layer and delegates the responsibility to authenticate the user to the AuthenticationProvider.

What is default authentication flow in Spring Boot?

Default Authentication Flow As shown in the spring security architecture diagram, the AuthenticationProvider is the one responsible for the logic of authentication. The AuthenticationManager receives a request from the HTTP filter layer and delegates the responsibility to authenticate the user to the AuthenticationProvider.


2 Answers

This might not be the complete answer, as I'm struggling with this a bit myself. I'm using a custom authentication provider and a custom user details service. I see the same behavior as you -- breakpoints get hit in my user details service, but not in my authentication provider. Here is what my entire config class looks like:

@Configuration @EnableWebMvcSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter {      @Autowired     private CustomUserDetailsService userDetailsService;     @Autowired     private CustomAuthenticationProvider customAuthenticationProvider;      @Autowired     public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {         auth.userDetailsService(userDetailsService);     }      @Override     protected void configure(HttpSecurity http) throws Exception {         AuthenticationProvider rememberMeAuthenticationProvider = rememberMeAuthenticationProvider();         TokenBasedRememberMeServices tokenBasedRememberMeServices = tokenBasedRememberMeServices();          List<AuthenticationProvider> authenticationProviders = new ArrayList<AuthenticationProvider>(2);         authenticationProviders.add(rememberMeAuthenticationProvider);         authenticationProviders.add(customAuthenticationProvider);         AuthenticationManager authenticationManager = authenticationManager(authenticationProviders);          http                 .csrf().disable()                 .headers().disable()                 .addFilter(new RememberMeAuthenticationFilter(authenticationManager, tokenBasedRememberMeServices))                 .rememberMe().rememberMeServices(tokenBasedRememberMeServices)                 .and()                 .authorizeRequests()                 .antMatchers("/js/**", "/css/**", "/img/**", "/login", "/processLogin").permitAll()                 .antMatchers("/index.jsp", "/index.html", "/index").hasRole("USER")                 .antMatchers("/admin", "/admin.html", "/admin.jsp", "/js/saic/jswe/admin/**").hasRole("ADMIN")                 .and()                 .formLogin().loginProcessingUrl("/processLogin").loginPage("/login").usernameParameter("username").passwordParameter("password").permitAll()                 .and()                 .exceptionHandling().accessDeniedPage("/login")                 .and()                 .logout().permitAll();     }      @Override     public void configure(WebSecurity web) throws Exception {         web.ignoring().antMatchers("/js/**", "/css/**", "/img/**");     }      @Bean     public BCryptPasswordEncoder bCryptPasswordEncoder(){         return new BCryptPasswordEncoder();     }      @Bean     public AuthenticationManager authenticationManager(List<AuthenticationProvider> authenticationProviders) {         return new ProviderManager(authenticationProviders);     }      @Bean     public TokenBasedRememberMeServices tokenBasedRememberMeServices() {         return new TokenBasedRememberMeServices("testKey", userDetailsService);     }      @Bean     public AuthenticationProvider rememberMeAuthenticationProvider() {         return new org.springframework.security.authentication.RememberMeAuthenticationProvider("testKey");     }      protected void registerAuthentication(AuthenticationManagerBuilder auth) throws Exception {         auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());     } } 

I've just discovered that if I specifically add my authentication provider to the HttpSecurity object, my breakpoints start getting hit:

http                 .csrf().disable()                 .headers().disable()                 .authenticationProvider(customAuthenticationProvider) 

My goal is to get a BCryptPasswordEncoder working, which does not with this config -- everything returns as bad credentials. Anyway, just thought I'd share.

like image 71
Bal Avatar answered Sep 21 '22 15:09

Bal


Use isAssignableFrom() instead of == or equals.

The problem is with the supports() method which will always return false.

Change from:

@Override public boolean supports(Class<?> authentication) {       return authentication.equals(UsernamePasswordAuthenticationToken.class); } 

To:

Java

@Override public boolean supports(Class<?> authentication) {     return (UsernamePasswordAuthenticationToken.class.isAssignableFrom(authentication)); } 

Kotlin

override fun supports(authentication: Class<*>): Boolean {     return UsernamePasswordAuthenticationToken::class.java.isAssignableFrom(authentication) } 

Finally the flow would pass through authenticate()

like image 24
Mohit Sharma Avatar answered Sep 23 '22 15:09

Mohit Sharma