Search code examples
springsecurityproxysocketexception

A connection attempt failed because the connected party did not properly respond after a period of time - spring security, webclient


I have a Java Spring service and I'm migrating a RestTemplate to a WebClient and spotted a problem with proxy (that's my guess).

Whole configuration is described here under my previous question here: Add additional parameter to the spring security oauth token request but I will copy paste it here again:

Project details:
spring-boot- 3.0.X

This is request required by customclient to get the token:

uri: xxxxxxx/token

{
    "grant_type": "client_credentials",
    "client_id": "xxxx",
    "client_secret": "xxxxxxxx",
    "account_id": "123456789"
}

application.yml

  security:
    oauth2:
      client:
        registration:
          custom-client:
            provider: custom-client
            client-id: xxxxxxxxxxxxxxx
            client-secret: xxxxxxxxxxxxxxx
            authorization-grant-type: client_credentials
            client-authentication-method: post
        provider:
          custom-client:
            token-uri: xxxxxxxxxxxxxxxxxxxxxxxxxx/token

WebClientConfig.java

@Configuration
@Getter
@Setter
public class WebClientConfig {

    @Bean
    public OAuth2AuthorizedClientManager webclientManager(ClientRegistrationRepository clientRegistrationRepository,
                                                           OAuth2AuthorizedClientService authorizedClientService) {
        OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
                .clientCredentials()
                .build();

        AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
                new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }

    @Bean
    public WebClient customWebClient(@Qualifier("webclientManager") OAuth2AuthorizedClientManager authorizedClientManager) {
        ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Filer = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        oAuth2Filer.setDefaultClientRegistrationId("customclient");
        return WebClient.builder()
                .filter(oAuth2Filer)
                .baseUrl(apiUrl)
                .build();
    }

}

This is an example service where I would like to use webClient to make some REST call:

MyService.java

@Service
public class MyService{

    WebClient webClient;

    public MyService(@Qualifier("customClient") WebClient webClient) {
        this.webClient = webClient;
    }

    public String testRequest() {
        return webClient.get()
                .uri("xxxxxx")
                .retrieve()
                .bodyToMono(String.class)
                .block();
    }
}

When I'm trying to test my code and make some REST call to other system using WebClient, I'm receiving following response:

"[invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: I/O error on POST request for "https:/xxxxxxxxxxxxxx/oauth2/token": A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond; nested exception is java.net.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond"

I think it can be a problem with proxy and I've tried add something like this:

@Configuration
@Getter
@Setter
public class WebClientConfig {

    @Bean
    public OAuth2AuthorizedClientManager webclientManager(ClientRegistrationRepository clientRegistrationRepository,
                                                           OAuth2AuthorizedClientService authorizedClientService) {
        OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
                .clientCredentials()
                .build();

        AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
                new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }

    @Bean
    public WebClient customWebClient(@Qualifier("webclientManager") OAuth2AuthorizedClientManager authorizedClientManager,
final @Value("${proxy.url}" String proxyUrl,
final @Value("${proxy.port}" String proxyPort,
final @Value("${proxy.username}" String proxyUsername,
final @Value("${proxy.password}" String proxyPassword) {

        ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Filer = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        oAuth2Filer.setDefaultClientRegistrationId("customclient");

        Function<String, String> httpsProxyPassword = username -> proxyPassword;

        HttpClient client = HttpClient.create()
            .proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP)
                .host(proxyUrl)
                .port(proxyPort)
                .password(httpsProxyPassword)
                .username(proxyUsername));

        return WebClient.builder()
            .clientConnector(new ReactorClientHttpConnector(client))
                .filter(oAuth2Filer)
                .baseUrl(apiUrl)
                .build();
    }

}

But the repsonse is still the same.


Solution

  • After spending few hours debugging and trying multiple way, It turned out to be a problem with token request itself, which has to have proxy configured separately (in addition to the resource proxy config done within .clientConnector()) .

    Examples here:

    WebClient proxy configuration not working with oAuth2

    https://blog.doubleslash.de/spring-oauth2-client-authorization-request-proxy-support