home-assistant / core

:house_with_garden: Open source home automation that puts local control and privacy first.
https://www.home-assistant.io
Apache License 2.0
71.59k stars 29.91k forks source link

Withings Callback URL must be both publically accessible AND your HA environment #26924

Closed pickerin closed 4 years ago

pickerin commented 4 years ago

Home Assistant release with the issue:

0.99.3

Last working Home Assistant release (if known): N/A

Operating environment (Hass.io/Docker/Windows/etc.):

Hass.io in Docker on Ubuntu

Component/platform:

withings platform integration

Description of problem: When establishing your Withings Application for integration you must specific a "Callback URL". That callback URL will be validated by Withings as accessible (So you cannot use RFC1918 IP addresses, localhost, etc.)

When authorizing HA with the Withings Integration, you are redirected to Withing's site to authorize the application. Upon selecting your profile, you will then receive an error from withings that the URL does not match:

{"errors":[{"message":"redirect_uri_mismatch: The redirect URI provided is missing or does not match partner callback url"}]}

This prevents the Integration from being authorized and the documentation states that if this happens you should: " Note: If you get a browser error saying the site is inaccessible, you can modify the http://domain portion of the URL to something you know is accessible, locally or publically. For example, http://localhost:8123. " However, "localhost:8123" will not pass the Withing's validity test and cannot be used. You also cannot use a local, RFC1918 IP, address either.

Problem-relevant configuration.yaml entries and (fill out even if it seems unimportant):

Traceback (if applicable):

{"errors":[{"message":"redirect_uri_mismatch: The redirect URI provided is missing or does not match partner callback url"}]}

Additional information:

pickerin commented 4 years ago

Use of the "base_url" attribute will allow you get past the error. The "base_url" MUST match the Callback URL you used in the Withings app. However, since that does not resolve to your HA environment the authorization will fail.

cnschulz commented 4 years ago

Pardon my ignorance, I don't know what an rfc1918 address is... I have also tried using the remote nabu casa url which is publicly available. I edited the base_url to match. This is ok with the developer api and seems to authenticate properly. The issue is that I am them redirected back to the withings authentication page.

probot-home-assistant[bot] commented 4 years ago

Hey there @vangorra, mind taking a look at this issue as its been labeled with a integration (withings) you are listed as a codeowner for? Thanks!

pickerin commented 4 years ago

RFC 1918 IPs are Private IP addresses, things like 192.168.1.1, or 172.32.2.3. They cannot be used on the Internet. Most Home Assistant installations will be using these types of IP addresses internally on the home network. You cannot use those IPs to validate the callback URL at Withings. You also cannot use 127.0.0.1, as the documentation states you can.

For the validation to work with Withings, the callback url MUST be accessible on the public Internet, must NOT use a port (like 8123), and must NOT use Private IPs.

Additionally, the callback URL you use with Withings must redirect your browser to your Home Assistant configuration in order to complete the authorization.

That makes it nearly impossible to actually authorize the integration. I tried configuring a base_url (which is stated as optional and I believe may be required), but that base_url must match the callback url you used when you set up your application, so that reduces it's usefulness.

e.g. I can set the callback URL at Withings to https://google.com/, but then I have to use a base_url in my configuration of https://google.com/ or else I'll get an error that they do not match. When I do that, I get redirected to Google at the end of the authorization and it does not complete (because now I'm staring at Google and not my Home Assistant configuration).

From what I can tell, you cannot successfully complete the authorization at all.

choffee commented 4 years ago

You need to edit your app in https://account.withings.com/partner/edit_oauth2 and set the callback url to: https://foobar.ui.nabu.casa/api where foobar is your unique nubacasa url. Then set the base_url to the same but without the api at the end. This seems to redirect things correctly back to the instance having authenticated but then I get a 500 error from the ha server.

cnschulz commented 4 years ago

My original post included this procedure (minus the /api, which still doesnt work). with (or without) the /api suggestion here, you are simply directed back to the withings user selection screen after the initial selection and authorisation. If you select a user and authorise again, a 500 error occurs. Has anyone actually had success here?

On Sat, 28 Sep 2019 at 06:36, John Cooper notifications@github.com wrote:

You need to edit your app in https://account.withings.com/partner/edit_oauth2 and set the callback url to: https://foobar.ui.nabu.casa/api where foobar is your unique nubacasa url. Then set the base_url to the same but without the api at the end. This seems to redirect things correctly back to the instance having authenticated but then I get a 500 error from the ha server.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/home-assistant/home-assistant/issues/26924?email_source=notifications&email_token=AAJXBZBUI2JHQ4S7TWKNVOTQLZVERA5CNFSM4I2TYFK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD72A2QA#issuecomment-536087872, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJXBZEUKTEL4XUSY7LNVDTQLZVERANCNFSM4I2TYFKQ .

pickerin commented 4 years ago

