I am using spring oAuthClient version 5.2.4.RELEASE By following the document link of spring security https://docs.spring.io/spring-security/site/docs/current/reference/html5/#oauth2Client-authorized-manager-provider
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import reactor.core.publisher.Mono;
@AllArgsConstructor
@Configuration
@Slf4j
public class WebClientConfig {
@Bean("AuthProvider")
WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations,
authorizedClients);
oauth.setDefaultOAuth2AuthorizedClient(true);
oauth.setDefaultClientRegistrationId("AuthProvider");
return WebClient.builder()
.filter(oauth)
.filter(this.logRequest())
.build();
}
private ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
log.info("Request: [{}] {}", clientRequest.method(), clientRequest.url());
log.debug("Payload: {}", clientRequest.body());
return Mono.just(clientRequest);
});
}
application.yaml
security:
oauth2:
client:
provider:
AuthProvider:
token-uri: ${tokenpath<read from environment variable>}
registration:
AuthProvider:
authorization-grant-type: client_credentials
client-id: ${<read from environment variable>}
client-secret: ${<read from environment variable>}
Getting the following error
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method webClient in com.sample.config.WebClientConfig required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' that could not be found.
The injection point has the following annotations:
- @org.springframework.beans.factory.annotation.Autowired(required=true)
Action:
Consider defining a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' in your configuration.
Let me know, if I missed any configuration as didnot get any specific help from other questions of stackoverflow
Interface ReactiveClientRegistrationRepository Therefore, this repository provides the capability to store a sub-set copy of the primary client registration information externally from the Authorization Server.
The OAuth 2.0 Client features provide support for the Client role as defined in the OAuth 2.0 Authorization Framework. At a high-level, the core features available are: Authorization Grant support. Authorization Code. Refresh Token.
It serves as an open authorization protocol for enabling a third party application to get limited access to an HTTP service on behalf of the resource owner. It can do so while not revealing the identity or the long-term credentials of the user. A third-party application itself can also use it on its behalf.
And here's the response client bean: This configuration is the same as the default one and is using the Spring implementation which is based on exchanging an authorization code with the provider. Of course, we could also substitute a custom response client.
<dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> We can’t inject directly the AuthenticationManager bean anymore in Spring-Boot 2.0, but it still is required by Spring Security. Therefore, we need to implement a small hack in order to gain access to this object:
6. Spring Boot OAuth2 Auto-Configuration (Using New Stack) To use the new stack, we need to add dependencies based on what we want to configure — an authorization server, a resource server, or a client application. Let's look at them one by one. 6.1.
These default configurations provide all the necessary information for authentication, which is what allows us to only enter the client credentials. If we want to use a different authentication provider not configured in Spring Security, we'll need to define the full configuration, with information such as authorization URI and token URI.
I am using spring boot 2.3.1.RELEASE I had the same problem, my pom.xml contained both these dependencies in my pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
I removed the following dependency and that did the trick for me :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Not saying this will resolve your hassle but this might also be a dependency conflict issue for you.
This other post put me on track : Reactive OAuth2 with Spring Security 5.3.2 ReactiveClientRegistrationRepository bean could not be found
Your spring-boot configuration is perfect.
Root cause of the issue: The problem is in application.yaml. Either the configuration is wrong or not picked from the environment.
So, the problem is not the OAuth2 version but the configuration in application.yaml.
Note : ReactiveClientRegistrationRepository
bean is created only
when you configure the client with the OAuth2 application owner details.
I created a new project from start.spring.io and used your configuration in that.
And after running the project with your configuration, I was facing the same issue.
Error log :
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method webClient in com.example.sampleoauth2.WebClientConfig required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' that could not be found.
The following candidates were found but could not be injected:
- Bean method 'clientRegistrationRepository' in 'ReactiveOAuth2ClientConfigurations.ReactiveClientRegistrationRepositoryConfiguration' not loaded because OAuth2 Clients Configured Condition registered clients is not available
Action:
Consider revisiting the entries above or defining a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' in your configuration.
Then, I saw that I didn't configure properties in application.yml file.
I read Spring Boot and OAuth2.0 Docs about how to get client-id and client-secret from github (Example) as you register your spring-boot app as OAuth app in that.
As soon as, I configured my application started to work.
I'm using spring-boot 2.3.1.RELEASE and OAuth2Client version 5.3.3.
My pom.xml :
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath /> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>sampleOauth2</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>sampleOauth2</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<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>
<dependency>
<groupId>org.projectreactor</groupId>
<artifactId>reactor-spring</artifactId>
<version>1.0.1.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
My client github registration properties for application.yml:
spring:
security:
oauth2:
client:
registration:
github:
client-id: 22a7100de41c7308d346
client-secret: 05910ab890be29579e9c183443d92e756c450aaf
Your updated WebClientConfig @Configuration class :
package com.example.sampleoauth2;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
@Configuration
public class WebClientConfig {
public static Logger log = LogManager.getLogger();
@Bean
public WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations,
ServerOAuth2AuthorizedClientRepository authorizedClients) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, authorizedClients);
oauth.setDefaultOAuth2AuthorizedClient(true);
return WebClient.builder().filter(oauth).filter(this.logRequest()).build();
}
private ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
log.info("Request: [{}] {}", clientRequest.method(), clientRequest.url());
log.debug("Payload: {}", clientRequest.body());
return Mono.just(clientRequest);
});
}
}
Success Log :
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.3.1.RELEASE)
2020-06-26 20:36:08.380 INFO 15956 --- [ main] c.e.s.SampleOauth2Application : Starting SampleOauth2Application on Anishs-MacBook-Pro.local with PID 15956 (/Users/anish/Downloads/sampleOauth2/target/classes started by anish in /Users/anish/Downloads/sampleOauth2)
2020-06-26 20:36:08.381 INFO 15956 --- [ main] c.e.s.SampleOauth2Application : No active profile set, falling back to default profiles: default
2020-06-26 20:36:08.935 INFO 15956 --- [ main] ctiveUserDetailsServiceAutoConfiguration :
Using generated security password: 7c63302f-f913-4aa1-852d-cb8445719acb
2020-06-26 20:36:09.132 INFO 15956 --- [ main] o.s.b.web.embedded.netty.NettyWebServer : Netty started on port(s): 8080
2020-06-26 20:36:09.138 INFO 15956 --- [ main] c.e.s.SampleOauth2Application : Started SampleOauth2Application in 0.978 seconds (JVM running for 1.313)
I used the configurations that @AnishB. suggested as answer but still got the error:
Parameter 0 of method webClient in com.example.sampleoauth2.WebClientConfig required a bean of type 'org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository' that could not be found.
So, i had to use these dependencies with spring 2.3.1.RELEASE:
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
And this the WebClientConfig
class:
@Configuration
public class WebClientConfig {
private static final Logger log = LoggerFactory.getLogger(WebClientConfig.class);
@Bean("cr")
ReactiveClientRegistrationRepository getRegistration(
@Value("${spring.security.oauth2.client.provider.keycloak.token-uri}") String tokenUri,
@Value("${spring.security.oauth2.client.registration.keycloak.client-id}") String clientId,
@Value("${spring.security.oauth2.client.registration.keycloak.client-secret}") String clientSecret
) {
ClientRegistration registration = ClientRegistration
.withRegistrationId("keycloak")
.tokenUri(tokenUri)
.clientId(clientId)
.clientSecret(clientSecret)
.authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
.build();
return new InMemoryReactiveClientRegistrationRepository(registration);
}
@Bean(name = "keycloak")
WebClient webClient(@Qualifier("cr") ReactiveClientRegistrationRepository clientRegistrations) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
oauth.setDefaultClientRegistrationId("keycloak");
return WebClient.builder()
.filter(oauth)
.filter(logRequest())
.build();
}
private ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
log.info("Request: [{}] {}", clientRequest.method(), clientRequest.url());
log.debug("Payload: {}", clientRequest.body());
return Mono.just(clientRequest);
});
}
}
and everything works fine, but it is question for me that why the solution of @AnishB. didn't worked for me?!
ReactiveClientRegistrationRepository
is come with Reactive stack (netty)
, not with Servlet stack (tomcat)
In case your pom.xml
include spring-boot-starter-web
, Spring understand that you use Servlet stack
, it will load ClientRegistrationRepository
instead of ReactiveClientRegistrationRepository
To create bean of WebClient
, two solution you can use:
Remove spring-boot-starter-web
from pom.xml
so Spring understand you are in Reactive stack
@Bean
WebClient webClient(
ReactiveClientRegistrationRepository clientRegistrationRepository,
ReactiveOAuth2AuthorizedClientService authorizedClientService
) {
var oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService
)
);
oauth.setDefaultClientRegistrationId("AuthProvider");
return WebClient.builder()
.filter(oauth)
.build();
}
Keep spring-boot-starter-web
in pom.xml
@Bean // with spring-boot-starter-web
WebClient webClient(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService
) {
var oauth = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
new AuthorizedClientServiceOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientService
)
);
oauth.setDefaultClientRegistrationId("AuthProvider");
return WebClient.builder()
.apply(oauth.oauth2Configuration())
.build();
}
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