0

I've got the initial half of an OAuth flow working with the SurveyMonkey API, but when I try to exchange the short-lived authorization code for a long-lived OAuth access token, I get an HTTP 400 response. This is step 3 of the SurveyMonkey OAuth Guide.

Here's a scrubbed version of the full exchange:

POST /oauth/token?api_key=<removed> HTTP/1.1
Accept: application/json
Accept-Encoding: gzip, deflate, compress
Content-Length: 338
Content-Type: application/json; charset=utf-8
Host: api.surveymonkey.net
User-Agent: HTTPie/0.7.2

{
    "client_id": "<removed>",
    "client_secret": "<removed>",
    "code": "dKkIJYnimBli3TMHoTdHoT-zkzkUFzfHeaWJJyPVmrYG35R5Q-jLLU-Y7Fg3BR0n3tVTQ6sAmDnwVxHXSjZVdiYTJ7u7SWbLCKgQa061bKJYXSpRhTsEL0v5GMWcMEBC2vje5UjRHp3SScFQEwIIjHKZH5raC5RQJJh.JYWEOqw8Iy-2Ds7km1zYaHGGlxqu",
    "grant_type": "authorization_code",
    "redirect_uri": "https://app.hubspotqa.com"
}

HTTP/1.1 400 Bad Request
Cache-Control: no-store
Connection: keep-alive
Content-Length: 96
Content-Type: application/json; charset=UTF-8
Date: Fri, 24 Jan 2014 00:05:53 GMT
SM-Request-ID: 41264d11-b93d-4f8b-ad1a-c656ccfa268b
Server: nginx

{
    "error": "invalid_request",
    "error_description": "Invalid POST body or Content-Type received."
}

I'm able to reproduce the exact same error using other HTTP clients as well, but I have no trouble manually getting an access token using the SurveyMonkey API console. What am I doing wrong?


Side question: the OAuth guide says that step 3 accepts a redirect_uri but the example Python guide uses redirect_url. Which is the correct parameter? Can I omit it entirely? My server certainly does not care about getting redirected anywhere.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710

1 Answers1

3

As it turns out, the required Content-Type for this POST is form encoding – application/x-www-form-urlencoded, not JSON.

Note that the documentation does not actually say that anywhere; it's implied by the example usage of the Python requests library.

Matt Ball
  • 354,903
  • 100
  • 647
  • 710
  • And, as it turns out, the `redirect_uri` must **exactly** match the original value specified. – Matt Ball Jan 24 '14 at 00:55
  • Our oauth guide on developer.surveymonkey.com does make a note about redirect_uri having to match and has the correct parameter name. However we could definitely make it clearer about form encoding, I'll make a note to clarify that. Will also clean up that GitHub code. Thanks for the feedback. – Miles Cederman-Haysom Jan 24 '14 at 01:22
  • @MilesCederman-Haysom appreciate the quick follow-up. The guide says that the `redirect_uri` **in step 1** has to match. Nothing in step 3 mentions such requirements or purpose of the `redirect_uri`. Frankly, I don't see the `redirect_uri` in step 3 adding anything other than inconvenience – does _requiring_ it actually improve security in any way? Is there any chance of seeing that requirement lifted? – Matt Ball Jan 24 '14 at 01:31
  • To be fair, there's nothing in there saying it should be changed either - it has the same variable name, so it should match what it was previously, and it should match what is on the Mashery account anyway. Out of interest, what were you changing the redirect_uri to? I will also add to the ticket to make it clearer about that requirement though, thanks. – Miles Cederman-Haysom Jan 24 '14 at 17:48
  • BTW, thanks for bringing this to our attention - looking at the sample code, it is incredibly outdated and uses a lot of deprecated features. We're going to overhaul the whole thing. – Miles Cederman-Haysom Jan 24 '14 at 18:32
  • I tried pretty much everything for the `redirect_uri` - omitting it, using `http://example.com`, using my app's configured "OAuth Redirect Url," and so on. I don't see what point it serves beyond being an extra piece of data I have to carry through. – Matt Ball Jan 24 '14 at 19:36
  • 1
    It's part of the OAuth 2.0 spec. http://tools.ietf.org/html/draft-ietf-oauth-v2-31#page-27 https://developers.google.com/accounts/docs/OAuth2Login – Miles Cederman-Haysom Jan 24 '14 at 21:06