splitwise / api-docs

API documentation for the Splitwise API.
http://dev.splitwise.com
28 stars 16 forks source link

Getting 404 when requesting token of oauth2 #43

Closed Enterisr closed 3 years ago

Enterisr commented 3 years ago

Hey there! Recently I've tried to make a request for the 'https://secure.splitwise.com/oauth/token' endpoint (after the callback_uri called successfully of course) , but it seemed down from some reason and returns 404.

Maybe the problem is with the request, But I tried to copy exactly the standard token request format to no help.

May you please take a look at that?
I am appending the fetch request so you'll see what I'm doing. image Thank you and happy new year!

jas14 commented 3 years ago

@Enterisr I see you're trying to submit your client ID and secret as part of an Authorization: Basic header. We're expecting your OAuth client ID and secret to be passed as parameters, namely client_id and client_secret, not as a header. Happy new year!

Enterisr commented 3 years ago

Thank you for you help, I really appreciate it! Sadly now I'm getting 400 with "unsupported_grant_type". Tried to add the contentType header, but nothing came through besides 400.

jas14 commented 3 years ago

@Enterisr you're quite welcome! I'm afraid it'll be quite difficult for me to debug your specific case here, but make sure grant_type is authorization_code.

aschoerg commented 3 years ago

Hi @jas14, hi @Enterisr,

Nice to see that the issues are answered! :+1: I am facing a very similar issue and I really would need your help :)

When I send a POST to :

https://www.splitwise.com/oauth/token
?code=<obtained code>
&grant_type=authorization_code
&client_id=<splitwise_consumer_key>
&client_secret=<splitwise_consumer_secret>
&redirect_uri=http://localhost

I get 400 Bad Request, don't get unsupported_grant_type, but:

{
    "error": "invalid_grant"
}

I dug into it a little more, using the JS-example provided http://dev.splitwise.com/?javascript#authentication ...

client.getOAuthAccessToken(
      qsObj.code,
      {
        'redirect_uri': MY_CALLBACK_URL,
        'grant_type': 'authorization_code'
      },
      function(e, access_token, refresh_token, results) {...}
)

... and looking at the source code from node-oauth library https://github.com/ciaranj/node-oauth/blob/master/lib/oauth2.js#L177-L190 translates to a params object of

params['redirect_uri'] = MY_CALLBACK_URL;
params['grant_type'] = 'authorization_code';
params['client_id'] = this._clientId;
params['client_secret'] = this._client_secret;
params['code'] = code;

This is then POSTed as application/x-www-form-urlencoded to https://www.splitwise.com/oauth/token.

And when I use PostMan to send the queryparams as headers: image

I get 400 Bad Request, some session cookies from splitwise.com, and the same:

{
    "error": "invalid_grant"
}

@jas14, please illuminate us, What do we need to send?

Thank you in advance, Happy new Year, Alex

aschoerg commented 3 years ago

I solved it! The answer in #6 was a hint!

I forgot to specify the callback url in my application. This made splitwise not give me an actual token. So the real problem seems to be masked by some errors, which makes debugging hard, but is possibly better for security :wink:

If anyone ever wants to do a Splitwise login, here are the steps (and please feel free to copy it to your docu):

That's it! :heart:

aschoerg commented 3 years ago

@Enterisr

Make sure to send the parameters as described in the above format. I tried the following in JS/node:

const fetch = require("node-fetch");

async function fetchToken() {
  let formBody = 
      ["code=<obtained code>",
      "grant_type=authorization_code",
      "client_id=<splitwise_consumer_key>",
      "client_secret=<splitwise_consumer_secret>",
      "redirect_uri=<callback_url>"
      ];
  let headers = "Content-Type:application/x-www-form-urlencoded";
  fetch('https://secure.splitwise.com/oauth/token', {
    headers: { "Content-Type": "application/x-www-form-urlencoded" },
    body: formBody.join("&"),
    mode: 'cors',
    method: 'POST'
  }).then(r => r.json()).then(ret => console.log(ret)).catch(e => console.log(e));

}

fetchToken();

that results in a json object:

{
  "access_token": "...",
  "token_type": "bearer"
}

Good Luck! :four_leaf_clover:

Enterisr commented 3 years ago

@aschoerg Thank you for reaching out. Your answser did help me to get to 200. I will attach here key notes that was not clear to me beforehand:

1.The body should not be sent in json format, but in a "query like" format - x-www-form-urlencoded 2.The redirect_uri should be the same uri that you given to the 'https://secure.splitwise.com/oauth/authorize' request, and that you entered in the site.

@jas14 Thank you for your help! Maybe it will be a good idea to allow developers more than one callback url, like you have in the spotify api 🤔. But this is off-topic, so I will close this issue.

Thank you again!