Spring Boot 2 Spring-Security 5 Поддержка OAuth2 для client_credentials grant_type - PullRequest
2 голосов
/ 11 февраля 2020

У меня есть приложение Spring Boot 2, использующее OIDC / OAuth2 для аутентификации и авторизации.

Цель состоит в том, чтобы GUI перенаправить пользователя на сервер авторизации для входа через тип разрешения authorization_code.

Кроме того, приложение предлагает веб-службы REST для других серверных приложений. Связь между серверами должна быть защищена типом предоставления client_credentials с того же сервера авторизации.

Приложению также требуется доступ к веб-службам REST из других серверных приложений без взаимодействия с пользователем, и поэтому требуется токен с типом гранта client_credentials.

Теперь мне требуется токен-носитель в моем приложении, чтобы доступ к другим серверам веб-сервисов. В настоящее время я получаю его с помощью RestTemplate, отправляя HTTP-запрос:

 private OAuth2AccessToken getBearerToken(ClientRegistration clientRegistration){
    String tokenUri = clientRegistration.getProviderDetails().getTokenUri();

    MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
    map.add("grant_type", clientRegistration.getAuthorizationGrantType().getValue());
    map.add("client_id",clientRegistration.getClientId());
    map.add("client_secret",clientRegistration.getClientSecret());

    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

    HttpEntity<MultiValueMap<String, String>> entity = new HttpEntity<>(map, headers);

    ResponseEntity<DefaultOAuth2AccessToken> exchange = restTemplate.exchange(tokenUri, HttpMethod.POST, entity, DefaultOAuth2AccessToken.class);
    LOGGER.info(exchange.getBody().getValue());
    return exchange.getBody();
}

Теперь я определил несколько клиентов OAuth2 с различными типами грантов в application.yml, и я получил client_credentials ClientRegistration из ClientRegistrationRepository. Но есть ли способ использовать функциональность Spring-Security 5 OAuth2 Client для получения токена-носителя для меня?

Я пытался сделать следующее:

 ClientRegistration adfsclient = clientRegistrationRepository.findByRegistrationId("client_credentials");
    OAuth2AuthorizationContext.Builder builder = OAuth2AuthorizationContext.withClientRegistration(adfsclient);
    OAuth2AuthorizationContext build = builder.build();
    OAuth2AuthorizedClient authorize = clientProvider.authorize(build);

Но я получаю:

java.lang.IllegalArgumentException: principal cannot be null
at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.2.3.RELEASE.jar:5.2.3.RELEASE]
at org.springframework.security.oauth2.client.OAuth2AuthorizationContext$Builder.build(OAuth2AuthorizationContext.java:199) ~[spring-security-oauth2-client-5.2.1.RELEASE.jar:na]
at my.test.sso.adfs.WebAPICaller.callURI(WebAPICaller.java:36) ~[classes/:na]
....
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]

Но у меня нет принципала, и на самом деле он мне не нужен. Есть ли другой способ, как я могу использовать Spring Security OAuth2 Client, чтобы получить мне токен на предъявителя?

Thx, Pero

1 Ответ

0 голосов
/ 20 февраля 2020

Я узнал, что OAuth2RestTemplate делает именно то, что мне нужно.

    @Bean()
    @ConfigurationProperties(prefix ="spring.security.oauth2.client.registration.adfs")
    protected ClientCredentialsResourceDetails oAuthDetails() {
        return new ClientCredentialsResourceDetails();
    }



    @Bean
    public OAuth2RestTemplate oAuth2RestTemplate(ClientCredentialsResourceDetails oAuthDetails){
        return new OAuth2RestTemplate(oAuthDetails);
    }

И, наконец, позвонил:

    OAuth2AccessToken accessToken = oAuth2RestTemplate.getAccessToken();

, что мне нужно.

Это Можно даже использовать экземпляр WebClient для получения токена, как описано здесь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...