Ios: Allow using installed client certificate for authentication

Created on 24 Apr 2017  Â·  41Comments  Â·  Source: home-assistant/iOS

My setup has an nginx server reverse-proxying requests to HA using HTTPS and mandating a client side certificate.
Would it be possible for the app to show a list of installed profiles/certificates and use them for SSL challenges?

Sadly, iOS's Safari has a bug where the client side certificate isn't used with websockets and my remote access to HA is unavailable ever since 0.38.

enhancement

Most helpful comment

The recent Home Assistant security vulnerabilities reminds us of the risk of enabling remote access to our systems. Having support for client side certificates would minimize the risk that these vulnerabilities present as only authorized users would have access to the system in the first place.

My HA implementation includes nginx and provides support for client side certificates but unfortunately the Home Assistant Companion iOS app does not support these client side certificates. This requires me to use OpenVPN to securely access my system remotely.

In light of these security vulnerabilities I would like to ask once again that client side certificates be added to the home assistant companion iOS app.

All 41 comments

I was just about to implement a similar configuration for my setup too. So here's a me too for this feature request.

@shmuelzon I have a similar issue and have reported the bug to apple. Chrome for MacOS works for Safari for MacOS as well as any networking in iOS does not send the client cert over wss://

Sadly I do not believe this is an issue that can be fixed with an app update (but i am hopeful). I think it is purely in Apple's court.

@Shirk the issue you are mentioning doesn't relate to client-side certs, just BasicAuth creds.

@cmsimike I've also opened a bug at Apple only to have it closed as a duplicate with the original bug still open. A few iOS releases since then without a fix.

I did notice in the app that I don't get a popup for choosing a profile even for the 'regular' HTTPS requests so I was hoping the approach is different in an app than in the Safari browser.
As I have zero knowledge in iOS development, I was hoping it would be possible.

@shmuelzon Apple just confirmed my bug report is a duplicate and has closed it. Ahhhh Apple software "engineering"

Might want to check Open Radar and/or submit it yourself if you can't find it.

I doubt this works with the app, but I did manage to get client certificates working with Safari/iOS. I noticed the same thing @cmsimike mentioned above -- client cert details don't seem to get sent with WebSocket requests. Details here. Basically involves setting a short-lived access token in a cookie on browsers that make the initial request with a valid client certificate.

