simov / grant

OAuth Proxy
MIT License
4.08k stars 257 forks source link

Oauth for Untappd not working #262

Closed adriaanh closed 2 years ago

adriaanh commented 2 years ago

Hi all! I'm using Strapi for a personal BeerApp project, and I'm trying to get Oauth2 for Untappd working. At the moment however, I don't seem to send the correct values to Untappd, as I'm getting indications that I'm not sending the required params in the URL.

I have the following Grant configuration:

    untappd: {
      authorize_url: "https://untappd.com/oauth/authenticate",
      access_url: "https://untappd.com/oauth/authorize",
      oauth: 2,
      key: "",
      secret: "",
      callback: `${strapi.config.server.url}/auth/untappd/callback`,

I am getting back the 'code' parameter to the callback URL, but after that it doesn't work. Untappd requires a GET request to get the access_token back with the following parameters:

https://untappd.com/oauth/authorize/?client_id=CLIENTID&client_secret=CLIENTSECRET&response_type=code&redirect_url=REDIRECT_URL&code=CODE

However, I get the message from Untappd:

http_code = 500. Param_error: Missing either the client_id, redirect_url, client_secret or code parameter. Please check your request and try again

I already tried to use the token_endpoint_auth_method: "client_secret_basic", as to my understanding Grant is using a POST request to get the access_token, right? But adding this option to the config this doesn't change anything.

Does anyone have a clue what to do?

adriaanh commented 2 years ago

I got the debugging working, looks like it is already with the authorization_code where it goes wrong: a POST request is send to Untappd, which should be a GET request. Is it possible to change that in the configuration?

req POST https://untappd.com/oauth/authorize
    user-agent:     simov/grant/5.4.17
    content-type:   application/x-www-form-urlencoded
    content-length: 249
    Host:           untappd.com
form
    grant_type:    authorization_code
    code:         X
    client_id:     X
    client_secret: X
    redirect_uri:  http://localhost:3000/connect/untappd/callback
(...)
json
    meta: 
      http_code:    500
      error_type:   param_error
      error_detail: Missing either the client_id, redirect_url, client_secret or code parameter. Please check your request a try again.
    response: 
      (empty array)
simov commented 2 years ago

Yes, it have to be implemented here, I can do it, it's fairly easy.

adriaanh commented 2 years ago

Oh that would be great!

simov commented 2 years ago

Can you pull master and test it? It was implemented here https://github.com/simov/grant/commit/d09f94e7f1494b15ca5fe8568f1fb000b9832a5d

Unfortunately I don't have an app to test it and it seems that one of the parameters may still be incorrect. Note that their implementation is outside of the OAuth spec.

adriaanh commented 2 years ago

That's fast!

I've pulled the changes and started a express server. But I seem to get the following error:

(node:1128) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'error' of undefined
    at data (/home/XXX/dev/grant/lib/response.js:70:14)
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
    at async app (/home/xxx/dev/grant/lib/handler/express-4.js:32:38)
(Use `node --trace-warnings ...` to show where the warning was created)
(node:1128) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 1)

I tested with the following:

{
  "defaults": {
    "origin": "http://localhost:3000",
    "transport": "session"
  },
  "untappd": {
    "key": "X",
    "secret": "X",
    "callback": "/hello"
  }
}

And the following js code:

var express = require("express");
var session = require("express-session");
var grant = require("../../").express();

express()
  .use(session({ secret: "grant", saveUninitialized: true, resave: false }))
  .use(grant(require("./config.json")))
  .get("/hello", (req, res) => {
    res.end(JSON.stringify(req.session.grant.response, null, 2));
  })
  .listen(3000);

After going to the /connect/untappd URL I get the error as shown above. With DEBUG logs I see that a GET request has been send and a status 200 OK was send back, including the code.

adriaanh commented 2 years ago

Edit: In English

By the way, I think you miss the following parameter

According to the documentation, this parameter should be send with both requests.

So:

  1. authorize_url: https://untappd.com/oauth/authenticate/?client_id=CLIENTID&response_type=code&redirect_url=REDIRECT_URL
  2. access_url: https://untappd.com/oauth/authorize/?client_id=CLIENTID&client_secret=CLIENTSECRET&response_type=code&redirect_url=REDIRECT_URL&code=CODE
simov commented 2 years ago

Ok, I'm adding it. That was the one that I was not sure about .. usually that's not being sent with that request.

adriaanh commented 2 years ago

Yeah, the OAuth implementation is not really according to the specs

simov commented 2 years ago

Updated here https://github.com/simov/grant/commit/111e7d379c27484906a79a914ab353d9a79cec98 let me know if it works.

adriaanh commented 2 years ago

Thanks, tried it just now but get the following error: image

adriaanh commented 2 years ago

Express logs: image

simov commented 2 years ago

Well it seems they are sending back just the access token instead of what they claim in their docs:

{
  "meta": {
    "http_code": 200
  },
  "response": {
    "access_token": "TOKEHERE"
  }
}

Ok .. yet another update incoming.

simov commented 2 years ago

Updated here https://github.com/simov/grant/commit/ea29993a73e435b7777c3966de3ae10cf9012df7 lets see.

adriaanh commented 2 years ago

Thanks, will check tomorrow!

adriaanh commented 2 years ago

Yes, it's working! I get the following back:

{
  "access_token": "X",
  "raw": {
    "access_token": "X",
    "token_type": "bearer"
  }
}
adriaanh commented 2 years ago

It's working with transport methods querystring & session. I cannot get 'state' to work, but that's I think more to do with my testsetup, so for now I think this item can be closed!

simov commented 2 years ago

Nice, we can keep this open until I publish the next release.

simov commented 2 years ago

Published in v5.4.18