Am trying to use Spring Secruity's OAuth API to obtain an access token from an externally published API.
This curl command works (and its contents are all that I need to obtain an access token):
curl -X POST \
https://api.app.com/v1/oauth/token \
-H 'content-type: application/x-www-form-urlencoded' \
-d'grant_type=client_credentials&client_id=bcfrtew123&client_secret=Y67493012'
Am able to obtain an access token from the external service after running this curl command.
When using Spring Security OAuth API:
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>2.1.1.RELEASE</version>
</dependency>
Setup my SpringMVC Controller's method like this:
@RequestMapping(value = "/getAccessToken", method = RequestMethod.POST, consumes="application/x-www-form-urlencoded")
public OAuth2AccessToken getAccessToken(@RequestParam(value="client_id", required=true) String clientId, @RequestParam(value="client_secret", required=true) String clientSecret) throws Exception {
String tokenUri = "https://api.app.com/v1/oauth/token";
ResourceOwnerPasswordResourceDetails resourceDetails = new ResourceOwnerPasswordResourceDetails();
resourceDetails.setAccessTokenUri(tokenUri);
resourceDetails.setClientId(clientId);
resourceDetails.setClientSecret(clientSecret);
resourceDetails.setGrantType("client_credentials");
resourceDetails.setScope(Arrays.asList("read", "write"));
DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext();
oauth2RestTemplate = new OAuth2RestTemplate(resourceDetails, clientContext);
OAuth2AccessToken token = oauth2RestTemplate.getAccessToken();
return token;
}
When I invoke the getAccessToken call from my local tomcat instance:
access_denied
error_description=Unable to obtain a new access token for resource 'null'.
The provider manager is not configured to support it.
Question(s):
(Please notice that the content-type needs to be "application/x-www-form-urlencoded"...)
How can I mimic the working curl command using Spring Security OAuth API?
Could it be the default values that I have set in the RequestParameters?
If successful, how can I set it up so that access token is always preloaded before any request made?
The real reason is, you are using ResourceOwnerPasswordResourceDetails
for a "client_credentials"
access token request. We cannot interchange ResourceOwnerPasswordResourceDetails
and ClientCredentialsResourceDetails
.
In ClientCredentialsResourceDetails
you need to set AccessTokenUri, ClientId, ClientSecret
and grantType
.
In ResourceOwnerPasswordResourceDetails
, you need to provide Username and Password
along with AccessTokenUri, ClientId, ClientSecret
and GrantType
.
(Some authserver do accept password
token request without username and password
.. But I would say it is wrong)
Refer : Securing an existing API with our own solution
This is what i use:
@Bean
public RestTemplate oAuthRestTemplate() {
ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails();
resourceDetails.setId("1");
resourceDetails.setClientId(oAuth2ClientId);
resourceDetails.setClientSecret(oAuth2ClientSecret);
resourceDetails.setAccessTokenUri(accessTokenUri);
OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, oauth2ClientContext);
return restTemplate;
}
The correct headers will be set bij the framework, but the username/password will be base64 encodes as Authorization header (basic authentication). This is the OAuth2 spec for a client_credentials grant.
Check if the api supports the spec:
curl -X POST \
'https://api.app.com/v1/oauth/token' \
-i -u 'client:secret' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'grant_type=client_credentials'
If you need to send the username & password as data instead of authorisation header, you can add resourceDetails.setAuthenticationScheme(AuthenticationScheme.form);
this should set de username & password as data
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