vicky
vicky

Reputation: 940

Curl Token request to Spring RestTemplate Conversion

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

Answers (3)

M. Deinum
M. Deinum

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

vicky
vicky

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

Shivam Puri
Shivam Puri

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

Related Questions