Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is There an Easier Way to Load Spring OAuth Client Configuration

I'm working on a little proof of concept for a set of endpoints that need to be able to call each other passing tokens which are obtained via an OAuth 2 client credentials flow. I'm using Spring Boot and related projects to build these endpoints, and I'm confused as to why the framework appears to be very opinionated about the following code:

package com.example.client;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestOperations;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableOAuth2Client;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@Configuration
@EnableAutoConfiguration
@EnableOAuth2Client
@RestController
public class StuffClient {

    @Value("${security.oauth2.client.access-token-uri}")
    private String tokenUrl;

    @Value("${security.oauth2.client.id}")
    private String clientId;

    @Value("${security.oauth2.client.client-secret}")
    private String clientSecret;

    @Value("${security.oauth2.client.grant-type}")
    private String grantType;

    @Autowired
    private OAuth2RestOperations restTemplate;

    private String uri = "http://localhost:8082/stuff/";

    @RequestMapping(value = "/client/{stuffName}", method = RequestMethod.GET)
    public String client(@PathVariable("stuffName") String stuffName) {
        String request = uri + stuffName;
        return restTemplate.getForObject(request, String.class);
    }

    @Bean
    public OAuth2RestOperations restTemplate(OAuth2ClientContext clientContext) {
        return new OAuth2RestTemplate(resource(), clientContext);
    }

    @Bean
    protected OAuth2ProtectedResourceDetails resource() {
        ClientCredentialsResourceDetails resource = new ClientCredentialsResourceDetails();
        resource.setAccessTokenUri(tokenUrl);
        resource.setClientId(clientId);
        resource.setClientSecret(clientSecret);
        resource.setGrantType(grantType);
        return resource;
    }
}

And the accompanying configuration file:

server:
  port: 8081

security:
  basic:
    enabled: false
  oauth2:
    client:
      id: test-client
      client-secret: test-secret
      access-token-uri: http://localhost:8080/uaa/oauth/token
      grant-type: client_credentials

The above works exactly as expected. If I change security.oauth2.client.id to security.oauth2.client.client-id (in both the Java code and the YAML), I get a 500 error, the first line of which is:

org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException: Unable to obtain a new access token for resource 'null'. The provider manager is not configured to support it. 

The code also works fine if I hard code values for all of the instance variables. It seems to work fine, in fact, in every permutation of populating those instance variables except the one where I use @Value to populate clientId with the value of security.oauth2.client.client-id

So my main question is: is the framework actually opinionated in this very specific way? And if so, why? And, can I leverage this opinionated-ness to simplify my code?

like image 395
Shaun Avatar asked Mar 01 '16 00:03

Shaun


People also ask

How do I automatically request and refresh OAuth2 client credentials token in Spring?

Before making a request to the resource server, first check if the token has already expired or is about to expire. If so, request a new token. Finally, make the request to the resource server. Save the token and expiration time in memory, and have a timer which triggers a token refresh some interval before expiry.

Is Spring Security OAuth2 deprecated?

After project Spring Security OAuth has been deprecated, there was a lot of confusion in the community. You could use Spring Security to write the resource server but not the authorization server. But the dark age is now over.

Does spring boot support OAuth2?

Spring Security and Spring Boot permit to quickly set up a complete OAuth2 authorization/authentication server in an almost declarative manner. The setup can be further shortened by configuring OAuth2 client's properties directly from application. properties/yml file, as explained in this tutorial.


1 Answers

I am not sure which spring-boot version you are using. I am using spring-boot version 1.5.4.RELEASED and to simplify your codes,

you can inject OAuth2ProtectedResourceDetails like

@Autowired
private OAuth2ProtectedResourceDetails resource;

and create OAuth2RestTemplate as

@Bean
@Primary
public OAuth2RestOperations restTemplate(OAuth2ClientContext clientContext) {
    return new OAuth2RestTemplate(resource, clientContext);
}

sample yaml ..

### OAuth2 settings ### 
security:
  user:
    password: none
  oauth2:
    client:
      accessTokenUri: ${auth-server}/oauth/token
      userAuthorizationUri: ${auth-server}/oauth/authorize
      clientId: myclient
      clientSecret: secret
    resource:
      user-info-uri: ${auth-server}/sso/user
      jwt:
        keyValue: |
          -----BEGIN PUBLIC KEY-----
          your public key
          -----END PUBLIC KEY-----

And then,use restTemplate instance in controllers as

@Autowired
private OAuth2RestOperations restTemplate;

I hope some helps for you.

like image 89
Cataclysm Avatar answered Sep 19 '22 17:09

Cataclysm