Docs: WebClient OAuth2 Setup for Reactive Applications might be wrong

See original GitHub issue

In the reference doc there is an example for a WebClient with OAuth2 Setup for Reactive Applications: https://docs.spring.io/spring-security/site/docs/current/reference/html5/#webclient-setup

    @Bean
    WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations, ServerOAuth2AuthorizedClientRepository authorizedClients) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
                new ServerOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
        oauth.setDefaultClientRegistrationId("keycloak");
        return WebClient.builder()
                .filter(oauth)
                .build();
    }

But in my szenario it leads to an exception:

java.lang.IllegalArgumentException: serverWebExchange cannot be null
	at org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager.lambda$authorize$4(DefaultReactiveOAuth2AuthorizedClientManager.java:131) ~[spring-security-oauth2-client-5.3.1.RELEASE.jar:5.3.1.RELEASE]
	Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException: 
Error has been observed at the following site(s):
	|_ checkpoint ⇢ Request to GET https://abc.de/service/api/endpoint?x=0&y=0&z=0 [DefaultWebClient]
Stack trace:
		at org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager.lambda$authorize$4(DefaultReactiveOAuth2AuthorizedClientManager.java:131) ~[spring-security-oauth2-client-5.3.1.RELEASE.jar:5.3.1.RELEASE]
		at reactor.core.publisher.MonoErrorSupplied.subscribe(MonoErrorSupplied.java:70) ~[reactor-core-3.3.4.RELEASE.jar:3.3.4.RELEASE]
		at reactor.core.publisher.Mono.subscribe(Mono.java:4210) ~[reactor-core-
...

However, switching the ServerOAuth2AuthorizedClientRepository to a ReactiveOAuth2AuthorizedClientService makes the code run.

    @Bean
    WebClient webClient(ReactiveClientRegistrationRepository clientRegistrations, ReactiveOAuth2AuthorizedClientService authorizedClientService) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth = new ServerOAuth2AuthorizedClientExchangeFilterFunction(new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(clientRegistrations, authorizedClientService));
        oauth.setDefaultClientRegistrationId("keycloak");
        return WebClient.builder()
                .filter(oauth)
                .build();
    }
spring-security-config:5.3.1.RELEASE
spring-security-oauth2-client:5.3.1.RELEASE
spring-boot-starter-parent:2.2.6.RELEASE
spring-boot-starter-webflux:2.2.6.RELEASE

Is that an issue or am I handling something wrong? I am not sure if there is a correlation but, the working code example does not retrieve a new token, when Mono.retryWhen(...) is used.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:9 (4 by maintainers)

github_iconTop GitHub Comments

4reactions
jgrandjacommented, Apr 29, 2020

@fabian-froehlich @Avec112 The issue here is that the OAuth 2.0 Client Reactive documentation is out-of-date and missing quite a bit of content compared to the Servlet sections.

Take a look at the OAuth2AuthorizedClientManager / OAuth2AuthorizedClientProvider (Servlet) docs:

The DefaultOAuth2AuthorizedClientManager is designed to be used within the context of a HttpServletRequest. When operating outside of a HttpServletRequest context, use AuthorizedClientServiceOAuth2AuthorizedClientManager instead.

Since 5.2, it’s recommended to use the OAuth2AuthorizedClientManager constructor.

However, switching the ServerOAuth2AuthorizedClientRepository to a ReactiveOAuth2AuthorizedClientService makes the code run.

This makes sense, however, I would recommend using the ReactiveOAuth2AuthorizedClientManager constructor and pass in AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager.

We have #8174 logged to get the Reactive docs in sync with the Servlet docs.

I’ll close this issue as answered. If something is still not clear let me know and we’ll address it.

3reactions
jgrandjacommented, Apr 30, 2020

@fabian-froehlich

DefaultReactiveOAuth2AuthorizedClientManager is intended to be used within a request context.

Given that you’re seeing serverWebExchange cannot be null, you must be operating outside of a request context, which in case you should use AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager instead.

NOTE: Change the ServerOAuth2AuthorizedClientRepository parameter to ReactiveOAuth2AuthorizedClientService.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Consider defining a bean of type 'org.springframework ...
Note : ReactiveClientRegistrationRepository bean is created only when you configure the client with the OAuth2 application owner details.
Read more >
WebClient :: Spring Security
The first step is ensuring to setup the WebClient correctly. An example of setting up WebClient in a fully reactive environment can be...
Read more >
How to Use Client Credentials Flow with Spring Security
In the next part of the tutorial, you will implement the same OAuth 2.0 client credentials grant using Spring WebClient . If you...
Read more >
Vert.x Web Client
Web Client options inherit Http Client options so you can set any one of them. If your already have an HTTP Client in...
Read more >
Spring WebClient and OAuth2 Support - Baeldung
Learn how to set up an application as an OAuth2 Client and use the WebClient to retrieve a secured resource in a full-reactive...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found