简体   繁体   中英

Spring Boot 2 Spring-Security 5 OAuth2 support for client_credentials grant_type

I have a Spring Boot 2 App using OIDC/OAuth2 for authentication and authorization.

The goal is to have a GUI where a user is redirected to an authorization server in order to log in via the authorization_code grant type.

Additionally, the app offers REST web services for other server apps. The server-to-server communication should be secured by the client_credentials grant type from the same authorization server.

The app also needs to access REST web services from other server apps without user interaction and therefore requires a token with client_credentials grant type.

Now I require a bearer token in my app in order to access other servers web services. Currently, I retrieve it with RestTemplate by sending an HTTP request:

 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();
}

Now I have defined multiple OAuth2 clients with different grant types in application.yml and I get the client_credentials ClientRegistration from the ClientRegistrationRepository. But is there a way to utilize Spring-Security 5 OAuth2 Client functionality to retrieve the bearer token for me?

I was trying the following:

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

But I am getting:

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]

But I do not have a Principal and actually I do not need one. Is there another way how I can utilize the Spring Security OAuth2 Client to get me the bearer token?

Thx, Pero

I found out that the OAuth2RestTemplate is doing exactly what I needed.

    @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);
    }

And eventually by calling:

    OAuth2AccessToken accessToken = oAuth2RestTemplate.getAccessToken();

which I needed.

It is even possible to use a WebClient instance to fetch the token as described here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM