Поддерживается ли Spring Boot WebClient OAuth2 client_credentials? - PullRequest
0 голосов
/ 28 апреля 2019

Я пытаюсь создать приложение REST Spring Boot, которое должно выполнить удаленный вызов REST другому приложению Spring Boot, защищенному OAuth2 (с типом предоставления client_credentials).

Первое приложение использует Reactive WebClient для вызова второго приложения OAuth2 REST.

Я настроил WebClient с помощью grant_type "client_credentials" (см. Код ниже)

public WebClient messageWebClient(
        ClientRegistrationRepository clientRegistrations,
        OAuth2AuthorizedClientRepository authorizedClients,
        ClientHttpConnector clientHttpConnector
) {

    ServletOAuth2AuthorizedClientExchangeFilterFunction oauth =
            new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);

    oauth.setDefaultClientRegistrationId("message");

    return WebClient.builder()
            .baseUrl(MESSAGE_BASE_URL)
            .clientConnector(clientHttpConnector)
            .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
            .defaultHeader(HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
            .filter(oauth)
            .filter(logRequest())
            .build();
}

@Bean
public ClientRegistrationRepository  clientRegistrations() {
    ClientRegistration clientRegistration = ClientRegistration
            .withRegistrationId("message")
            .clientId("client")
            .clientSecret("secret")
            .authorizationGrantType(AuthorizationGrantType.CLIENT_CREDENTIALS)
            .tokenUri("http://localhost:8081/oauth/token")
            .build();

    return new InMemoryClientRegistrationRepository(clientRegistration);
}

Но каждый раз, когда я звоню почтальону первому приложению, я получаю следующее исключение:

"IllegalArgumentException: недопустимый тип разрешения авторизации (client_credentials) для регистрации клиента с идентификатором: ..." из DefaultOAuth2AuthorizationRequestResolver

enter image description here

Действительно ли "client_credentials" поддерживается для WebClient ... или я что-то упустил?

Привет

Ответы [ 2 ]

1 голос
/ 10 мая 2019

Ну, наконец-то я смог заставить свой код работать.

... и да, WebClient поддерживает OAuth2 с client_credential (ну частично).

Чтобы решить мои проблемы Мне пришлось отключить автоматическую настройку oauth2 и создать собственную реализацию WebSecurityConfigurerAdapter .

Причина, по которой я говорю «частично», заключается в том, что текущая версия Spring Security (5.1.x) для WebClient не запрашивает новый токен по истечении срока действия токена (для учетных данных клиента). Только с версией 5.2.0.M2 или (M1) он запрашивает новый токен, когда токен истек.

Спасибо:)

0 голосов
/ 30 апреля 2019

Вы должны использовать .apply(oauth.oauth2Configuration()) вместо .filter(oauth), см. ServletOAuth2AuthorizedClientExchangeFilterFunction:

Предоставляет простой механизм использования OAuth2AuthorizedClient для выполнения запросов OAuth2включив токен как токен на предъявителя.Он также предоставляет механизмы для поиска OAuth2AuthorizedClient.Этот класс предназначен для использования в среде сервлетов.Пример использования:

OAuth2AuthorizedClientExchangeFilterFunction oauth2 = new OAuth2AuthorizedClientExchangeFilterFunction(authorizedClientService);
WebClient webClient = WebClient.builder()
    .apply(oauth2.oauth2Configuration())
    .build();
Mono response = webClient
    .get()
    .uri(uri)
    .attributes(oauth2AuthorizedClient(authorizedClient))
    // ...
    .retrieve()
    .bodyToMono(String.class);

и Справочник по безопасности Spring :

13.1 Настройка OAuth2 WebClient

Первый шаг - обеспечение правильной настройки WebClient.Пример настройки WebClient в среде сервлета можно найти ниже:

@Bean
WebClient webClient(ClientRegistrationRepository clientRegistrations,
        OAuth2AuthorizedClientRepository authorizedClients) {
    ServletOAuth2AuthorizedClientExchangeFilterFunction oauth =
            new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations, authorizedClients);
    // (optional) explicitly opt into using the oauth2Login to provide an access token implicitly
    // oauth.setDefaultOAuth2AuthorizedClient(true);
    // (optional) set a default ClientRegistration.registrationId
    // oauth.setDefaultClientRegistrationId("client-registration-id");
    return WebClient.builder()
            .apply(oauth2.oauth2Configuration())
            .build();
}
...