I was looking at the documentation to find some more information about how the authentication mechanism works.
To me it seems it is purely JavaScript based which is a little sad. I was hoping to find a URI somewhere which people can directly access after authenticating and where the authentication bearer will automatically be sent to. That URI should then respond with the respective HTTP code 2xx or 4xx.
The use case I have in mind to re-use existing authentication together with NGINX reverse proxy and it’s auth_request option for conditional forwarding to backend servers.
Can somebody say if such URI exists already somewhere in HASS or whether this might be considered for implementation as a feature request?
Any solution on this topic? I’m trying to run without supervised install and trying to add some more features as iframe panels that run on behind nginx proxy on sub-path. But I would like to reuse authentication from home assistant using exactly this subrequest nginx feature.
I’m also interested in using nginx’s auth_request module for implementing internal webservices in has using iframe panels.
Is there a subpage which responds with http 200 if a user is authenticated or with 4xx if the user is unauthenticated?
Eventually I found https://github.com/vouch/vouch-proxy that’s supposed to have support for Home Assistant auth and serve as auth_request provider for nginx. Once I get the config right I’m posting updates.
Just to understand this. So let’s say I have a docker install of HA, will I be able to display the UI of another docker component - say zigbee just like what supervised does with add-ons?
exactly!
if webview has the ability to pass user‘s current bearer token, nginx would be able to pass this token to ha’s rest api using auth module to check validity of these tokens.
I can also provide a nginx example config if nessecary.
location / {
set $bearer $arg_access_token; # has delivers a valid token within the url (?access_token=xxxxxxxxx), this can also be done using a request header
auth_request /auth; # redirects authentication request to internal page
proxy_pass http://webserver:80; #passes request to backend if authenticated
}
location /auth {
proxy_pass http://homeassistant:8123/api/; #has api which delivers a http status: 200: authenticated, 40x: forbidden
proxy_pass_request_body off; #nginx doesn‘t take care about the request body, because only the http status is nessecary
proxy_set_header Content-Length "";
proxy_set_header Authorization "Bearer $bearer"; #delivers the access_token from above to has api as described in api documentation
internal; #page can only be accessd inernaly from nginx
}
Does that work for you? I’m getting Failed login attempt from Home Assistant Log and I don’t see any access token in URL.
I’ve added it this way:
server {
server_name nuc.local;
listen 80 default_server;
location /esphome/ {
set $bearer $arg_access_token; # has delivers a valid token within the url (?access_token=xxxxxxxxx), this can also be done using a request header
auth_request /auth-check; # redirects authentication request to internal page
proxy_pass http://localhost:6052;
rewrite ^/esphome/(.*)$ /$1 break;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
location /auth-check {
proxy_pass http://localhost:8123/api/; #has api which delivers a http status: 200: authenticated, 40x: forbidden
proxy_pass_request_body off; #nginx doesn‘t take care about the request body, because only the http status is nessecary
proxy_set_header Content-Length "";
proxy_set_header Authorization "Bearer $bearer"; #delivers the access_token from above to has api as described in api documentation
internal; #page can only be accessd inernaly from nginx
}
location / {
proxy_pass http://localhost:8123;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
Here’s a new NGINX config which works very well for my purposes:
proxy_cache_path /var/cache/nginx/homeassistant_ingress keys_zone=homeassistant_ingress:1m max_size=2m; # cache for access tokens
map $http_upgrade $connection_upgrade { # handles websocket request to has backend
default upgrade;
'' close;
}
server {
include snippets/server.conf;
include snippets/ssl.conf;
listen 443 ssl http2;
server_name myhass.domain.tld;
set $homeassistant 'http://homeassistant:8123'; # homeassistant backend
location ~ '^/ingress/app1/(?<bearer>[^/]+)' { # Adds a subdir in the format https://myhass.domain.tld/ingress/app1/longlivedaccesstoken-from-has/ and extracts the access token to variable bearer
set $ingress 'http://192.168.1.14:80'; # Proxy backend
proxy_set_header Authorization "Basic xxxxxxxxxxxxxxxxxx"; # Adds basic auth to proxy backend, if needed
rewrite ^/ingress/[^/]+/[^/]+(/.*)$ $1 break; # rewrites /ingress/app1/token to /
auth_request /ingress/authorize; # validate has access token
proxy_pass $ingress; # proxy pass to backend
}
location ~ '^/ingress/zwave/(?<bearer>[^/]+)' { # Adds a subdir in the format https://myhass.domain.tld/ingress/zwave/longlivedaccesstoken-from-has/ and extracts the access token to variable bearer
set $ingress 'http://zwave:8091'; # zwave2mqtt backend
proxy_set_header X-External-Path $request_uri; # required for zwave2mqtt - see manual on github
rewrite ^/ingress/[^/]+/[^/]+(/.*)$ $1 break; # rewrites /ingress/zwave/token to /
auth_request /ingress/authorize; # validate has access token
proxy_pass $ingress; # proxy pass to backend
}
location ~ '^/ingress/authorize$' { # checks access token using has api
proxy_pass_request_body off; # disable body, because not needed
proxy_set_header Content-Length "";
proxy_set_header Authorization "Bearer $bearer"; # adds bearer token from above (has long lived access token) to the request
proxy_cache homeassistant_ingress; # name of proxy cache (1st line)
proxy_cache_key $bearer; # item to cache
proxy_cache_valid 200 60s; # caches successful checked tokens for 1 minute. so we dont't have to call has api for every request
proxy_ignore_headers Cache-Control Expires Set-Cookie; # ignores cache header. required for caching the token
internal; # makes site not accessable form external
proxy_pass $homeassistant/api/; # proxy pass to hass api
}
location ~ '^/' { # location for has webinterface
include snippets/proxy.conf;
proxy_pass $homeassistant;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
So after you got a long lived access token from has, you can add a iframe panel to lovelace ui with the following url: /ingress/zwave/39q48pzm59t8qg34938434pq83z3485 mz239453485435/
asuming your token is 39q48pzm59t8qg34938434pq83z3485 mz239453485435
Please notice the slash after the access token.
Thanks. But unfortunately I have only white empty page within iframe. I have no idea how to get it to work. Nginx logs shows the follofing (url and token are changed):
It would be great to allow to check current users access_token instead of having to create long lived ones, so cancelling user would not pose a rick of user being aware of those long living authenticated URLs