As far as I can tell, no. There's no way to make this actually work. I too just tried the exact procedure that @choffee recommended. I get a "Corrupted callback", which probably is the same as @cnschulz and the 500 error.

vangorra commented 4 years ago

Withings is very picky about the domains they send data to. Additionally, they are also picky that request data matches dev account data clearly. This makes the setup process a lot more complicated that using other oath2 enabled components.

The domain provided in the withings developer page isn't very important, it just needs to be publicly accessible and return some data. This can literally be a blank html page some place. Withings will check and return an obscure error when saving the form if it doesn't fit their requirements.

If you have nabu casa, login to your HA and use that domain in the withings developer config. Eg: https://my_long_id.nabu.casa/, then set that as the base_url in the withings HA config.

Now when you go through the integration steps, the component will send you to the withings site with a redirect_url using the base_url in the config. If this base_url doesn't have the same domain as your withing developer config, withings will fail with an obscure message.

Once you authorize access, one of two things can happen. 1) You'll either be redirected back to the HA and it will confirm setup is complete. 2) The withings site directs you to the domain in question but no HA is hosted there. Just change the base in the browser url to the url you want, like http://192.168.1.12. That will load HA and the config workflow will complete.

After all that, it sadly still won't work. It appears between the time this component was completed and merged, Withings made a hard requirement on an additional attribute for accessing data. This is a downstream dependency and the developer in question hasn't released it yet (https://github.com/orcasgit/python-nokia/issues/38).

The issue talking about the authentication can be found here: https://github.com/home-assistant/home-assistant/issues/26716 There's even advice on how to hack it to work until the dependency is fixed.

vangorra commented 4 years ago

Withings imposes strict requirements on the callback URL. The host cannot be an ip and the URL must resolve when setting up an account. There isn't anything we can do from the HA side.

vangorra commented 4 years ago

This issue can be closed.

aldesantis commented 4 years ago

@vangorra could you clarify the status of this issue? Is the Withings integration currently broken?

cnschulz commented 4 years ago

Hasnt worked since september

On Mon, 3 Feb 2020 at 08:44, Alessandro Desantis notifications@github.com wrote:

@vangorra https://github.com/vangorra could you clarify the status of this issue? Is the Withings integration is currently broken?

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/home-assistant/home-assistant/issues/26924?email_source=notifications&email_token=AAJXBZHD5AESXPXAQQJYXHLRA45DTA5CNFSM4I2TYFK2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEKSB23A#issuecomment-581180780, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAJXBZCWDLSTBNPPWK7N5UDRA45DTANCNFSM4I2TYFKQ .

vangorra commented 4 years ago

Interesting. I'll take a look. It's working for me.

Chr1stian commented 4 years ago

I struggled a bit to get it working, but somehow after changing the callback URL in Withings developer settings to start with exactly the same as the base URL and some refreshing later is suddenly went trough.

http:
    base_url: https://MYDOMAIN.duckdns.org:433

Had to include the port, 443 in the Withings URL!

vangorra commented 4 years ago

That's expected. Withings is very strict regarding what URLs they will accept.

aldesantis commented 4 years ago

FYI, I'm not sure if I'm doing something wrong but this is not working at all for me. I created the app on Withing's Developer Portal and used my Nabu Casa URL as the callback URL. Then I connected to the Nabu Casa URL, set up the integration, but it's redirecting me back to my local URL instead (192.168.x.x). If I change the hostname manually and visit the callback URL through the Nabu Casa domain instead, I get a 500.

Clem- commented 4 years ago

@aldesantis, you need to add this code in your configuration.yaml :

http:
  base_url: https://YOUR_ID.nabu.casa/

so that HA set the correct Callback URL

scstraus commented 4 years ago

Hi all, I know that this issue is long closed, but I found it difficult to make this work with nabu casa, so I thought I'd share my config. Most important thing is to set your callback URI in withings config to your nabu casa URL plus /auth/external/callback So with recent versions of homeassistant (I tried on .107.7) it will look something like the below:

https://YOUR_NABU_CASA_ID.ui.nabu.casa/auth/external/callback

That's different than many of the formats shown above which threw me off. The above format works for me. Once you set it that way, you can easily add the integration from the integration pane.

Zorkny commented 4 years ago

The problem is that when I press "open website" during adding the integration, the URL on withings site contains my local IP as redirect URL and not the Nabucasa URL. Since base_url is now deprecated I cant seem to change this. Where is this stored in home assistant?

makingwilliam commented 4 years ago

I too am having a problem adding this integration into HA. I would like to point out though, that base_url is no longer valid and you must now assign external_url in your configuration. That aside, I have been able to setup other integrations with my external_url properly configured, including SmartThings which I understand integrates similarly. I am receiving the same invalid callback url as everyone else seems to be. Is there a way on my end to change the url? I tried just changing it in the browser address line, which did allow me to login to Withings, then when the callback occurs I'm presented with a site cannot be reached message.

I am using https://mydomain.com/auth/external/callback and leaving intact all of the remaining data from ? on in the URL line which I copied from the Open Website button during the integration configuration process. I also tried adding the SSL port onto the address, but that prevented me from getting to the Withings portal.

vangorra commented 4 years ago

A recent change to Home Assistant's underlying libraries has made this super confusing. Duplicated and worked around in #36053

scstraus commented 4 years ago

I have my base url set to https://MY_NABUCASA_ID.ui.nabu.casa/ and it works correctly. I don't use external_url at all. If you are using nabu casa, why do you need it?

haddood commented 4 years ago

I got to work with 2 profiles. I noticed that the call back from withings is using the internal url. I just put the same duckdns domain without port for internal url. no base url. not sure what are the implications for that. in the router I have external ports 8123 and 443 pointing to internal 8123 Home Assistant 0.110.5 external url: https://(mything).duckdns.org:8123 internal url: https://(mything).duckdns.org

TheNetAdmin commented 4 years ago

Hi all, I know that this issue is long closed, but I found it difficult to make this work with nabu casa, so I thought I'd share my config. Most important thing is to set your callback URI in withings config to your nabu casa URL plus /auth/external/callback So with recent versions of homeassistant (I tried on .107.7) it will look something like the below:

https://YOUR_NABU_CASA_ID.ui.nabu.casa/auth/external/callback

That's different than many of the formats shown above which threw me off. The above format works for me. Once you set it that way, you can easily add the integration from the integration pane.

In addition, please note there is no / at the end of URI.

So this is correct:

https://YOUR_NABU_CASA_ID.ui.nabu.casa/auth/external/callback

But this is wrong:

https://YOUR_NABU_CASA_ID.ui.nabu.casa/auth/external/callback/
scstraus commented 4 years ago

I had the same problem so I made a pull request against the documentation. It's now correctly shown in the documentation, Frenck also separated out the instructions for nabu casa cloud and the more advanced configuration for people who are managing exposing their hass instance to the outside world themselves, so may help some of those cases where people are having problems above.

Hooch76 commented 4 years ago

I've seen that the issue is closed, but I wonder if anyone could provide some tips for securing the public URL then. I am using a custom certification authority with user certs so that Home Assistant can only be reached if you've got the right cert using apache reverse proxy (I know that this won't work with the callback URL requirement from the Withings API). I could set up another subdomain (e.g. sub2) with a public (letsencrypt) cert but Home Assistant would be exposed to the internet without an additional layer of security. Would it still work when restricting access to /auth/external/callback only for sub2? And/or only allow POST or something like that?

vangorra commented 4 years ago

Asking in the home assistant community forums is where you will likely find the most assistance with systems administration questions. The github issues is for discussing the code and issues.

Hooch76 commented 4 years ago

Fair enough ... but I guess that "the guys over there" in the Home Assistant forum won't be able to help much. I am basically searching for detailed information about what the Withings API is expecting when contacting the callback URL. EDIT I think I just found the answer here: https://developer.withings.com/oauth2/#tag/glossary

Callback URL

Partner URL called by our system to send notifications through HTTP POST requests. Make sure that your server can handle a HTTP HEAD request called to verify the validity of your url.

Your URL must :

starts with https
be a valid URL, provided as a URL-encoded string. Please refer to w3schools URL encoding reference to learn more about URL encoding.
not be greater than 255 characters.
neither contain an IP or 'localhost'. Only port 80 and 443 are allowed.
vangorra commented 4 years ago

The code is a good reference. https://github.com/home-assistant/core/blob/dev/homeassistant/components/withings/__init__.py#L176

ajboelen commented 3 years ago

I today had issues connecting a withings account to Home Assistent. After reading all comments I copied the exact url that was in the "internal URL" field with "auth/external/callback" added to the end, into the url-field in the withings API settings.

This was in my case something like "http://myservername.local:8123/auth/external/callback" where this part "http://myservername.local:8123/" was in the internal URL field in the HASS settings. It complies in no way to the Withings callback URL criteria since it has no SSL, contains another port than 80 or 443 and is unreachable from the internet...

When leaving the Withings API connection in the Dev (and not Prod) setting Withings will accept that URL.

Added the next bits to the configuration.yaml

# Withings entry
withings:
  client_id: [as given by the Withings API]
  client_secret: [as given by the Withings API]
  profiles: [profilename1], [profilename2], [profiliename3]

and it worked like a charm. I had to add the last line with 'profiles:' else HASS indicated my config was incorrect.

Hope this helps others struggling with this connection.

Raptor607 commented 3 years ago

I bounced back & forth trying most everything listed by others above. What worked for me in the end:

  1. in HA General Settings, I left external URL blank and internal set to http://hassio.local:8123/
  2. Callback set to https://YOUR_NABU_CASA_ID.ui.nabu.casa/auth/external/callback
  3. Added the configuration via my local HA instance (NOT the Nabu Case instance)