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.
Deprecated. Strategy for extracting an Authorization header from an access token and the request details.
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.
You can find examples for writing OAuth clients here:
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 .
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(); } }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With