Skip to content

Instantly share code, notes, and snippets.

@xentac
Last active October 1, 2018 18:57
Show Gist options
  • Select an option

  • Save xentac/64e022efee918f704400b6e1b75897b7 to your computer and use it in GitHub Desktop.

Select an option

Save xentac/64e022efee918f704400b6e1b75897b7 to your computer and use it in GitHub Desktop.
Authentication with aggressive web worker caching
When mixing cookie-based out-of-application authentication and a websocket
application that attempts to hijack all attempts at authentication, one needs to
pick ones battles. Sometimes allowing unauthenticated access is the only way to
do certain things.
Take, for example,
https://github.com/home-assistant/home-assistant-polymer/issues/110 and
https://github.com/home-assistant/home-assistant/issues/6184. The entire site is
driven by a webworker that caches all urls
(https://github.com/home-assistant/home-assistant-polymer/blob/3701683d4b4ab2bd0ceb4ab7842f40c29ee398a8/gulp/tasks/gen-service-worker.js#L93)
except /home-assistant-polymer/.*, /api/.*, /service_worker.js, /manifest.json.
If you were to use 302 redirects for all urls, you will confuse most http
requests made by the web worker. In the Home Assistant case, it interprets all
failed websocket connections (after 10 attempts) as requiring HTTP auth. This
means that normal 302 authentication redirects will always be thwarted.
To solve this, we will add extra html to the web worker and adding a few of our
own /api urls.
I use the bitly/oauth2_proxy so I have set my proxy-prefix to /api/__oauth2. My
hope is that Home Assistant won't make urls starting in /api/__ official
endpoints. The oauth2_proxy authentication url in /api/__oauth2/sign_in.
My nginx config allows /, /manifest.json, and /local/custom_ui/oauth.html
through without any authentication. This makes sure that the service worker will
never cache a 302 status code.
I have configured /api/__checkauth to return a 200 or a 404 if authenticated and
a 401 if not authenticated. The oauth.html requests that url and changes
window.location to /api/__oauth2/sign_in if it receives not 200 and not 404.
From there, authentication works all the time, as long as the Home Assistant
devs don't change the caching strategy for the url prefix I chose (originally I
used /local, but that was changed to "fastest" in the service worker).
# Instruct the web worker to load custom html to check for 302-based authentication requests
frontend:
extra_html_url: /local/custom_ui/oauth.html
extra_html_url_es5: /local/custom_ui/oauth.html
proxy-prefix = "/api/__oauth2"
<!-- Real path is www/custom_ui/oauth.html -->
<div hidden="" by-polymer-bundler=""><script>
window.oauth = window.oauth || {
init: function() {
var req = new XMLHttpRequest();
req.open('GET', '/api/__checkauth', true);
req.onload = function() {
if (req.status != 200 && req.status != 404) {
window.location = '/api/__oauth2/sign_in';
}
}
req.send();
}
}
window.oauth.init()
</script></div>
@abmantis
Copy link

Any tips on adapting this for basic_auth?

@jeffc
Copy link

jeffc commented Aug 9, 2018

Thanks, this issue has been driving me nuts and your explanation is super helpful! Would you mind posting the relevant chunk of your nginx config (specifically the __checkauth endpoint)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment