OAuth2, Ресурс Access / oauth2 / token за прокси - PullRequest
0 голосов
/ 27 февраля 2020

Мне нужно использовать API, защищенный OAuth2 с WebClient. Я настроил OAuth2AuthorizedClientManager для управления токеном доступа и обновил sh, когда это необходимо.

Однако я столкнулся с некоторой проблемой, java.net.UnknownHostException. Между моим Приложением и ресурсом токена OAuth2 имеется прокси-сервер, и я не знаю, как его настроить.

Что я пробовал:

  • Проверьте его в другой среде без прокси и это работа. Моя OAuth2AuthorizedClientManager конфигурация правильная.
  • System.setProperty(), не решение, у меня есть несколько прокси для управления.

возможно, я неправильно понимаю некоторые понятия OAuth2

Вот код:

application.properties

spring.security.oauth2.client.registration.client.client-id=clientId
spring.security.oauth2.client.registration.client.authorization-grant-type=client_credentials
spring.security.oauth2.client.registration.client.client-secret=clientSecret
spring.security.oauth2.client.provider.client.token-uri=URI/oauth2/token

WebClientConfig

    @Bean
    public OAuth2AuthorizedClientManager authorizedClientManager(
            ClientRegistrationRepository clientRegistrationRepository,
            OAuth2AuthorizedClientService clientService)
    {

        OAuth2AuthorizedClientProvider authorizedClientProvider = 
            OAuth2AuthorizedClientProviderBuilder.builder()
                .clientCredentials()
                .build();

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

        return authorizedClientManager;
    }

    @Bean
    WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
        ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
                new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
        oauth2Client.setDefaultClientRegistrationId("client");
        return WebClient.builder()
                .baseUrl("URI")
                .clientConnector(getReactorClientHttpConnector(url))
                .apply(oauth2Client.oauth2Configuration())
                .build();
    }

Мой тест

    @Autowired
    WebClient webClient;

    public void test() {
        RequestHeadersSpec<?> request = webClient.get()
                .uri("/heartbeats");
    }

Ошибка

org.springframework.security.oauth2.core.OAuth2AuthorizationException: [invalid_token_response] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: I/O error on POST request for "URI/oauth2/token": URI; nested exception is java.net.UnknownHostException: URI

У меня вопрос Как настроить прокси для OAuth2AuthorizedClientManager?

Пожалуйста, не стесняйтесь просить разъяснений.

Любая помощь будет оценена. Спасибо

1 Ответ

0 голосов
/ 27 марта 2020

В прошлом у нас была похожая проблема, и мы решили ее с помощью следующей конфигурации.

@Configuration
public class AuthConfiguration {

    @Bean
    public JwtDecoderFactory<ClientRegistration> jwtDecoderFactory() {
        return new CustomOidcIdTokenDecoderFactory(jwksRestTemplate());
    }

    @Bean
    public DefaultAuthorizationCodeTokenResponseClient oAuth2AccessTokenResponseClient() {
        var defaultAuthorizationCodeTokenResponseClient = new DefaultAuthorizationCodeTokenResponseClient();
        defaultAuthorizationCodeTokenResponseClient.setRestOperations(tokenRestTemplate());
        return defaultAuthorizationCodeTokenResponseClient;
    }

    @Bean
    public RestTemplate jwksRestTemplate() {
        return new RestTemplate(requestFactory());
    }

    @Bean
    public RestTemplate tokenRestTemplate() {
        // Copied from constructor of  DefaultAuthorizationCodeTokenResponseClient
        var restTemplate = new RestTemplate(Arrays.asList(
            new FormHttpMessageConverter(), new OAuth2AccessTokenResponseHttpMessageConverter()));
        restTemplate.setErrorHandler(new OAuth2ErrorResponseErrorHandler());
        restTemplate.setRequestFactory(requestFactory());
        return restTemplate;
    }

    private ClientHttpRequestFactory requestFactory() {
        var requestFactory = new SimpleClientHttpRequestFactory();

        var proxy = new Proxy(Type.HTTP, new InetSocketAddress("my.host.com", 8080));
        requestFactory.setProxy(proxy);

        return requestFactory;
    }
}

