18

I'm trying to do an OAuth2 user-credentials post to an OAuth2 service using the Grails RestBuilder plugin.

If I try to specify the post body as a map, I get an error about no message converters for LinkedHashMap.

If I try to specify the body as a String, the post goes through, but none of the variables are posted to the server action.

Here's the post:

RestBuilder rest = new RestBuilder() def resp = rest.post("http://${hostname}/oauth/token") { auth(clientId, clientSecret) accept("application/json") contentType("application/x-www-form-urlencoded") // This results in a message converter error because it doesn't know how // to convert a LinkedHashmap // ["grant_type": "password", "username": username, "password": password] // This sends the request, but username and password are null on the host body = ("grant_type=password&username=${username}&password=${password}" as String) } def json = resp.json 

I've also tried setting the urlVariables in the post() method call, but the username/password are still null.

This is a very simple post, but I can't seem to get it to work. Any advice would be greatly appreciated.

2
  • Can you try sending JSON instead of Map? body(["grant_type": "password", "username": username, "password": password] as JSON). Ideally, if the content-type is JSON, then you can directly send the body in POST as json {} instead of using body. Commented Feb 13, 2014 at 3:20
  • I probably could, but the spec specifies it should be url-formencoded: tools.ietf.org/html/rfc6749#section-4.3.2 Commented Feb 13, 2014 at 3:24

3 Answers 3

34

I solved the problem by using a MultiValue map for the body.

RestBuilder rest = new RestBuilder() MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>() form.add("grant_type", "password") form.add("username", username) form.add("password", password) def resp = rest.post("http://${hostname}/oauth/token") { auth(clientId, clientSecret) accept("application/json") contentType("application/x-www-form-urlencoded") body(form) } def json = resp.json 
Sign up to request clarification or add additional context in comments.

2 Comments

Correct, but in my case I need to post both a json description and upload a file, so it is needed also a piece of code to retain in memory the file with def filebytescont = new File(filename).bytes; ByteArrayResource contentsAsResource = new ByteArrayResource(filebytescont){ String filename = "fileattached"; @Override public String getFilename(){ return filename; } }; and in map form.add("file", contentsAsResource) and of ocurse a content different: contentType("application/form-data")
Have a look at the RequestCustomizer class which is used internally as the delegate for your auth(), accept(), contentType() and body() methods. It also has a setProperty() method which adds properties to an MVM map, so it basically does what you're doing before your post() call.
4

Following code works for Box connection. Spend few of hours figuring this out

 String pclient_id = grailsApplication.config.ellucian.box.CLIENT_ID.toString() String pclient_secret=grailsApplication.config.ellucian.box.CLIENT_SECRET.toString() String pcode = params.code log.debug("Retrieving the Box Token using following keys Client ID: ==>"+pclient_id+"<== Secret: ==>"+pclient_secret+"<== Code: ==>"+pcode) RestBuilder rest = new RestBuilder() MultiValueMap<String, String> form = new LinkedMultiValueMap<String, String>() form.add("client_id", pclient_id) form.add("client_secret", pclient_secret) form.add("grant_type", "authorization_code") form.add("code", pcode) def resp = rest.post("https://app.box.com/api/oauth2/token") { accept("application/json") contentType("application/x-www-form-urlencoded") body(form) } def js = resp.json.toString() println("sss"+js) def slurper = new JsonSlurper() def result = slurper.parseText(js) println("Message:"+result.error) render js 

Comments

3

I found out some very easy to perform such type of action

//Get public static RestResponse getService(String url) { RestResponse rResponse = new RestBuilder(proxy:["localhost":8080]).get(Constants.URL+"methodName") return rResponse } //POST : Send complete request as a JSONObject public static RestResponse postService(String url,def jsonObj) { RestResponse rResponse = new RestBuilder(proxy:["localhost":8080]).post(url) { contentType "application/json" json { jsonRequest = jsonObj } } return rResponse } Method 1 : def resp = RestUtils.getService(Constants.URL+"methodName")?.json render resp as JSON Method 2 : JSONObject jsonObject = new JSONObject() jsonObject.put("params1", params.paramOne) jsonObject.put("params2", params.paramTwo) def resp = RestUtils.postService(Constants.URL+"methodName", jsonObject)?.json render resp as JSON 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.