I am in the process of converting an existing and working Spring Security (version 3.2.10) XML-configuration to a Java-based configuration. The XML-configuration I am replacing has an authentication manager configured:
<authentication-manager alias="authenticationManager">
<authentication-provider ref="kerberosServiceAuthenticationProvider"/>
<authentication-provider ref="samlAuthenticationProvider"/>
<authentication-provider ref="pkiAuthenticationProvider"/>
<authentication-provider ref="openIdConnectAuthenticationProvider"/>
</authentication-manager>
My Java configuration equivalent is:
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
{
@Autowired
public void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(kerberosServiceAuthenticationProvider())
.authenticationProvider(samlAuthenticationProvider())
.authenticationProvider(pkiAuthenticationProvider())
.authenticationProvider(openIdConnectAuthenticationProvider());
}
}
As the authentication manager is referred to by its alias in constructing other beans, I have overridden the authenticationmanagerbean like this:
@Override
@Bean(name = "authenticationManager")
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
As suggested e.g. in How To Inject AuthenticationManager using Java Configuration in a Custom Filter However, on creating of this bean, the following exception is thrown:
Caused by: java.lang.IllegalArgumentException: delegateBuilder cannot be null
at org.springframework.util.Assert.notNull(Assert.java:112)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.<init>(WebSecurityConfigurerAdapter.java:426)
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter.authenticationManagerBean(WebSecurityConfigurerAdapter.java:220)
The delegate builder is the authentication builder that is being used as first argument when overriding the bean (snippet is the implementation of super.authenticationManagerBean()), which is null.
public AuthenticationManager authenticationManagerBean() throws Exception {
return new AuthenticationManagerDelegator(authenticationBuilder, context);
}
So it seems something is missing when this bean is created. This delegate builder is only set by this method in the WebSecurityConfigurerAdapter:
@Autowired
public void setObjectPostProcessor(ObjectPostProcessor<Object> objectPostProcessor)
{...}
But it doesn't get called (and does not seem to be meant to override). I also noticed the configure method has not been called yet. I am obviously missing something but have no idea what it is.
I have had the exact same error while migrating to Spring Boot 2 (in the process, I hade to migrate from Spring Security 4 to Spring Security 5.0.0 and converting my XML configuration to JavaConfig).
So I'm not sure this applies to you. In Spring Security 5, that authenticationBuilder
is initialized in WebSecurityConfigurerAdapter's method:
@Autowired
public void setApplicationContext(ApplicationContext context) {..}
It should therefore try to inject the context. However, my @Bean-annotated method which defines the AuthenticationManager bean is always invoked before that method and results in the same error than you have. I fixed that by simply implementing the ApplicationContextAware interface, which force the invocation of the method before everything else:
public class MySecurityConfigurerAdapter extends WebSecurityConfigurerAdapter implements ApplicationContextAware {
/*...*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(dbAuthenticationProvider)
.authenticationProvider(otherAuthProvider);
}
@Bean(name = BeanIds.AUTHENTICATION_MANAGER)
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
I can't explain the exact reason behind, I couldn't find a new "right" way to do it in the documentation, but at least it worked for me.
If you are having problems with AuthenticationManagerBuilder
giving you an error that states IllegalArgumentException: delegateBuilder cannot be null
you likely have a circular bean dependency that is not able to be resolved. This is easy to do with AuthenticationManagerBuilder
. Instead, I'd recommend exposing an AuthenticationManager
as a Bean and do not use AuthenticationManagerBuilder
at all.
For example:
@Bean
public ProviderManager authenticationManager() {
return new ProviderManager(Arrays.asList(
kerberosServiceAuthenticationProvider(),
samlAuthenticationProvider(),
pkiAuthenticationProvider(),
openIdConnectAuthenticationProvider());
}
If you are still having issues, you can also try making the methods defining Spring Security's authentication (i.e. AuthenticationManager
and AuthenticationProvider
, PasswordEncoder
, etc) static which allows the definition to be loaded without initializing the entire class. If problems persist, I'd recommend moving all of your AuthenticationManager
and AuthenticationProvider
configuration to a separate configuration class.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With