After migration to spring boot 3.2.1 (from 3.1.2) I'm facing the following issue:
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate
[org.springframework.security.web.server.SecurityWebFilterChain]: Factory method 'springSecurityFilterChain' threw
exception with message: authenticationManager cannot be null
at
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:177) ~
[spring-beans-6.1.2.jar:6.1.2]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:651) ~
[spring-beans-6.1.2.jar:6.1.2]
... 143 common frames omitted
Caused by: java.lang.IllegalArgumentException: authenticationManager cannot be null
at org.springframework.util.Assert.notNull(Assert.java:172) ~[spring-core-6.1.2.jar:6.1.2]
at org.springframework.security.web.server.authentication.AuthenticationWebFilter.<init>
(AuthenticationWebFilter.java:94) ~[spring-security-web-6.2.1.jar:6.2.1]
at
org.springframework.security.config.web.server.ServerHttpSecurity$HttpBasicSpec.configure(ServerHttpSecurity.java:2305)
~[spring-security-config-6.2.1.jar:6.2.1]
at org.springframework.security.config.web.server.ServerHttpSecurity.build(ServerHttpSecurity.java:1545) ~[spring-
security-config-6.2.1.jar:6.2.1]
at
org.springframework.boot.actuate.autoconfigure.security.reactive.ReactiveManagementWebSecurityAutoConfiguration.sprin gSecurityFilterChain(ReactiveManagementWebSecurityAutoConfiguration.java:69) ~[spring-boot-actuator-autoconfigure- 3.2.1.jar:3.2.1]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:568) ~[na:na]
at
org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:140) ~
[spring-beans-6.1.2.jar:6.1.2]
... 144 common frames omitted
Relevant dependencies:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-impl</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-gson</artifactId>
<version>${jwt.version}</version>
</dependency>
<dependency>
<groupId>io.github.openfeign.form</groupId>
<artifactId>feign-form</artifactId>
<version>${feign-form.version}</version>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>${caffeine.version}</version>
</dependency>
<dependency>
<groupId>com.playtika.reactivefeign</groupId>
<artifactId>feign-reactor-spring-cloud-starter</artifactId>
<version>${reactive-feign.version}</version>
<type>pom</type>
</dependency>
Configuration file:
@Configuration
@ComponentScan(basePackageClasses = SecurityConfig.class)
@EnableReactiveMethodSecurity
@EnableWebFluxSecurity
@EnableConfigurationProperties({ ClientProperties.class, MultipleIssuersProperties.class })
class SecurityConfig {
AuthenticationExceptionEntryPoint authenticationEntryPoint; // autowired
Issuer mainIssuer;
MultipleIssuersProperties issuers;
List<String> whitelistedUrls;
List<String> allowedOrigins;
// Constructor omitted
@Bean
public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) {
return http
.authorizeExchange(exchange -> exchange
.pathMatchers(whitelistedUrls.toArray(String[]::new))
.permitAll()
.anyExchange().authenticated())
.cors(cors -> cors.configurationSource(corsConfigurationSource()))
.csrf(CsrfSpec::disable)
.exceptionHandling(exception -> exception.authenticationEntryPoint(authenticationEntryPoint))
.oauth2ResourceServer(server -> server.authenticationManagerResolver(reactiveAuthenticationManagerResolver()))
.build();
}
@Bean
public JwtIssuerReactiveAuthenticationManagerResolver reactiveAuthenticationManagerResolver() {
var managers = new HashMap<String, ReactiveAuthenticationManager>();
managers.put(
mainIssuer.issuerUri(),
new JwtReactiveAuthenticationManager(reactiveJwtDecoder())
);
issuers.issuers().forEach(issuer -> {
var jwkSource = reactiveRemoteJWKSource(issuer);
var jwtDecoder = reactiveJwtDecoder(issuer, jwkSource);
var manager = new JwtReactiveAuthenticationManager(jwtDecoder);
managers.put(issuer.issuerUri(), manager);
});
return new JwtIssuerReactiveAuthenticationManagerResolver(issuer -> justOrEmpty(managers.get(issuer)));
}
@Bean
public ReactiveJwtDecoder reactiveJwtDecoder() {
return reactiveJwtDecoder(mainIssuer, reactiveRemoteJWKSource());
}
// other beans omitted
Codebase remains unchanged, aside from version upgrade.
Comment From: wilkinsona
After migration to spring boot 3.2.1
What version were you using previously?
Relevant dependencies I think there may be other dependencies that are relevant. For example, I can see
ReactiveManagementWebSecurityAutoConfigurationwhich is part of Spring Boot's actuator but is not shown in your dependencies.
If you would like us to spend some more time investigating, please spend some time providing a complete yet minimal sample that reproduces the problem. You can share it with us by pushing it to a separate repository on GitHub or by zipping it up and attaching it to this issue.
Comment From: razvdana
Edited*, will try to find some time tomorrow to set up something
Comment From: razvdana
Update: Somehow I missed some conditionals so the entire SecurityConfig is not loaded. Then through auto configuration it leads to
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'httpHandler' defined in class path resource [org/springframework/boot/autoconfigure/web/reactive/HttpHandlerAutoConfiguration$AnnotationConfig.class]: Failed to instantiate [org.springframework.http.server.reactive.HttpHandler]: Factory method 'httpHandler' threw exception with message: Error creating bean with name 'org.springframework.security.config.annotation.web.reactive.WebFluxSecurityConfiguration': Unsatisfied dependency expressed through method 'setSecurityWebFilterChains' parameter 0: Error creating bean with name 'springSecurityFilterChain' defined in class path resource [org/springframework/boot/actuate/autoconfigure/security/reactive/ReactiveManagementWebSecurityAutoConfiguration.class]: Failed to instantiate [org.springframework.security.web.server.SecurityWebFilterChain]: Factory method 'springSecurityFilterChain' threw exception with message: authenticationManager cannot be null
What would be the recommended approach to conditionally disable security ? Define a web filter chain with permitAll, or disable some auto configurations ?
Comment From: wilkinsona
It's hard to say. In your case, ReactiveManagementWebSecurityAutoConfiguration caused the problem. That's the auto-configuration for Actuator security in a WebFlux app. It could be that it should have backed off automatically. You could exclude it, but that may mask an underlying problem rather than solving it. I think we'll really need a sample that reproduces the problem to be able to offer any specific advice or identify if a fix needs to be made.
Comment From: razvdana
Created this demo project.
Comment From: wilkinsona
Thank you.
It works in 3.1.x due to the auto-configuration of a MapReactiveUserDetailsService by ReactiveUserDetailsServiceAutoConfiguration. From this user details service, Spring Security is able to create the authentication manager that the basic auth configured in ReactiveManagementWebSecurityAutoConfiguration requires.
It does not work in 3.2.x due to https://github.com/spring-projects/spring-boot/issues/35338 which means that the MapReactiveUserDetailsService is no longer auto-configured as you have resource server on the classpath. The same problem occurs with 3.1.x if ReactiveUserDetailsServiceAutoConfiguration is excluded. This is another variant of https://github.com/spring-projects/spring-boot/issues/37504 that we'd overlooked previously and is the same as the problems that we attempted to fix in https://github.com/spring-projects/spring-boot/commit/afad358047c4fa9a0a9281d406e875279528a495.
This fix made in https://github.com/spring-projects/spring-boot/commit/afad358047c4fa9a0a9281d406e875279528a495 doesn't work here due to the auto-configuration ordering. The deny-all authentication manager is auto-configured by ReactiveSecurityAutoConfiguration in the absence of a ReactiveAuthenticationManager, a ReactiveUserDetailsService, and a SecurityWebFilterChain:
https://github.com/spring-projects/spring-boot/blob/d032b9d2342d23036d66223ee2297c431896828d/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/reactive/ReactiveSecurityAutoConfiguration.java#L59-L64
ReactiveManagementWebSecurityAutoConfiguration is ordered before ReactiveSecurityAutoConfiguration and defines a SecurityWebFilterChain, causing the auto-configuration of the deny-all authentication manager to back off.
For the purposes of Actuator security, I think we need to auto-configure a deny-all authentication manager when there's no ReactiveAuthenticationManager and no ReactiveUserDetailsService. I'm not yet sure how the ordering will work out though.
Comment From: wilkinsona
Closed by https://github.com/spring-projects/spring-boot/commit/6ec56da91910fb76a5e10a0b48809de1712f181e.