Environment: Spring Boot 2.3.1, Java 11
I have tried out a few things already (also comparing with the sample-app by spring), but so far I have been unsuccessful in creating a WebClient
that requires a ReactiveClientRegistrationRepository
.
I get the following exception when starting up my spring-boot application:
required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository'
The way I understand spring-boot-autoconfigure it should use the ReactiveOAuth2ClientAutoConfiguration
, as in the yml-file the required properties are given.
Following some code-snippets, I can provide more if something is missing to get the whole context
Main-Class
@Slf4j
@SpringBootApplication
@EnableConfigurationProperties(MyAppConfigurationProperties.class)
public class MyApp{
public static void main(final String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
Configuration:
@Configuration
//@Import(ReactiveOAuth2ClientAutoConfiguration.class) // in the test it works with this, but should not be required: spring-boot-autoconfigure
public class MyRestClientConfig {
@Bean
WebClient myWebClient(WebClient.Builder builder, ReactiveClientRegistrationRepository clientRegistrations) {
//content not relevant to this problem
}
}
Configuration for security
@EnableGlobalMethodSecurity(securedEnabled = true)
@EnableWebSecurity
@EnableWebFluxSecurity
public class SecurityConfig {
}
application.yml
spring:
security:
oauth2:
client:
registration:
providerid:
authorization-grant-type: "client_credentials"
client-id: "myClientId"
client-secret: "mySecret"
user-info-authentication-method: header
provider:
providerid:
token-uri: "working token-uri"
I tried with different dependencies, so some may not be required. Which dependencies are actually required?
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-autoconfigure</artifactId>
</dependency>
<!-- <dependency>-->
<!-- <groupId>org.springframework.security.oauth.boot</groupId>-->
<!-- <artifactId>spring-security-oauth2-autoconfigure</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security.oauth</groupId>-->
<!-- <artifactId>spring-security-oauth2</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-oauth2-client</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security</groupId>-->
<!-- <artifactId>spring-security-oauth2-core</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.security</groupId>-->
<!-- <artifactId>spring-security-oauth2-jose</artifactId>-->
<!-- </dependency>-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.boot</groupId>-->
<!-- <artifactId>spring-boot-starter-webflux</artifactId>-->
<!-- </dependency>-->
In an integration-test the Spring-Boot-Application starts up
@EnableConfigurationProperties
@Import(ReactiveOAuth2ClientAutoConfiguration.class) // in the test it works with this, but should not be required: spring-boot-autoconfigure, can be omitted if added in MyRestClientConfig
@ComponentScan(basePackages = "com.mycompany")
public class ManualClientTester {
}
EDIT 1: Debug of Positive Matches for Autoconfiguration
In test where it works:
============================
CONDITIONS EVALUATION REPORT
============================
Positive matches:
-----------------
ReactiveOAuth2ClientAutoConfiguration matched:
- @ConditionalOnClass found required classes 'reactor.core.publisher.Flux', 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity', 'org.springframework.security.oauth2.client.registration.ClientRegistration' (OnClassCondition)
- NoneNestedConditions 0 matched 1 did not; NestedCondition on ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.ServletApplicationCondition not a servlet web application (ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition)
ReactiveOAuth2ClientConfigurations.ReactiveClientRegistrationRepositoryConfiguration matched:
- OAuth2 Clients Configured Condition found registered clients myClientId (ClientsConfiguredCondition)
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; SearchStrategy: all) did not find any beans (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration matched:
- @ConditionalOnBean (types: org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; SearchStrategy: all) found bean 'clientRegistrationRepository' (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration#authorizedClientRepository matched:
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; SearchStrategy: all) did not find any beans (OnBeanCondition)
ReactiveOAuth2ClientConfigurations.ReactiveOAuth2ClientConfiguration#authorizedClientService matched:
- @ConditionalOnMissingBean (types: org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientService; SearchStrategy: all) did not find any beans (OnBeanCondition)
When starting my spring boot application:
============================
CONDITIONS EVALUATION REPORT
============================
Negative matches:
-----------------
ReactiveOAuth2ClientAutoConfiguration:
Did not match:
- NoneNestedConditions 1 matched 0 did not; NestedCondition on ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition.ServletApplicationCondition found 'session' scope (ReactiveOAuth2ClientAutoConfiguration.NonServletApplicationCondition)
Matched:
- @ConditionalOnClass found required classes 'reactor.core.publisher.Flux', 'org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity', 'org.springframework.security.oauth2.client.registration.ClientRegistration' (OnClassCondition)
EDIT 2: After changing as suggested, I have now the following:
@EnableReactiveMethodSecurity
@EnableWebFluxSecurity
public class SecurityConfig {
}
pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Furthermore all used versions of spring-projects:
<spring-amqp.version>2.2.7.RELEASE</spring-amqp.version>
<spring-batch.version>4.2.4.RELEASE</spring-batch.version>
<spring-boot.version>2.3.1.RELEASE</spring-boot.version>
<spring-data-releasetrain.version>Neumann-SR1</spring-data-releasetrain.version>
<spring-framework.version>5.2.7.RELEASE</spring-framework.version>
<spring-hateoas.version>1.1.0.RELEASE</spring-hateoas.version>
<spring-integration.version>5.3.1.RELEASE</spring-integration.version>
<spring-kafka.version>2.5.2.RELEASE</spring-kafka.version>
<spring-ldap.version>2.3.3.RELEASE</spring-ldap.version>
<spring-restdocs.version>2.0.4.RELEASE</spring-restdocs.version>
<spring-retry.version>1.2.5.RELEASE</spring-retry.version>
<spring-security.version>5.3.3.RELEASE</spring-security.version>
<spring-session-bom.version>Dragonfruit-RELEASE</spring-session-bom.version>
<spring-ws.version>3.0.9.RELEASE</spring-ws.version>
<spring.boot.version>2.3.1.RELEASE</spring.boot.version>
<spring.cloud.version>Hoxton.SR5</spring.cloud.version>
The problem still exists.
I ran into the same problem and noticed that the application created a ClientRegistrationRepository
instead of a ReactiveClientRegistrationRepository
. Somewhere in Spring boot the @EnableWebSecurity
was added (we need the @EnableWebFluxSecurity
in this case).
To fix the problem I've added the following property:
spring.main.web-application-type: reactive
If you're also using @SpringBootTest
to test your application you also need to add the property there.
@SpringBootTest(properties = ["spring.main.web-application-type=reactive]")
or by setting the web environment to NONE
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
The reason why this happens is also explained in this answer: Error when using @EnableWebFluxSecurity in springboot