Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use OAuth2RestTemplate?

I'm trying to understand how to use a OAuth2RestTemplate object to consume my OAuth2 secured REST service (which is running under a different project and let's assume also on a different server etc...)

An example of my REST service is:

http://localhost:8082/app/helloworld 

-> Accessing this URL generates an error as I am not authenticated

To request a token I would go to:

http://localhost:8082/app/oauth/token?grant_type=password&client_id=restapp&client_secret=restapp&username=**USERNAME**&password=**PASSWORD** 

After I receive the token I can then connect to the REST API by using the following URL (example token inserted)

http://localhost:8082/app/helloworld/?access_token=**4855f557-c6ee-43b7-8617-c24591965206** 

Now my question is how do I implement a second application which can consume this OAuth2 secured REST API? I really haven't found any working examples where you provide the user name and password (e.g. coming from a login form) and then a token is generated which can be re-used to get data from the REST API.

I currently tried something with the following objects:

BaseOAuth2ProtectedResourceDetails baseOAuth2ProtectedResourceDetails =  new BaseOAuth2ProtectedResourceDetails(); baseOAuth2ProtectedResourceDetails.setClientId("restapp"); baseOAuth2ProtectedResourceDetails.setClientSecret("restapp"); baseOAuth2ProtectedResourceDetails.setGrantType("password"); // how to set user name and password ???  DefaultAccessTokenRequest accessTokenRequest = new DefaultAccessTokenRequest(); OAuth2ClientContext oAuth2ClientContext = new DefaultOAuth2ClientContext(accessTokenRequest());  OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(baseOAuth2ProtectedResourceDetails,oAuth2ClientContext); 

But this just isn't working :(

Any ideas, links to working examples or tutorials are greatly appreciated.

like image 744
Joachim Seminck Avatar asked Jan 09 '15 15:01

Joachim Seminck


People also ask

Is oauth2resttemplate deprecated?

Deprecated. Strategy for extracting an Authorization header from an access token and the request details.

What is the difference between client credentials and authorization code?

Client Credentials Grant Type RolesApplication: A client that makes protected requests using the authorization of the resource owner. Authorization Server: The Single Sign‑On server that issues access tokens to client apps after successfully authenticating the resource owner.


2 Answers

You can find examples for writing OAuth clients here:

  • https://github.com/spring-projects/spring-security-oauth

In your case you can't just use default or base classes for everything, you have a multiple classes Implementing OAuth2ProtectedResourceDetails. The configuration depends of how you configured your OAuth service but assuming from your curl connections I would recommend:

@EnableOAuth2Client @Configuration class MyConfig{      @Value("${oauth.resource:http://localhost:8082}")     private String baseUrl;     @Value("${oauth.authorize:http://localhost:8082/oauth/authorize}")     private String authorizeUrl;     @Value("${oauth.token:http://localhost:8082/oauth/token}")     private String tokenUrl;      @Bean     protected OAuth2ProtectedResourceDetails resource() {         ResourceOwnerPasswordResourceDetails resource;         resource = new ResourceOwnerPasswordResourceDetails();          List scopes = new ArrayList<String>(2);         scopes.add("write");         scopes.add("read");         resource.setAccessTokenUri(tokenUrl);         resource.setClientId("restapp");         resource.setClientSecret("restapp");         resource.setGrantType("password");         resource.setScope(scopes);         resource.setUsername("**USERNAME**");         resource.setPassword("**PASSWORD**");         return resource;     }      @Bean     public OAuth2RestOperations restTemplate() {         AccessTokenRequest atr = new DefaultAccessTokenRequest();         return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(atr));     } }  @Service @SuppressWarnings("unchecked") class MyService {      @Autowired     private OAuth2RestOperations restTemplate;      public MyService() {         restTemplate.getAccessToken();     } } 

Do not forget about @EnableOAuth2Client on your config class, also I would suggest to try that the urls you are using are working with curl first, also try to trace it with the debugger because lot of exceptions are just consumed and never printed out due security reasons, so it gets little hard to find where the issue is. You should use logger with debug enabled set. Good luck

I uploaded sample springboot app on github https://github.com/mariubog/oauth-client-sample to depict your situation because I could not find any samples for your scenario .

like image 189
mariubog Avatar answered Sep 21 '22 18:09

mariubog


In the answer from @mariubog (https://stackoverflow.com/a/27882337/1279002) I was using password grant types too as in the example but needed to set the client authentication scheme to form. Scopes were not supported by the endpoint for password and there was no need to set the grant type as the ResourceOwnerPasswordResourceDetails object sets this itself in the constructor.

...

public ResourceOwnerPasswordResourceDetails() {     setGrantType("password"); } 

...

The key thing for me was the client_id and client_secret were not being added to the form object to post in the body if resource.setClientAuthenticationScheme(AuthenticationScheme.form); was not set.

See the switch in: org.springframework.security.oauth2.client.token.auth.DefaultClientAuthenticationHandler.authenticateTokenRequest()

Finally, when connecting to Salesforce endpoint the password token needed to be appended to the password.

@EnableOAuth2Client @Configuration class MyConfig {  @Value("${security.oauth2.client.access-token-uri}") private String tokenUrl;  @Value("${security.oauth2.client.client-id}") private String clientId;  @Value("${security.oauth2.client.client-secret}") private String clientSecret;  @Value("${security.oauth2.client.password-token}") private String passwordToken;  @Value("${security.user.name}") private String username;  @Value("${security.user.password}") private String password;   @Bean protected OAuth2ProtectedResourceDetails resource() {      ResourceOwnerPasswordResourceDetails resource = new ResourceOwnerPasswordResourceDetails();      resource.setAccessTokenUri(tokenUrl);     resource.setClientId(clientId);     resource.setClientSecret(clientSecret);     resource.setClientAuthenticationScheme(AuthenticationScheme.form);     resource.setUsername(username);     resource.setPassword(password + passwordToken);      return resource; }  @Bean  public OAuth2RestOperations restTemplate() {     return new OAuth2RestTemplate(resource(), new DefaultOAuth2ClientContext(new DefaultAccessTokenRequest()));     } }   @Service @SuppressWarnings("unchecked") class MyService {     @Autowired     private OAuth2RestOperations restTemplate;      public MyService() {         restTemplate.getAccessToken();     } } 
like image 45
theINtoy Avatar answered Sep 18 '22 18:09

theINtoy