Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Security java.lang.StackOverflowError exception after all providers

Environment:

  • Spring 4.1.6
  • Spring Security 4.0.1

I have 2 authentication providers - one that hits ActiveDirectory, and then one that hits a custom database provider I've created. Logging in as a user that is in either of those environments works perfectly. The user is authenticated and the app continues.

However, when an invalid user is entered and neither provider is able to authenticate, I get this exception on the page:

java.lang.StackOverflowError
    org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$UserDetailsServiceDelegator.loadUserByUsername(WebSecurityConfigurerAdapter.java:393)
    org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$UserDetailsServiceDelegator.loadUserByUsername(WebSecurityConfigurerAdapter.java:394)
    org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$UserDetailsServiceDelegator.loadUserByUsername(WebSecurityConfigurerAdapter.java:394)
    org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$UserDetailsServiceDelegator.loadUserByUsername(WebSecurityConfigurerAdapter.java:394)

Here is my WebSecurityConfigurerAdapter configuration:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
            .csrf().disable()
            .formLogin().loginPage("/login").failureUrl("/login?error").defaultSuccessUrl("/overview").permitAll()
            .and()
                .logout().logoutSuccessUrl("/login?logout").permitAll()
            .and()
                .authorizeRequests()
                .antMatchers("/resources/**").permitAll()
                .antMatchers("/favicon.ico").permitAll()
                .antMatchers("/**").hasRole("AUTH");
}

@Override
protected void configure(AuthenticationManagerBuilder authManagerBuilder) throws Exception {
    authManagerBuilder
            .authenticationProvider(activeDirectoryLdapAuthenticationProvider())
            .userDetailsService(userDetailsService());

    authManagerBuilder
            .authenticationProvider(databaseAuthenticationProvider())
            .userDetailsService(userDetailsService());
}

@Bean
public ActiveDirectoryLdapAuthenticationProvider activeDirectoryLdapAuthenticationProvider() {
    ActiveDirectoryLdapAuthenticationProvider provider = new ActiveDirectoryLdapAuthenticationProvider(DOMAIN, URL);
    provider.setConvertSubErrorCodesToExceptions(true);
    provider.setUseAuthenticationRequestCredentials(true);
    provider.setUserDetailsContextMapper(userDetailsContextMapper());
    return provider;
}

@Bean
public UserDetailsContextMapper userDetailsContextMapper() {
    UserDetailsContextMapper contextMapper = new MyUserDetailsContextMapper();
    return contextMapper;
}

@Bean
public MyDatabaseAuthenticationProvider databaseAuthenticationProvider() {
    return new MyDatabaseAuthenticationProvider();
}

There's really nothing special in the "MyDatabaseAuthenticationProvider" or "MyUserDetailsContextMapper" classes except for some custom logic for mapping and looking up users.

The app doesn't crash, but obviously not the page I want to show the user. :)

Any thoughts on how I can get rid of the StackOverflowError?

like image 885
Brian Waldhart Avatar asked Jun 10 '15 19:06

Brian Waldhart


2 Answers

I had the same problem, this was the solution for me:

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

The problem where the brackets after userDetailsService - removed them and it works as expected. From your code snippet I can't be sure where you get the userDetailsService from, for me I had it @Autowired.

like image 155
zeisi Avatar answered Sep 22 '22 13:09

zeisi


I had the same problem and another solution worked in my case. The difference is, that I had simply username and password, database authentication.

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

@Bean
UserDetailsService userDetailsService() {
    return new UserDetailsService();
}

The fix was to add the @Override annotation to the @Bean annotated method:

@Bean
@Override
UserDetailsService userDetailsService() {
    return new UserDetailsService();
}
like image 35
xenteros Avatar answered Sep 21 '22 13:09

xenteros