10

I have tried to set network proxy in the following ways, but none of the method is working

1: set jvm variables like -Dhttp.proxyHost= -Dhttp.proxyPort= .......
2: Created the Bean.

@Bean
public RestTemplate restTemplate() {
    final String proxyHost = "######"; // host
    final int proxyPort = ####;  // port
    SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
    factory.setProxy(new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)));
    return new RestTemplate(factory);
}

But this configuration is overridden by OAuth2AccessTokenSupport.restTemplate.

So the below method always returns the newly created rest template object.

org.springframework.security.oauth2.client.token.OAuth2AccessTokenSupport

protected RestOperations getRestTemplate() {
    if (restTemplate == null) {
        synchronized (this) {
            if (restTemplate == null) {
                RestTemplate restTemplate = new RestTemplate();
                restTemplate.setErrorHandler(getResponseErrorHandler());
                restTemplate.setRequestFactory(requestFactory);
                restTemplate.setInterceptors(interceptors);
                this.restTemplate = restTemplate;
            }
        }
    }
    if (messageConverters == null) {
        setMessageConverters(new RestTemplate().getMessageConverters());
    }
    return restTemplate;
}

Kindly help me to override or set proxy on the rest template from OAuth Client application.

Karthikeyan
  • 748
  • 1
  • 8
  • 13

5 Answers5

8

Another way to do this is by setting a custom AccessTokenProvider to your OAuth2RestTemplate. In the code sample below the SSL validation is bypassed :

@Configuration
public class ConfigLocal {

    @Value("${https.proxyHost}")
    private String proxyHost;

    @Value("${https.proxyPort}")
    private Integer proxyPort;

    @Value("${https.proxyUser}")
    private String proxyUser;

    @Value("${https.proxyPassword}")
    private String proxyPassword;

    @Bean
    public OAuth2RestTemplate oauth2RestTemplate(ClientCredentialsResourceDetails clientCredentialsResourceDetails)
            throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException {
        OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(clientCredentialsResourceDetails);

        // Instanciate a new http client with proxy configuration, and bypass SSL Certificate verification
        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxyUser, proxyPassword));

        HttpClientBuilder httpClientBuilder =
                HttpClients.custom()
                        .setProxy(new HttpHost(proxyHost, proxyPort))
                        .setDefaultCredentialsProvider(credentialsProvider)
                        .setSSLHostnameVerifier(new NoopHostnameVerifier())
                            .setSSLContext(new SSLContextBuilder().loadTrustMaterial(null, (x509Certificates, s) -> true)
                                    .build());

        // requestFactory
        HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClientBuilder.build());
        ClientCredentialsAccessTokenProvider clientCredentialsAccessTokenProvider = new ClientCredentialsAccessTokenProvider();
        clientCredentialsAccessTokenProvider.setRequestFactory(requestFactory);

        // accessTokenProvider
        AccessTokenProvider accessTokenProvider = new AccessTokenProviderChain(Arrays.<AccessTokenProvider> asList(
                new AuthorizationCodeAccessTokenProvider(), new ImplicitAccessTokenProvider(),
                new ResourceOwnerPasswordAccessTokenProvider(), clientCredentialsAccessTokenProvider));

        restTemplate.setAccessTokenProvider(accessTokenProvider);

        return restTemplate;
    }
}
Will
  • 91
  • 1
  • 6
2

This seems to be a cleaner solution:

In a class with @Configuration add this:

@Bean
public CustomUserInfoRestTemplateCustomizer customUserInfoRestTemplateCustomizer() {
    return new CustomUserInfoRestTemplateCustomizer();
}

/**
 * Customize the UserInfoRestTemplateCustomizer used by OAuthRestTemplate
 * 
 */
private static class CustomUserInfoRestTemplateCustomizer implements UserInfoRestTemplateCustomizer {
    @Value("${http.custom.connect-timeout:500}")
    private int connectTimeout;

    @Value("${http.custom.read-timeout:30000}")
    private int readTimeout;

    @Value("${http.custom.proxy-host:}")
    private String proxyHost;

    @Value("${http.custom.proxy-port:-1}")
    private int proxyPort;

    @Override
    public void customize(OAuth2RestTemplate template) {
        template.setRequestFactory(new ClientHttpRequestFactory() {
            @Override
            public ClientHttpRequest createRequest(URI uri, HttpMethod httpMethod) throws IOException {
                SimpleClientHttpRequestFactory clientHttpRequestFactory = new SimpleClientHttpRequestFactory();
                clientHttpRequestFactory.setConnectTimeout(connectTimeout);
                clientHttpRequestFactory.setReadTimeout(readTimeout);
                if (StringUtils.isNoneEmpty(proxyHost)) {
                    Proxy proxy = new Proxy(Type.HTTP, new InetSocketAddress(proxyHost, proxyPort));
                    clientHttpRequestFactory.setProxy(proxy);
                }
                return clientHttpRequestFactory.createRequest(uri, httpMethod);
            }
        });
    }
}
UBIK LOAD PACK
  • 33,980
  • 5
  • 71
  • 116
