# Authorized Clients ## Resolving an Authorized Client The `@RegisteredOAuth2AuthorizedClient` annotation provides the capability of resolving a method parameter to an argument value of type `OAuth2AuthorizedClient`. This is a convenient alternative compared to accessing the `OAuth2AuthorizedClient` using the `ReactiveOAuth2AuthorizedClientManager` or `ReactiveOAuth2AuthorizedClientService`. Java ``` @Controller public class OAuth2ClientController { @GetMapping("/") public Mono index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) { return Mono.just(authorizedClient.getAccessToken()) ... .thenReturn("index"); } } ``` Kotlin ``` @Controller class OAuth2ClientController { @GetMapping("/") fun index(@RegisteredOAuth2AuthorizedClient("okta") authorizedClient: OAuth2AuthorizedClient): Mono { return Mono.just(authorizedClient.accessToken) ... .thenReturn("index") } } ``` The `@RegisteredOAuth2AuthorizedClient` annotation is handled by `OAuth2AuthorizedClientArgumentResolver`, which directly uses a [ReactiveOAuth2AuthorizedClientManager](#oauth2Client-authorized-manager-provider) and therefore inherits it’s capabilities. ## WebClient integration for Reactive Environments The OAuth 2.0 Client support integrates with `WebClient` using an `ExchangeFilterFunction`. The `ServerOAuth2AuthorizedClientExchangeFilterFunction` provides a simple mechanism for requesting protected resources by using an `OAuth2AuthorizedClient` and including the associated `OAuth2AccessToken` as a Bearer Token. It directly uses an [ReactiveOAuth2AuthorizedClientManager](#oauth2Client-authorized-manager-provider) and therefore inherits the following capabilities: * An `OAuth2AccessToken` will be requested if the client has not yet been authorized. * `authorization_code` - triggers the Authorization Request redirect to initiate the flow * `client_credentials` - the access token is obtained directly from the Token Endpoint * `password` - the access token is obtained directly from the Token Endpoint * If the `OAuth2AccessToken` is expired, it will be refreshed (or renewed) if a `ReactiveOAuth2AuthorizedClientProvider` is available to perform the authorization The following code shows an example of how to configure `WebClient` with OAuth 2.0 Client support: Java ``` @Bean WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) { ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); return WebClient.builder() .filter(oauth2Client) .build(); } ``` Kotlin ``` @Bean fun webClient(authorizedClientManager: ReactiveOAuth2AuthorizedClientManager): WebClient { val oauth2Client = ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager) return WebClient.builder() .filter(oauth2Client) .build() } ``` ### Providing the Authorized Client The `ServerOAuth2AuthorizedClientExchangeFilterFunction` determines the client to use (for a request) by resolving the `OAuth2AuthorizedClient` from the `ClientRequest.attributes()` (request attributes). The following code shows how to set an `OAuth2AuthorizedClient` as a request attribute: Java ``` @GetMapping("/") public Mono index(@RegisteredOAuth2AuthorizedClient("okta") OAuth2AuthorizedClient authorizedClient) { String resourceUri = ... return webClient .get() .uri(resourceUri) .attributes(oauth2AuthorizedClient(authorizedClient)) (1) .retrieve() .bodyToMono(String.class) ... .thenReturn("index"); } ``` Kotlin ``` @GetMapping("/") fun index(@RegisteredOAuth2AuthorizedClient("okta") authorizedClient: OAuth2AuthorizedClient): Mono { val resourceUri: String = ... return webClient .get() .uri(resourceUri) .attributes(oauth2AuthorizedClient(authorizedClient)) (1) .retrieve() .bodyToMono() ... .thenReturn("index") } ``` |**1**|`oauth2AuthorizedClient()` is a `static` method in `ServerOAuth2AuthorizedClientExchangeFilterFunction`.| |-----|--------------------------------------------------------------------------------------------------------| The following code shows how to set the `ClientRegistration.getRegistrationId()` as a request attribute: Java ``` @GetMapping("/") public Mono index() { String resourceUri = ... return webClient .get() .uri(resourceUri) .attributes(clientRegistrationId("okta")) (1) .retrieve() .bodyToMono(String.class) ... .thenReturn("index"); } ``` Kotlin ``` @GetMapping("/") fun index(): Mono { val resourceUri: String = ... return webClient .get() .uri(resourceUri) .attributes(clientRegistrationId("okta")) (1) .retrieve() .bodyToMono() ... .thenReturn("index") } ``` |**1**|`clientRegistrationId()` is a `static` method in `ServerOAuth2AuthorizedClientExchangeFilterFunction`.| |-----|------------------------------------------------------------------------------------------------------| ### Defaulting the Authorized Client If neither `OAuth2AuthorizedClient` or `ClientRegistration.getRegistrationId()` is provided as a request attribute, the `ServerOAuth2AuthorizedClientExchangeFilterFunction` can determine the *default* client to use depending on it’s configuration. If `setDefaultOAuth2AuthorizedClient(true)` is configured and the user has authenticated using `ServerHttpSecurity.oauth2Login()`, the `OAuth2AccessToken` associated with the current `OAuth2AuthenticationToken` is used. The following code shows the specific configuration: Java ``` @Bean WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) { ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); oauth2Client.setDefaultOAuth2AuthorizedClient(true); return WebClient.builder() .filter(oauth2Client) .build(); } ``` Kotlin ``` @Bean fun webClient(authorizedClientManager: ReactiveOAuth2AuthorizedClientManager): WebClient { val oauth2Client = ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager) oauth2Client.setDefaultOAuth2AuthorizedClient(true) return WebClient.builder() .filter(oauth2Client) .build() } ``` | |It is recommended to be cautious with this feature since all HTTP requests will receive the access token.| |---|---------------------------------------------------------------------------------------------------------| Alternatively, if `setDefaultClientRegistrationId("okta")` is configured with a valid `ClientRegistration`, the `OAuth2AccessToken` associated with the `OAuth2AuthorizedClient` is used. The following code shows the specific configuration: Java ``` @Bean WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) { ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); oauth2Client.setDefaultClientRegistrationId("okta"); return WebClient.builder() .filter(oauth2Client) .build(); } ``` Kotlin ``` @Bean fun webClient(authorizedClientManager: ReactiveOAuth2AuthorizedClientManager): WebClient { val oauth2Client = ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager) oauth2Client.setDefaultClientRegistrationId("okta") return WebClient.builder() .filter(oauth2Client) .build() } ``` | |It is recommended to be cautious with this feature since all HTTP requests will receive the access token.| |---|---------------------------------------------------------------------------------------------------------| [OAuth2 Client Authentication](client-authentication.html)[OAuth2 Resource Server](../resource-server/index.html)