Search code examples
springspring-securityproxyspring-bootspring-security-oauth2

How to set proxy on spring oauth2 OAuth2AccessToken request or How to override OAuth2AccessTokenSupport restTemplate variable?


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.


Solution

  • 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;
      }
    }