magnific0 / nokia-weight-sync

Get weight from Nokia Health and update in Garmin Connect or Smashrun
GNU General Public License v3.0
71 stars 30 forks source link

http://, localhost, IPs not supported in callback URL, Missing Token Error #12

Open tolrahC opened 5 years ago

tolrahC commented 5 years ago

I'm having an issue when trying to configure the Nokia connection. First: Now Nokia require a callback url that does not contain an ip address or localhost, also the port must be 80 or 443. Secondly: I'm having this error when trying to create the connection with Nokia, in automatic or manual mode

Traceback (most recent call last):
  File "D:\Tools\nokia-weight-sync\nokia-weight-sync.py", line 262, in <module>
    setup_nokia( options, config )
  File "D:\Tools\nokia-weight-sync\nokia-weight-sync.py", line 128, in setup_nokia
    creds = auth.get_credentials(nokia_auth_code)
  File "D:\Tools\nokia-weight-sync\nokia.py", line 87, in get_credentials
    client_secret=self.consumer_secret)
  File "C:\Users\tolra\AppData\Local\Programs\Python\Python37-32\lib\site-packages\requests_oauthlib\oauth2_session.py", line 307, in fetch_token
    self._client.parse_request_body_response(r.text, scope=self.scope)
  File "C:\Users\tolra\AppData\Local\Programs\Python\Python37-32\lib\site-packages\oauthlib\oauth2\rfc6749\clients\base.py", line 415, in parse_request_body_response
    self.token = parse_token_response(body, scope=scope)
  File "C:\Users\tolra\AppData\Local\Programs\Python\Python37-32\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 425, in parse_token_response
    validate_token_parameters(params)
  File "C:\Users\tolra\AppData\Local\Programs\Python\Python37-32\lib\site-packages\oauthlib\oauth2\rfc6749\parameters.py", line 435, in validate_token_parameters
    raise MissingTokenError(description="Missing access token parameter.")
oauthlib.oauth2.rfc6749.errors.MissingTokenError: (missing_token) Missing access token parameter.
magnific0 commented 5 years ago

@tolrahC again thanks for raising the issue. I will update the documentation and some other older issues soon and think more about a proper solution.

Solution A: using automatic authorization

  1. using a proper domain name and point it to your public IP and make sure the router handles the port forwarding to the machine requesting the authorization.
  2. pick any fictitious domain name (e.g., example.com) and redirect it to 127.0.0.1 by editing the hosts file.

Both solutions are not ideal, because the http scheme is not allowed anymore. So you'll have to setup certificates and modify the Python application or using an reverse proxy to host a HTTPS front calling back to a HTTP url.

Solution B: using manual authorization

This is probably easier at the moment.

  1. Point it to a site like: https://httpbin.org/anything (allowed by Withings, I checked). Copy the response from the browser back into the application.

Please let me know if any of this works out for you!

tolrahC commented 5 years ago

@magnific0 I still have the missing token error doing solution B.

rafdev18 commented 5 years ago

@magnific0 same behavior here ... tried several times ... not a user error ;)

.... parameters.py", line 435, in validate_token_parameters raise MissingTokenError(description="Missing access token parameter.") oauthlib.oauth2.rfc6749.errors.MissingTokenError: (missing_token) Missing access token parameter.

piccit commented 5 years ago

I'm not sure that Withing's end is fully working right now, my IFTTT integration hasn't worked since the 14th

tolrahC commented 5 years ago

@magnific0 I finally got it working manually using curl (Nokia Help here)

I never worked with Python before, but after a quick debug session the problem seems to come from the OAuth2Session class, but I guess you already know that ;)

cristian5th commented 5 years ago

Hello.

Has the MissingTokenError issue been solved? I have just launched the script in a new computer and I'm getting this error.

I cannot use the localhost solution as in my old computer because Nokia wouldn't allow it so I switched to @magnific0's proposal of using https://httpbin.org/anything with a manual authorisation, but after I copy the code back into the script, I get this MissingTokenError.

@tolrahC, how did you managed to get it working manually?

Thank you all. Regards.

magnific0 commented 5 years ago

Hi, I'm not sure what the timeout is exactly, but you need to be rather quick in copying the values over. Maybe that helps?

cristian5th commented 5 years ago

How fast should I be? :)

I believe there are two different issues here. As you told me to be fast, I tried several times intending to be as fast as I can be, and once I got a timeout issue which is not the missing token issue that I was having previously.

Most of the times I try the manual configuration, the error I get back is this one:

Traceback (most recent call last):
  File "nokia-weight-sync.py", line 262, in <module>
    setup_nokia( options, config )
  File "nokia-weight-sync.py", line 128, in setup_nokia
    creds = auth.get_credentials(nokia_auth_code)
  File "/Users/cralvarez/Python_scripts/nokia-weight-sync/nokia.py", line 87, in get_credentials
    client_secret=self.consumer_secret)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests_oauthlib/oauth2_session.py", line 307, in fetch_token
    self._client.parse_request_body_response(r.text, scope=self.scope)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/clients/base.py", line 415, in parse_request_body_response
    self.token = parse_token_response(body, scope=scope)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 425, in parse_token_response
    validate_token_parameters(params)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/oauthlib/oauth2/rfc6749/parameters.py", line 435, in validate_token_parameters
    raise MissingTokenError(description="Missing access token parameter.")
