Reputation: 940
I am trying to convert a curl request, which is giving me a token into Spring's Resttemplate post request, but I am getting 403 - bad request
My Curl Request
curl -d "grant_type=client_credentials&client_id=nu5yzeth9tektzf5egxuntp7&client_secret=uP2Xvr6SCKYgXgxxJsv2QkUG"
-H "Content-Type: application/x-www-form-urlencoded"
-X POST https://cloudsso.example.com/as/token.oauth2
Curl Response:
{"access_token":"HVURQ845OPJqs8UpOlef5m2ZCNwR","token_type":"Bearer","expires_in":3599}
Now, Here is my Java code to implement above curl post request
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
MultiValueMap<String, String> bodyParamMap = new LinkedMultiValueMap<String, String>();
bodyParamMap.add("grant_type", "client_credentials");
bodyParamMap.add("client_id", "nu5yzeth9tektzf5egxuntp7");
bodyParamMap.add("client_secret", "uP2Xvr6SCKYgXgxxJsv2QkUG");
entity = new HttpEntity<>(reqBodyData, bodyParamMap);
restTemplate.postForEntity(url, entity, TokenDTO.class)
Resttemplate call response:
2019-12-04 11:10:16,483[0;39m [39mDEBUG[0;39m [[34mrestartedMain[0;39m] [33morg.springframework.core.log.CompositeLog[0;39m: Accept=[application/json, application/*+json]
[30m2019-12-04 11:10:16,484[0;39m [39mDEBUG[0;39m [[34mrestartedMain[0;39m] [33morg.springframework.core.log.CompositeLog[0;39m: Writing [{"grant_type":["client_credentials"],"client_id":["nu5yzeth9tektzf5egxuntp7"],"client_secret":["uP2Xvr6SCKYgXgxxJsv2QkUG"]}] with org.springframework.http.converter.StringHttpMessageConverter
[30m2019-12-04 11:10:17,976[0;39m [39mDEBUG[0;39m [[34mrestartedMain[0;39m] [33morg.springframework.core.log.CompositeLog[0;39m: Response 400 BAD_REQUEST
[30m2019-12-04 11:10:17,981[0;39m [34mINFO [0;39m [[34mrestartedMain[0;39m] [33mcom.ibm.ciscoApiIntegration.service.impl.CiscoAPIServiceImpl[0;39m: e::: 400 Bad Request
How can make the above curl request in RestTemplate
working?
Note: https://cloudsso.example.com/as/token.oauth2 it's little modified for the question.
Upvotes: 3
Views: 3104
Reputation: 124898
If you take a look at the documentation for HttpEntity
you will see that you are using the wrong constructor.
entity = new HttpEntity<>(reqBodyData, bodyParamMap);
You are passing the arguments you want to use as the body (bodyParamMap
) as headers (as the second argument is the headers to be used for the request). In fact you aren't even using the HttpHeaders
for the request as you aren't passing them to the HttpEntity
. I'm not sure what the reqBodyData
is but probably a toString
of the bodyParamMap
.
What you should have been doing is the following
entity = new HttpEntity<>(bodyParamMap, headers);
As HttpHeaders
impements MultiValueMap
you can directly use them in the constructor. You also want to pass the bodyParamMap
as is.
NOTE: I would also suggest to explictly set the Content-Type
on the HttpHeaders
so you are sure what is being send.
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
Thus the total resulting code should look like
RestTemplate restTemplate = new RestTemplate();
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> bodyParamMap = new LinkedMultiValueMap<>();
bodyParamMap.add("grant_type", "client_credentials");
bodyParamMap.add("client_id", "nu5yzeth9tektzf5egxuntp7");
bodyParamMap.add("client_secret", "uP2Xvr6SCKYgXgxxJsv2QkUG");
entity = new HttpEntity<>(bodyParamMap, headers);
restTemplate.postForEntity(url, entity, TokenDTO.class)
NOTE: You shouldn't be constructing a single use RestTemplate
but you rather want to configure that once and inject that into your class.
Upvotes: 3
Reputation: 940
I have just solved the issue:
I had this in this
// wrong
//private HttpEntity<String> entity;
I changed it to this:
private MultiValueMap<String, String> parametersMap;
and changed it
// not working
entity = new HttpEntity<>(reqBodyData, bodyParamMap);
to this
// working
entity = new HttpEntity<>(bodyParamMap, headers);
Now it's working perfectly fine.
response:
2019-12-04 11:52:46,503 DEBUG [restartedMain] org.springframework.core.log.CompositeLog: HTTP POST https://cloudsso.example.com/as/token.oauth2
2019-12-04 11:52:46,521 DEBUG [restartedMain] org.springframework.core.log.CompositeLog: Accept=[application/json, application/*+json]
2019-12-04 11:52:46,522 DEBUG [restartedMain] org.springframework.core.log.CompositeLog: Writing [{grant_type=[client_credentials], client_id=[nu5yzeth9tektzf5egxuntp7], client_secret=[uP2Xvr6SCKYgXgxxJsv2QkUG]}] with org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter
2019-12-04 11:52:47,831 DEBUG [restartedMain] org.springframework.core.log.CompositeLog: Response 200 OK
Note: in my case, adding or disabling this value, isn't making any difference, i am getting the auth token anyway.
//headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
Upvotes: 2
Reputation: 1666
As suggested by post https://stackoverflow.com/a/49127760/11226302
You should set the request content type in header as; headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
Hope this helps!
Upvotes: 1