Ios: Basic auth in addition to native auth?

Created on 10 Jan 2019  ·  22Comments  ·  Source: home-assistant/iOS

I'm trying to get HTTP Basic Auth working for my HASS (iOS app v1.5.0 (34) beta from Testflight and HASS v0.84.6). When validating the connection, the webview asks for the basic auth username/password and then continues to the normal hass login.

Questions:

  • Is the Basic Auth setting the iOS app used _in addition_ to the native HASS auth (as en extra layer of security), or is the Basic Auth meant to replace the native auth?
  • How can I help debugging this further?
feature-request

Most helpful comment

Home-assistant is a fast paced code base, and while it 99% likely is perfectly safe, we never know what might show up down the road. A tiny mistake or wrong assumption might (worst case) turn into a worm-able vulnerability. Many people don't upgrade home-assistant regularly either.

Security is built in layers. Adding a layer of basic auth makes so much sense here. What's the chance that there's an exploitable vulnerability in BOTH nginx and home-assistant? :)

We ought to be able to change the lock to our house.. Or use two locks if we feel paranoid.

All 22 comments

Hi @jschlyter,

After auditing the HTTP basic auth code (I didn't write it) I've found a few holes that i've patched in c6d10a13b751ddd220b266677c9d5e3110a71267. However, I have been unable to properly test HTTP Basic I believe due to random 401's on the API. Can you share your setup details, including configuration, so I can get a working test environment going?

For reference, here's my relevant NGINX config:

server {
  listen 8124;

  proxy_buffering off;

  auth_basic "Home Assistant Basic Auth";
  auth_basic_user_file /usr/local/etc/nginx/htpasswd;

  location / {
    proxy_set_header Authorization "Bearer TOKEN";
    proxy_pass http://localhost:8123;
    proxy_set_header Host $host;
    proxy_http_version 1.1;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
  }

  location /api/websocket {
    proxy_set_header Authorization "Bearer TOKEN";
    proxy_pass http://localhost:8123/api/websocket;
    proxy_set_header Host $host;

    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
  }
}

Also, just to be perfectly honest here, I am strongly considering HTTP Basic Authentication from the app since it was implemented just before the new authentication system thus it is no longer required as much. But, if I can get a test setup going, I guess i'm okay with leaving it in the app with the understanding that it is not recommended and could break randomly.

Also, to directly answer at least Q1, yes, you should be able to use basic auth in concert with native auth

I'm using https://caddyserver.com/ with the following Caddyfile:

 hass.example.com {
   tls [email protected]
   basicauth / username password
   proxy / localhost:8123 {
     transparent
     websocket
   }
 }

For the moment, I'm using the above without the "basicauth" part and it
works just fine (although exposing HASS a bit too much to the
Intertubes).

@robbiet480 It would be disappointing if basic authentication was removed. I'd like to use it for device-level authentication in place of client certs on iOS. As I mentioned in #26, the Authorization header isn't being sent so the server responds with 401 Authorization Required as expected.

I've tried with both the legacy API password and the token authentication scheme to no avail. Unfortunately I'm not set up to do iOS development but I'm happy to help you test builds. The nginx configuration you're using above should work fine.

@jschlyter You're using the basic auth fields in the iOS app configuration screen? Basic auth works fine for me in the webview but the app doesn't appear to send the Authorization header. I don't understand how this is working for you.

@jschlyter @rcarz Thanks to both of you for your feedback.

@jschlyter I tried your Caddyfile, it works just like nginx does. I get an initial HTTP Basic auth request, complete it, login to HA, then once i'm on the dashboard I get a bunch more authentication requests, I assume from the ServiceWorker driving all the HA API interaction on the frontend. Is this what you see as well?

@robbiet480 Indeed, but that seems to be the case for normal webtraffic to the frontend as well. The "normal" requests work as expected, but all background API calls fails. I wonder if Basic Auth is doomed due to this.

@rcarz To clarify, it does _not_ work with basic auth at the moment - neither with the iOS app nor with a webbrowser.

Following up on this, I'm again leaning towards removing basic auth as of 2.0 as it will feature amazing support for mobile_app which enables the app to send _all_ requests via a single URL that has been hardened for security. Even better, if you subscribe to Nabu Casa it will become a "cloudhook" automatically, so you will never need to have a open port in your router again!

My recommendation for those using basic auth is to either stop entirely in favor of closing the port in their router and using a Cloudhook or to carve out a basic auth exception for the webhook routes that mobile_app will use.

How does this sound to y'all?

The problem with this is, afaik it is basically a piece of untested code (in comparison to nginx which serves billions of request probably every hour or day) which has the responsibility to keep people away from your very personal data, power plugs, maybe cameras...
And nabu casa... I never saw any numbers but as far as i know just very few people used it or even still use it. So please, keep the Basic Auth. robbie 👍

Off-topic... any release date estimates for the 2.0? ;)

@robbiet480 I prefer to open a port than rely on a third party system so the cloud hook option has no appeal to me. Is there a technical reason you prefer to remove basic auth? I'm sure the hardened URLs are a great feature, but I trust nginx far more than a relatively immature codebase with full access to my home's lighting and other systems. Ideally I would like to use client certs, but the WebKit bug is preventing that on iOS. I think the next best option is basic auth.

I'm unable to get HTTP Basic Auth + Native auth working in 1.5.1 from the app store. I'm using a very simple nginx config similar to what @robbiet480 included above. It works fine from a desktop web browser but when I try and "Validate and Save Connection Settings" in the app I get prompted several times for credentials and eventually it fails.

Count me in as one who would prefer basic auth as a perimeter security control.

