Search code examples
spring-securityspring-webfluxspring-oauth2

Webflux - Spring Boot - oAuth2 client with http proxy support


I'm struggeling to correctly setup the webflux-weblient with oauth2 behind a proxy.

It seems, that the ServerOAuth2AuthorizedClientExchangeFilterFunction uses a new instance of a webclient , which doesn't contain my proxy-configuration.

OAuth2-Config

    ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2ClientFilter = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
      clientRegistrations,
      new UnAuthenticatedServerOAuth2AuthorizedClientRepository());
   oauth2ClientFilter.setDefaultClientRegistrationId("azure");

OAuth2AuthorizedClientResolver.class contains:

private ReactiveOAuth2AccessTokenResponseClient<OAuth2ClientCredentialsGrantRequest> clientCredentialsTokenResponseClient = new WebClientReactiveClientCredentialsTokenResponseClient();

The WebClientReactiveClientCredentialsTokenResponseClient.java creates a new webclient as follows:

private WebClient webClient = WebClient.builder().build();

Does anybody have a sample how to correctly setup a http-proxy for the oauth2 client?


Solution

  • Thanks to the incomplete answer of @abhinaba-chakraborty, I managed to set proxy based on the JVM params inside the WebClient for WebClientReactiveClientCredentialsTokenResponseClient.

    Here is my pieces of code to help other people with the same issue :

    This is a helper function to take the JVM params and set them to the HttpClient

        public HttpClient proxyHttpClient() {
            String proxyHost = System.getProperty("https.proxyHost");
            String proxyPort = System.getProperty("https.proxyPort");
    
            if (proxyHost == null && proxyPort == null) {
                return HttpClient.create();
            }
    
            return HttpClient.create()
                    .tcpConfiguration(tcpClient ->
                            tcpClient.proxy(proxy ->
                                    proxy.type(ProxyProvider.Proxy.HTTP).host(proxyHost).port(Integer.valueOf(proxyPort))
                            )
                    );
        }
    
    

    This is how to configure the OAuth2Client for the WebClient used for calling outside systems (based on the response of @abhinaba-chakraborty). Note the function named configureHttpProxy:

        @Bean
        public ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
                ReactiveClientRegistrationRepository clientRegistrationRepository,
                ReactiveOAuth2AuthorizedClientService authorizedClientService) {
    
            return configureHttpProxy(
                    new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                            clientRegistrationRepository,
                            authorizedClientService
                    )
            );
        }
    
        @Bean
        WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
            ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Client = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
            oauth2Client.setDefaultClientRegistrationId("registration_id");
            return WebClient.builder()
                    .filter(oauth2Client)
                    .clientConnector(new ReactorClientHttpConnector(HttpClient.create().wiretap(true)))
                    .baseUrl(rdoWebClientProperties.getBaseUrl())
                    .defaultHeader(rdoWebClientProperties.getApikeyName(), rdoWebClientProperties.getApikeyValue())
                    .build();
        }
    

    And here is the configureHttpProxy function:

        private AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager configureHttpProxy(AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
            // set the webclient with proxy configuration in the ReactiveOAuth2AccessTokenResponseClient
            WebClientReactiveClientCredentialsTokenResponseClient tokenResponseClient = new WebClientReactiveClientCredentialsTokenResponseClient();
            tokenResponseClient.setWebClient(
                    WebClient.builder()
                            .clientConnector(new ReactorClientHttpConnector(proxyHttpClient()))
                            .build()
            );
    
            // set the ReactiveOAuth2AccessTokenResponseClient with webclient configuration in the ReactiveOAuth2AuthorizedClientProvider
            ClientCredentialsReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = new ClientCredentialsReactiveOAuth2AuthorizedClientProvider();
            authorizedClientProvider.setAccessTokenResponseClient(tokenResponseClient);
    
            // set the ReactiveOAuth2AuthorizedClientProvider in the ReactiveOAuth2AuthorizedClientManager
            authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
    
            return authorizedClientManager;
        }
    

    Hoping this will help.