Может быть, это поможет. Также необходимо добавить следующий класс, потому что это закрытый пакет в Spring;)

package org.springframework.security.oauth2.client.oidc.authentication;

import org.springframework.core.convert.converter.Converter;
import org.springframework.security.oauth2.client.oidc.authentication.DefaultOidcIdTokenValidatorFactory;
import org.springframework.security.oauth2.client.oidc.authentication.OidcIdTokenDecoderFactory;
import org.springframework.security.oauth2.client.registration.ClientRegistration;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.core.OAuth2Error;
import org.springframework.security.oauth2.core.OAuth2TokenValidator;
import org.springframework.security.oauth2.core.converter.ClaimTypeConverter;
import org.springframework.security.oauth2.jose.jws.JwsAlgorithm;
import org.springframework.security.oauth2.jose.jws.SignatureAlgorithm;
import org.springframework.security.oauth2.jwt.Jwt;
import org.springframework.security.oauth2.jwt.JwtDecoder;
import org.springframework.security.oauth2.jwt.JwtDecoderFactory;
import org.springframework.security.oauth2.jwt.NimbusJwtDecoder;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.Map;
import java.util.function.Function;

import static org.springframework.security.oauth2.jwt.NimbusJwtDecoder.withJwkSetUri;

/**
 * extension for {@link OidcIdTokenDecoderFactory} to mock the JWKS request
 */
public class CustomOidcIdTokenDecoderFactory implements JwtDecoderFactory<ClientRegistration> {
    private static final String MISSING_SIGNATURE_VERIFIER_ERROR_CODE = "missing_signature_verifier";
    private static final Converter<Map<String, Object>, Map<String, Object>> DEFAULT_CLAIM_TYPE_CONVERTER =
            new ClaimTypeConverter(OidcIdTokenDecoderFactory.createDefaultClaimTypeConverters());
    private Function<ClientRegistration, JwsAlgorithm> jwsAlgorithmResolver = clientRegistration -> SignatureAlgorithm.RS256;
    private Function<ClientRegistration, OAuth2TokenValidator<Jwt>> jwtValidatorFactory = new DefaultOidcIdTokenValidatorFactory();
    private Function<ClientRegistration, Converter<Map<String, Object>, Map<String, Object>>> claimTypeConverterFactory =
            clientRegistration -> DEFAULT_CLAIM_TYPE_CONVERTER;
    private final RestTemplate restTemplate;

    public CustomOidcIdTokenDecoderFactory(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    @Override
    public JwtDecoder createDecoder(ClientRegistration clientRegistration) {
        NimbusJwtDecoder jwtDecoder = buildDecoder(clientRegistration);
        jwtDecoder.setJwtValidator(this.jwtValidatorFactory.apply(clientRegistration));
        Converter<Map<String, Object>, Map<String, Object>> claimTypeConverter =
                this.claimTypeConverterFactory.apply(clientRegistration);
        if (claimTypeConverter != null) {
            jwtDecoder.setClaimSetConverter(claimTypeConverter);
        }
        return jwtDecoder;
    }

    private NimbusJwtDecoder buildDecoder(ClientRegistration clientRegistration) {
        JwsAlgorithm jwsAlgorithm = this.jwsAlgorithmResolver.apply(clientRegistration);
        String jwkSetUri = clientRegistration.getProviderDetails().getJwkSetUri();
        if (!StringUtils.hasText(jwkSetUri)) {
            OAuth2Error oauth2Error = new OAuth2Error(
                    MISSING_SIGNATURE_VERIFIER_ERROR_CODE,
                    "Failed to find a Signature Verifier for Client Registration: '" +
                            clientRegistration.getRegistrationId() +
                            "'. Check to ensure you have configured the JwkSet URI.",
                    null
            );
            throw new OAuth2AuthenticationException(oauth2Error, oauth2Error.toString());
        }
        return withJwkSetUri(jwkSetUri).jwsAlgorithm((SignatureAlgorithm) jwsAlgorithm).restOperations(restTemplate).build();
    }
}
...