1

This might not be a simple solution. But finally managed to set the proxy on oauth request by the below code.

Register the filter

@Override
protected void configure(HttpSecurity http) throws Exception {
    // @formatter:off
    http.antMatcher("/**")
    .authorizeRequests().antMatchers("/webjars/**", "/scripts/**", "/styles/**", "/instances/**", "/#/invalid").permitAll()
    .anyRequest().authenticated()
    .and().csrf().csrfTokenRepository(csrfTokenRepository())
    .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
    .addFilterBefore(oauthFilter(), BasicAuthenticationFilter.class);
    // @formatter:on
    super.configure(http);
}

Auth filter

@Autowired
OAuth2ClientContext oauth2ClientContext;

@Autowired
OAuth2ProtectedResourceDetails resource;

@Autowired
ResourceServerProperties resourceServer;

@Autowired
RequestHelper requestHelper;

private Filter oauthFilter() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
    OAuth2ClientAuthenticationProcessingFilter oauthFilter = new OAuth2ClientAuthenticationProcessingFilter("/login");
    OAuth2RestTemplate oauthTemplate = new OAuth2RestTemplate(resource, oauth2ClientContext);
    OAuth2AccessTokenSupport authAccessProvider = new AuthorizationCodeAccessTokenProvider();
    // Set request factory for '/oauth/token'
    authAccessProvider.setRequestFactory(requestHelper.getRequestFactory());
    AccessTokenProvider accessTokenProvider = new AccessTokenProviderChain(Arrays.<AccessTokenProvider> asList(
            (AuthorizationCodeAccessTokenProvider)authAccessProvider));
    oauthTemplate.setAccessTokenProvider(accessTokenProvider);
    // Set request factory for '/userinfo'
    oauthTemplate.setRequestFactory(requestHelper.getRequestFactory());
    oauthFilter.setRestTemplate(oauthTemplate);
    UserInfoTokenServices userInfoTokenService = new UserInfoTokenServices(resourceServer.getUserInfoUri(), resource.getClientId());
    userInfoTokenService.setRestTemplate(oauthTemplate);
    oauthFilter.setTokenServices(userInfoTokenService);
    return oauthFilter;
}

Request helper code

@Configuration
public class RequestHelper {

  @Value("${proxy.hostname}")
  private String proxyHost;

  @Value("${proxy.port}")
  private int proxyPort;

  @Value("${proxy.username}")
  private String proxyUser;

  @Value("${proxy.password}")
  private String proxyPassword;

  @Value("${useProxy}")
  private boolean useProxyFlag;

  @Value("${skipSslValidation}")
  private Boolean skipSslValidationFlag;

  public HttpComponentsClientHttpRequestFactory getRequestFactory() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {

      HttpClientBuilder httpClientBuilder = HttpClients.custom();

      // Skip SSL validation based on condition
      if (skipSslValidationFlag) {
          TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

          SSLContext sslContext = org.apache.http.ssl.SSLContexts.custom()
                  .loadTrustMaterial(null, acceptingTrustStrategy)
                  .build();
          SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

          httpClientBuilder = httpClientBuilder.setSSLSocketFactory(csf);
      }

      // Set proxy based on condition
      if (useProxyFlag) {
          CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
          credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(proxyUser, proxyPassword));
          httpClientBuilder = httpClientBuilder.setProxy(new HttpHost(proxyHost, proxyPort));
          httpClientBuilder = httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
      }

      CloseableHttpClient httpClient = httpClientBuilder.build();
      HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory();
      requestFactory.setHttpClient(httpClient);
      return requestFactory;
  }
}
Karthikeyan
  • 748
  • 1
  • 8
  • 13
1

The accepted answer worked for me, but here's a simpler version of the sample code, so you can inject an OAuth2RestTemplate for whatever reasons you may have (in my case, I just wanted to do some additional, custom logging):

@Autowired OAuth2ClientContext oauth2ClientContext;
@Autowired OAuth2ProtectedResourceDetails resource;

private Filter oAuth2ClientAuthenticationProcessingFilter() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
    OAuth2ClientAuthenticationProcessingFilter oauthFilter = new OAuth2ClientAuthenticationProcessingFilter("/login");
    OAuth2RestTemplate oauthTemplate = new LoggingOAuth2RestTemplate(resource, oauth2ClientContext);
    oauthFilter.setRestTemplate(oauthTemplate);
    return oauthFilter;
}

Then add it:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
        // ... your other config here ...
        .addFilterBefore(oAuth2ClientAuthenticationProcessingFilter(), BasicAuthenticationFilter.class);
}
Todd
  • 99
  • 1
  • 4
0

In case anyone lands here from Google...

We had the same issue as described. Spent days trying to fix it including trying the posts, above. We fixed it by setting the JVM proxy args without the protocol!

Incorrect: -Dhttp.proxyHost=http://some.host

Correct: -Dhttp.proxyHost=some.host

SamJB
  • 104
  • 3