Last active
October 1, 2018 18:57
-
-
Save xentac/64e022efee918f704400b6e1b75897b7 to your computer and use it in GitHub Desktop.
Authentication with aggressive web worker caching
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| proxy-prefix = "/api/__oauth2" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!-- 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> |
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
Any tips on adapting this for basic_auth?