Hi I am learning about Spring Security and was trying to create a simple OAuth2 client and resource server based on the guidelines at https://dzone.com/articles/implement-oauth-20-easily-with-spring-boot-and-spr
I came into an issue where the compiler keeps saying that it cannot find a bean for "ClientRegistrationRepository". I did some digging on the web, which says that if the Spring client configurations are configured correctly, it should work. Someone having similar issues said the problem may be caused by indetation issue in the properties file, but I am not seeing such case.
May I seek for your help to see if there is anything configured incorrectly, thanks.
Console output
***************************
APPLICATION FAILED TO START
***************************
Description:
Parameter 0 of method webClient in com.somecompany.configuration.WebClientConfig required a bean of type 'org.springframework.security.oauth2.client.registration.ClientRegistrationRepository' 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.ClientRegistrationRepository' in your configuration.
OAuth2 client main class
package com.somecompany;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Oauth2DemoClientApplication {
public static void main(String[] args) {
SpringApplication.run(Oauth2DemoClientApplication.class, args);
}
}
OAuth2 client controller
package com.somecompany.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient;
@RestController
@RequestMapping("/api/client")
public class Oauth2DemoClientController {
@Autowired
private WebClient webClient;
@Value("${resourceServer.url}")
private String resourceServerUrl;
@Value("${resourceServer.helloPath}")
private String resourceServerHelloPath;
@GetMapping("/")
public String home(@AuthenticationPrincipal OidcUser user) {
return "Welcome " + user.getFullName();
}
@GetMapping("/hello")
public String sayHello() {
return webClient.get().uri(resourceServerUrl + resourceServerHelloPath).retrieve().bodyToMono(String.class)
.block();
}
}
OAuth2 client configuration
package com.somecompany.configuration;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.web.OAuth2AuthorizedClientRepository;
import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
@Configuration
public class WebClientConfig {
@Value("${defaultClientApplication}")
private String defaultClientApplication;
@Bean
WebClient webClient(ClientRegistrationRepository clientRegistrations,
OAuth2AuthorizedClientRepository authorizedClients) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations, authorizedClients);
oauth2.setDefaultOAuth2AuthorizedClient(true);
oauth2.setDefaultClientRegistrationId(defaultClientApplication);
return WebClient.builder().apply(oauth2.oauth2Configuration()).build();
}
}
OAuth2 client application.yml
logging.level.root: "debug"
defaultClientApplication: "okta"
spring:
security:
oauth2:
client:
provider:
okta:
issuer-uri: "https://dev-27548664.okta.com/oauth2/default"
registration:
okta:
client-id: {client ID}
client-secret: {client secret}
resourceServer:
url: "http://localhost:8081"
helloPath: "/api/resource/hello"
OAuth2 client 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.4.3</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.somecompany</groupId>
<artifactId>oauth2-demo-client</artifactId>
<version>1.0.0</version>
<name>oauth2-demo-client</name>
<description>oauth2-demo-client</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</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-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>