I can confirm that iOS websockets don’t pass any form of authentication. It’s not specific to hass.
I have client-side certs & http-auth working (the later being requested if the former is not passed) but I still have to add an exception for /api/websocket to not need any of them (api-password only on that location).
There are a few projects ok github that discovered this bug so far :(

Good to know I'm not crazy :)

The blog I linked above doesn't need to add any exceptions. It's basically a nginx lua script that tags browsers with a cookie when they make a request with a valid client certificate. The cookie is valid for a configurable time (enforced with HMAC of client id + timestamp), and is all completely seamless from a user perspective. The page loads in the same way that it would if the browser was sending client cert data for the wss request.

I don't know enough about iOS network stuff to know if this would work for the app. If the app sends client cert data along with the initial request, and accepts the cookie set in the response, it should work.

@sidoh did you get this lua script / cookie setup working on iOS with the HA page added to the homescreen? This works flawlessly for me when I open HA in Safari, but if I add that same page to the homescreen, I am unable to get past the login screen. It correctly prompts for my certificate, but it sits on the "loading data" spinner indefinitely, with no notable errors in the nginx logs.

Yeah, it works for me with a pinned page on the homescreen. I've had to force-refresh a few times. Is nginx seeing the /api/websocket request?

No, nginx doesn't see the request come through at all. I don't have a mac at home that I can tether my device to, otherwise I'd try to capture the safari console

Huh. You're not seeing a request for / either? Is it possible the browser is caching?

It's possible - I've done everything short of a factory reset, to no avail. I think I am experiencing https://github.com/home-assistant/home-assistant/issues/7123 at this point, which appears unrelated to this issue. I'll take my conversation over there so I don't pollute this one

I submitted this as a bug report to apple but it was close with no further info as 'duplicate'

@sidoh i can confirm that with your nginx lua script works in nginx (v1.4.6) and Safari (iOS 11 and MacOS 10.13) but doesn't work with the HA iOS App (v1.1.1).

Okay y'all. I think I'm going to close this issue. Even if client certificates get implemented in the app, it wouldn't fix the websocket issues which, after 3 years of being a bug, Apple/WebKit doesn't seem too keen to fix.

As an alternative security improvement to look forward to, I plan to implement support for Webhooks soon which will mean that you won't need to worry about authentication since we will only send data to HA via the webhook which won't expose any unrelated data.

I'm willing to reopen this once Apple/WebKit fixes the websocket issue.

I hope everyone understands.

I implemented a lua script in nginx using modifications to Chris Mullen's own work to support websockets with Safari. I've been working on patching the iOS app to send a client certificate if one is found in the application bundle. I'm making progress but I'm not done yet. Would you at least be willing to consider a pull request if I successfully implement it? Generating SSL client certificates and configuring a LUA script is not that difficult to implement in the grand scheme of the overall configuration required for use with nginx so it would be nice if the app could support that.

@chach17 I guess i'd be willing to implement support for this via your PR assuming it was a generic setup that anybody could use vs something tailored for your own uses. Furthermore, I'd suggest using the iTunes upload method like we do for push notification sounds already instead of requiring a custom app build with the certificate.

Even though the issue is closed - people will still find this on Google.

I used Chris "sidoh" Mullin's workaround and put it into a little script for Docker Images. Maybe this will be any use for you: https://github.com/dersimn/mqtt-smarthome-webui/tree/4f9039067547fea961d3545e5947e04297810721

These 3 are the important files for you:

  • Dockerfile
  • nginx.template
  • run.bash

@robbiet480 I have put together a working version of the app that uses client certificate authentication. Here are some notes, screenshots, and questions.

  1. When "Show advanced settings" is selected there is an additional toggle switch to enable the use of a client certificate. When that is enabled the "Choose Certificate" button is available.

  2. When you choose a certificate the default File Picker UI is displayed (screenshot 1) allowing users to select certificate files stored in iCloud or other apps acting as Document Providers (DropBox, etc.). The chosen certificate is imported into the Documents folder in the app's container. Once a certificate is selected a password can be entered for the certificate. Screenshot 2 shows completed form.

  3. One caveat is that the same certificate must also be installed on iOS so that it is visible in Settings.app -> General -> Profiles. This is easy to do by going to the Files app and downloading the same certificate. From there go to Settings.app -> General -> Profiles and select the certificate to install it.

  4. The server setup in Nginx to support client certificates is significant in order to overcome the core issue of Safari not presenting a client certificate when using WebSockets. With the 2.0 version of the iOS app and 0.9 version of Home Assistant, does it make more sense to merge my pull request into the iOS 2.0 beta? The use of WebHooks in the 2.0 version of the app eliminates all the complications in the Nginx setup, at which point I think client certificate support is pretty feasible.

  5. Please provide feedback!

IMG_0248
IMG_0249

As an update, I ported my changes over to the testflight/2.0.0/8 branch and reconfigured Nginx to do basic out of the box client certificate authentication (without Christopher Mullin's enhancements) and it works perfectly under the new webhooks architecture. @robbiet480, can I submit as a pull request for you to review? I can stand up a special instance of HomeAssistant and a client certificate to test against if needed.

Hey @chach17,

I was very happy to read what you've done and I wanted to thank you for your work.
One, technical, question: If you're using the iOS KeyStore for the certificate (as it probably should be), why do I need to also load the client certificate via the File Picker UI? Isn't possible to select an already installed certificate from a list instead?

Also, is there anywhere I can get your changes and test it out myself?

Thanks again!

@shmuelzon - I may have spoken too soon. I apparently didn't disable Chris Mullin's client certificate validation code properly on Nginx and once I did my version of the iOS app broke. So I need to go back and take another look at that but I believe I will get it working. You need to use the Document Picker because there has to be a way to import the certificate into the app first, although I admit I hadn't considered investigating the key store. Right now I am just storing it in the application's container in the Document folder. The certificate is password protected so I figured this would be acceptable. I will investigate the key store and see if there are better options there.

@chach17, to be honest, I don't really mind Chris Mullin's solution as I'll probably keep it around so Safari will keep on working. If the app will use the client certificate on the initial request, that's good enough for me as that's what's keeping me from using the app.

Thanks for working on this @chach17, looks good. Feel free to submit a PR (against the new-ios12 branch please). Be aware that this probably wouldn't make it into 2.0. Hopefully 2.1.

Is this setting available in the latest app on app store? Cannot find it yet.

Also according to https://bugs.webkit.org/show_bug.cgi?id=158345 , Webkit has added support of client certificate for websocket. I've tried out that without @chach17 's workaround on iOS 13.5.1 with Experimental Features -> "NSURLSession WebSocket" on, and it just works.

For now I'm using Safari to login to my homeassistant, but it'd be great if the app can also support such a feature.

Why is this issue still "Closed" as many people request this?

This feature is blocking me from switching from OpenHAB to HA.

@banholzer Agree with you too

Hmm, this is kinda sad that this wont be supported. Client certificates are not simply for authentication access to a specific service but can be used in a zero-trust model when doing things behind a strong WAF like CloudFlare. If I want to proxy my traffic through CloudFlare and ensure that all traffic is properly secured via that proxy it breaks how the iOS app talks to home-assistant if it is via web hooks or otherwise.

I would also really like to see this implemented at some level and webhooks (as I believe they're now implemented in the app) should make this trivial.

I'd have to read more into how an iOS app can read and use client certs on the system, but I suspect there is a way to kickoff that behavior will little code changes required, but I could be wrong.

Assuming client certificates installed on the system aren't working automatically, this is still a valid feature request.

Is this possible if NSURLSession is used for websockets? Or are webhooks used instead?

Adding my request for client certificates. For security reason, I’ve added the capability to my nginx / HA implementation and would like to be able to utilization the iOS companion app to access HA.

+1 on this ask. Is there any active development on adding support for certificates? @chach17 said he has his change in testflight/2.0.0/8 branch. Is it going to be ported to the latest version?

The recent Home Assistant security vulnerabilities reminds us of the risk of enabling remote access to our systems. Having support for client side certificates would minimize the risk that these vulnerabilities present as only authorized users would have access to the system in the first place.

My HA implementation includes nginx and provides support for client side certificates but unfortunately the Home Assistant Companion iOS app does not support these client side certificates. This requires me to use OpenVPN to securely access my system remotely.

In light of these security vulnerabilities I would like to ask once again that client side certificates be added to the home assistant companion iOS app.

+1 for me too. I agree with @flyboy013 that it would make sense to allow people the option to use client certificates to provide defence in depth.

+1 for me currently having to use a VPN for iOS app access and CloudFlare access behind a service token for things like custom Alexa, etc. Would prefer everything behind CloudFlare with client certs.

+1 for me too. Client certificates provide a very secure way of accessing home-assistant without having to rely on VPNs, which may provide an ever bigger attack surface if not configured correctly.

+1, Security functions needs to be built-in.
Application layer controls do not replace lower layers like client certificates that help reduce attack surface significantly by preventing access to potentially vulnerable application functions.
The recent vulnerabilities serve as a reminder that defense in depth is a good principle to apply.

subscribe

Yep if websockets don't work due to websockets, I'd love to see a fallback to http.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

fi-sch picture fi-sch  Â·  7Comments

andynbaker picture andynbaker  Â·  3Comments

wolverinevn picture wolverinevn  Â·  3Comments

Nicxe picture Nicxe  Â·  8Comments

riemers picture riemers  Â·  11Comments