Let me just emphasize the importance of the extra layer of security that HTTP Basic Auth would provide. I urge @robbiet480 to make the necessary adjustments to support this before the next release - it would help people exposing their instances on the public Internet significantly.

Pushing people to trust a single authority was always something HA was fighting against, but Basic Auth has to die for Nabu Casa? 🤷‍♀️ 😢

Home-assistant is a fast paced code base, and while it 99% likely is perfectly safe, we never know what might show up down the road. A tiny mistake or wrong assumption might (worst case) turn into a worm-able vulnerability. Many people don't upgrade home-assistant regularly either.

Security is built in layers. Adding a layer of basic auth makes so much sense here. What's the chance that there's an exploitable vulnerability in BOTH nginx and home-assistant? :)

We ought to be able to change the lock to our house.. Or use two locks if we feel paranoid.

I absolutely agree. Putting an additional layer of security in front of home assistant should be a requirement for security minded people if you think about what they might control with it (door lock, webcam, ...).

I would agree that basic auth is necessary for a secure self-hosted environment.
Let me explain why from my point of view:
During the last years I have invested much time to build up a secure home network environment for automation and IoT devices, using separate VLANs, firewall rules and so on. It does not feel right to open "uncontrolled" access from the internet to a device or a service within "the heart of my home zone": Home Assistant.
Home Assistant has done a lot right in its design to make it a secure service while still offering a lot of features to its users. I think the service by Nabu Casa is the right way - for people who "just want to do home automation", but do not care about the rest. It's easy and has a well designed integration.
But for all other people who are love home assistant by its privacy and all-local/cloud-less design, it should still be possible to host and/or secure everything them self.

Let's compare it with a company: From my experience in a security concept you would never offer a public service by opening and forwarding a port directly to an internal server. Not even when filtering and whitelisting only a single url. Because, if you are in, you are in. They would firewall the service and put it in a DMZ, then forward authorized requests from the DMZ to the internal network.

As its not really possible to apply the DMZ architecture here, you could provide an extra layer of security with basic auth:
User <-> Webserver Apache/Nginx or HAProxy w. BasicAuth <-> HA instance
or:
Attacker <-> Webserver (<-> HA instance).

Finally, I would really love to have the possibility to add a second layer of security - so that I can sleep better ;-) The easiest here wold be BasicAuth I guess, as TLS Client Certs don't work on iOS..., VPN has to be established each time, ...

Last but not least, thanks to all home assistant developers for your great work!

Hi,

New user of Home Assistant, longtime user of OpenHab, and HA is a breath of fresh air. Really digging it and migrating everything over.

Today I configured my external access and Nginx rev proxy worked great until I tried basic auth over the top which of course led me here!

Is this a thing, 6 months on? I strongly agree with the sentiment in this thread.

Niether the web app in Chrome on my mobile, nor the Android v 1.9.0-167 were happy with my meddling when basic auth was on.

Manged to get the Android App to work just once with basic auth, by using the https://proxuser:[email protected] inthe app config home assistant URL field.
After that one time, it refused after restarting the app and will spam requests for the basic auth credentials, but not actually work when entered, it will spam with 'unable to connect to home assistant' as you enter creds.

The prox logs indicate user"-" being passed back by the Android App so it 401's..

Firefox, will accept a request with the above fulls creds in the URL method too and log in, this is so far what I'm using but hoping to get the app working for push notifications.

Im fairly certain all the config is what it'd need to be, there are a number of services exposed behind the rev proxy and Hass does work once I remove the basic auth.

Anyone know the formula to get the Android App to work with basic auth?

Edit: ...or is it not really supported at all and im wasting my time attempting for this extra line of security?

Running HassOS 4.9 and 0.110.5 core and as mentioned Android v 1.9.0-167

Thanks dev's this is an excellent app, loving the availability of tools for when I stuff up it tells me why and how! How many wasted hours on other platforms where debug tools barely exist.

The latest I have to say on this: Still not opposed to adding but same issues remain. WebSockets don't support basic auth on iOS. I am happy to accept a PR to add basic auth, but as its something I personally don't use, I have no interest in adding it myself.

Could we use client certs instead of Basic Auth?

Logistically speaking I do not believe this is _possible_ to implement basic auth in the app in a way that isn't either difficult to understand or significantly less secure.

The HTTP protocol uses the Authorization header for both basic (value like Basic <base64>) and token (value like Bearer <token>) authentication, which means we would be unable to simultaneously send a 'basic auth' value and an API token to API requests, which must work to use the app. The HTTP spec does suggest you can comma-separate multiple values here, but in practice effectively nothing supports this.

Practically speaking this means you would need to either (1) disable authentication on your Home Assistant instance for the API, or (2) encode your authorization token in your reverse proxy.

any news here? :>

AFAIK, only a parallel discussion with a workaround solution for android: https://github.com/home-assistant/android/issues/526

Agreed on the point regarding the Authorization header.

Assuming solutions like client TLS certificates (PKI too complicated to set up and manage), or other hacks such as putting a secret in a custom HTTP header, perhaps a slightly better solution would be to encode a secret token in the URI for the API endpoint? This value could be checked on the HomeAssistant HTTP server or checked and rewritten on the reverse proxy.

This isn't a great solution as it would be security by obscurity and a bit hacky, but I'm not too keen to expose something as powerful as HomeAssistant or something that presents the opportunity to laterally traverse into my home network without some additional protection, especially something that could be programmatically discovered as noted above.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fi-sch picture fi-sch  ·  3Comments

adec picture adec  ·  5Comments

wolverinevn picture wolverinevn  ·  3Comments

henrikbjorn picture henrikbjorn  ·  7Comments

wilfredsmit picture wilfredsmit  ·  5Comments