For the latest stable version, please use Spring Security 6.4.1!spring-doc.cn

Authorized Client Features

This section covers additional features provided by Spring Security for the OAuth2 client.spring-doc.cn

Resolving an Authorized Client

The @RegisteredOAuth2AuthorizedClient annotation provides the ability to resolve a method parameter to an argument value of type OAuth2AuthorizedClient. This is a convenient alternative compared to accessing the OAuth2AuthorizedClient by using the OAuth2AuthorizedClientManager or OAuth2AuthorizedClientService. The following example shows how to use @RegisteredOAuth2AuthorizedClient:spring-doc.cn

@Controller
public class OAuth2ClientController {

	@GetMapping("/")
	public String index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) {
		OAuth2AccessToken accessToken = authorizedClient.getAccessToken();

		...

		return "index";
	}
}
@Controller
class OAuth2ClientController {
    @GetMapping("/")
    fun index(@RegisteredOAuth2AuthorizedClient("okta") authorizedClient: OAuth2AuthorizedClient): String {
        val accessToken = authorizedClient.accessToken

        ...

        return "index"
    }
}

The @RegisteredOAuth2AuthorizedClient annotation is handled by OAuth2AuthorizedClientArgumentResolver, which directly uses an OAuth2AuthorizedClientManager and, therefore, inherits its capabilities.spring-doc.cn

WebClient Integration for Servlet Environments

The OAuth 2.0 Client support integrates with WebClient by using an ExchangeFilterFunction.spring-doc.cn

The ServletOAuth2AuthorizedClientExchangeFilterFunction provides a mechanism for requesting protected resources by using an OAuth2AuthorizedClient and including the associated OAuth2AccessToken as a Bearer Token. It directly uses an OAuth2AuthorizedClientManager and, therefore, inherits the following capabilities:spring-doc.cn

  • An OAuth2AccessToken is requested if the client has not yet been authorized.spring-doc.cn

    • authorization_code: Triggers the Authorization Request redirect to initiate the flow.spring-doc.cn

    • client_credentials: The access token is obtained directly from the Token Endpoint.spring-doc.cn

    • password: The access token is obtained directly from the Token Endpoint.spring-doc.cn

  • If the OAuth2AccessToken is expired, it is refreshed (or renewed) if an OAuth2AuthorizedClientProvider is available to perform the authorizationspring-doc.cn

The following code shows an example of how to configure WebClient with OAuth 2.0 Client support:spring-doc.cn

@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
	ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
			new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
	return WebClient.builder()
			.apply(oauth2Client.oauth2Configuration())
			.build();
}
@Bean
fun webClient(authorizedClientManager: OAuth2AuthorizedClientManager?): WebClient {
    val oauth2Client = ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager)
    return WebClient.builder()
            .apply(oauth2Client.oauth2Configuration())
            .build()
}

Providing the Authorized Client

The ServletOAuth2AuthorizedClientExchangeFilterFunction determines the client to use (for a request) by resolving the OAuth2AuthorizedClient from the ClientRequest.attributes() (request attributes).spring-doc.cn

The following code shows how to set an OAuth2AuthorizedClient as a request attribute:spring-doc.cn

@GetMapping("/")
public String index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) {
	String resourceUri = ...

	String body = webClient
			.get()
			.uri(resourceUri)
			.attributes(oauth2AuthorizedClient(authorizedClient))   (1)
			.retrieve()
			.bodyToMono(String.class)
			.block();

	...

	return "index";
}
@GetMapping("/")
fun index(@RegisteredOAuth2AuthorizedClient("okta") authorizedClient: OAuth2AuthorizedClient): String {
    val resourceUri: String = ...
    val body: String = webClient
            .get()
            .uri(resourceUri)
            .attributes(oauth2AuthorizedClient(authorizedClient)) (1)
            .retrieve()
            .bodyToMono()
            .block()

    ...

    return "index"
}
1 oauth2AuthorizedClient() is a static method in ServletOAuth2AuthorizedClientExchangeFilterFunction.

The following code shows how to set the ClientRegistration.getRegistrationId() as a request attribute:spring-doc.cn

@GetMapping("/")
public String index() {
	String resourceUri = ...

	String body = webClient
			.get()
			.uri(resourceUri)
			.attributes(clientRegistrationId("okta"))   (1)
			.retrieve()
			.bodyToMono(String.class)
			.block();

	...

	return "index";
}
@GetMapping("/")
fun index(): String {
    val resourceUri: String = ...

    val body: String = webClient
            .get()
            .uri(resourceUri)
            .attributes(clientRegistrationId("okta"))  (1)
            .retrieve()
            .bodyToMono()
            .block()

    ...

    return "index"
}
1 clientRegistrationId() is a static method in ServletOAuth2AuthorizedClientExchangeFilterFunction.

Defaulting the Authorized Client

If neither OAuth2AuthorizedClient or ClientRegistration.getRegistrationId() is provided as a request attribute, the ServletOAuth2AuthorizedClientExchangeFilterFunction can determine the default client to use, depending on its configuration.spring-doc.cn

If setDefaultOAuth2AuthorizedClient(true) is configured and the user has authenticated by using HttpSecurity.oauth2Login(), the OAuth2AccessToken associated with the current OAuth2AuthenticationToken is used.spring-doc.cn

The following code shows the specific configuration:spring-doc.cn

@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
	ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
			new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
	oauth2Client.setDefaultOAuth2AuthorizedClient(true);
	return WebClient.builder()
			.apply(oauth2Client.oauth2Configuration())
			.build();
}
@Bean
fun webClient(authorizedClientManager: OAuth2AuthorizedClientManager?): WebClient {
    val oauth2Client = ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager)
    oauth2Client.setDefaultOAuth2AuthorizedClient(true)
    return WebClient.builder()
            .apply(oauth2Client.oauth2Configuration())
            .build()
}

Be cautious with this feature, since all HTTP requests receive the access token.spring-doc.cn

Alternatively, if setDefaultClientRegistrationId("okta") is configured with a valid ClientRegistration, the OAuth2AccessToken associated with the OAuth2AuthorizedClient is used.spring-doc.cn

The following code shows the specific configuration:spring-doc.cn

@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
	ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
			new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
	oauth2Client.setDefaultClientRegistrationId("okta");
	return WebClient.builder()
			.apply(oauth2Client.oauth2Configuration())
			.build();
}
@Bean
fun webClient(authorizedClientManager: OAuth2AuthorizedClientManager?): WebClient {
    val oauth2Client = ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager)
    oauth2Client.setDefaultClientRegistrationId("okta")
    return WebClient.builder()
            .apply(oauth2Client.oauth2Configuration())
            .build()
}

Be cautious with this feature, since all HTTP requests receive the access token.spring-doc.cn