oauthlib.oauth2.rfc6749.errors.MissingTokenError: (missing_token) Missing access token parameter.

It seems to me as an authorisation problem.

One of my latests tries, the one I thought to be the fastest, I got a totally different error. I see the timeout you are talking about.

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 343, in _make_request
    self._validate_conn(conn)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 839, in _validate_conn
    conn.connect()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connection.py", line 344, in connect
    ssl_context=context)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/util/ssl_.py", line 344, in ssl_wrap_socket
    return context.wrap_socket(sock, server_hostname=server_hostname)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 412, in wrap_socket
    session=session
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 853, in _create
    self.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 1117, in do_handshake
    self._sslobj.do_handshake()
socket.timeout: _ssl.c:1039: The handshake operation timed out

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 638, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/util/retry.py", line 367, in increment
    raise six.reraise(type(error), error, _stacktrace)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/packages/six.py", line 686, in reraise
    raise value
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 600, in urlopen
    chunked=chunked)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 346, in _make_request
    self._raise_timeout(err=e, url=url, timeout_value=conn.timeout)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/urllib3/connectionpool.py", line 306, in _raise_timeout
    raise ReadTimeoutError(self, url, "Read timed out. (read timeout=%s)" % timeout_value)
urllib3.exceptions.ReadTimeoutError: HTTPSConnectionPool(host='account.withings.com', port=443): Read timed out. (read timeout=2)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "nokia-weight-sync.py", line 262, in <module>
    setup_nokia( options, config )
  File "nokia-weight-sync.py", line 128, in setup_nokia
    creds = auth.get_credentials(nokia_auth_code)
  File "/Users/cralvarez/Python_scripts/nokia-weight-sync/nokia.py", line 87, in get_credentials
    client_secret=self.consumer_secret)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests_oauthlib/oauth2_session.py", line 284, in fetch_token
    verify=verify, proxies=proxies)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 581, in post
    return self.request('POST', url, data=data, json=json, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests_oauthlib/oauth2_session.py", line 425, in request
    headers=headers, data=data, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/requests/adapters.py", line 529, in send
    raise ReadTimeout(e, request=request)
requests.exceptions.ReadTimeout: HTTPSConnectionPool(host='account.withings.com', port=443): Read timed out. (read timeout=2)

What do you think of this?

Thanks.

tolrahC commented 5 years ago

@cristian5th I retrieved the accces token using curl and putted it in the config.ini file.

The config file should look like this: `[garmin] username = _your_garminusername password = _your_garminpassword

[nokia] consumer_key = _generated_consumer_key_from_theprocedure consumer_secret = _generated_consumer_secret_from_theprocedure callback_uri = https://httpbin.org/anything access_token = _token_retrieved_fromcurl token_expiry = _expirency_retrieved_fromcurl token_type = Bearer refresh_token = _refreshtoken_retrieved_fromcurl user_id = _not_sure_about_this_one_before_probably_fromcurl`

cristian5th commented 5 years ago

Hi @tolrahC

What is the url you are feeding to curl? Any specific argument? I'm trying with the url given as answer when I authorise the application at Nokia but all curl is giving me back is the same informations as the Nokia webpage. There is no token nowhere.

{
  "args": {
    "code": "8329710c7e3f1517186367b6bb47c23f65fa6377"
  }, 
  "data": "", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept": "*/*", 
    "Host": "httpbin.org", 
    "User-Agent": "curl/7.54.0"
  }, 
  "json": null, 
  "method": "GET", 
  "origin": "88.188.103.26, 88.188.103.26", 
  "url": "https://httpbin.org/anything?code=8329710c7e3f1517186367b6bb47c23f65fa6377"
}

Then, you are stating that I should simply write the config.ini file with this data but, how is it that the config.ini file which I retrieved from my old computer was also raising the missing token error? I was originally configured with the localhost callback URL and I moved all the files from the old to the new computer, including the config.ini. There I got the missing token error so I tried to simply delete the application at Nokia and start everything again. Since then, I haven't managed to make it work, always because of the missing token error.

I have just downloaded the latest update but I still have the same issue.

Thank you. Regards.

tolrahC commented 5 years ago

@cristian5th You have to use this method here

cristian5th commented 5 years ago

What a trip! Finally! It worked following the method you mentioned @tolrahC.

Thank you very much for your help and your patience.

g3d12 commented 5 years ago

I am trying to register for api access at https://account.withings.com/partner/add_oauth2 but I cannot figure out what format and what url shoudl be provided. In guidlines it says http://developer.withings.com/oauth2/#tag/glossary that it needs to be URL-encoded string. I tried: https://httpbin.org/anything https%3A%2F%2Fhttpbin.org%2Fanything httpbin.org/anything httpbin.org%2Fanything It always says as response: This is not a valid URL. Any help. I want to use the script to schedule on daily basis sending weight to garmin connect on RPI. Thanks for any help.

samwiseg0 commented 5 years ago

An easier workaround is to make sure requests-oauthlib v1.0.0 is installed.

To force a specific version use:

pip install requests-oauthlib==1.0.0

I would also recommend that a virtual environment be created for the script:

cd nokia-weight-sync/

#You may need to change python3 to python depending on your os
python3 -m venv ./venv

#Install requirements
./venv/bin/python -m pip install arrow requests-oauthlib==1.0.0

#Run the script
./venv/bin/python ./nokia-weight-sync.py -k CLIENT_ID -s CONSUMER_SECRET setup nokia