Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 712
Karthikeyan Avatar asked Jun 16 '16 08:06

Karthikeyan


3 Answers

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;
    }
}
like image 118
Will Avatar answered Oct 16 '22 16:10

Will


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);
            }
        });
    }
}
like image 25
UBIK LOAD PACK Avatar answered Oct 16 '22 16:10

UBIK LOAD PACK


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;
  }
}
like image 36
Karthikeyan Avatar answered Oct 16 '22 15:10

Karthikeyan