Other software can directly use nginx as a proxy to add authentication, but this hass is really strong in user security and privacy. To be a proxy, you need to configure a whitelist, and the supported three-party authentication is not suitable for my needs. I have to change the source code. OK, later I found a compromise without changing the source code
reference article
- External Authentication
- Authenticating with external auth and oauth2_proxy to bypass homeassistant auth
- Authentication Providers
- HTTP (nginx proxy hass)
Deploy hass in containerd and integrate sso
I deployed it to kubernetes, refer to the link
Login hass locally and create a long-lived token
hass configuration file
# 配置nginx代理
http:
use_x_forwarded_for: true
trusted_proxies:
- 10.234.104.88 #这个地址是nginx服务的ip地址
nginx configuration file
server {
listen 86;
listen [::]:86;
server_name localhost;
#替换响应中的内容,类似于string.replace函数
sub_filter '<head>' '<head><script>window.externalApp={getExternalAuth:function(){window.externalAuthSetToken(true,{"access_token":"第一步创建长期的令牌","expires_in":248832000});},revokeExternalAuth:function(){window.externalAuthRevokeToken(false);}};</script>';
sub_filter_once on;
location / {
proxy_pass http://localhost:8123;#hass地址
auth_request http://xxx/sso/auth;#sso鉴权接口地址
proxy_set_header Host $host;
proxy_set_header Accept-Encoding "";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header X-Real-IP $remote_addr; # //一层代理时是用户真实ip,二层代理时是第一台nginxip
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # //一层代理时没有值,多层代理里面会存储多个ip值,第一个值就是真实用户ip
proxy_set_header X-Forwarded-Proto $scheme;
}
location /api/websocket {
proxy_pass http://localhost:8123/api/websocket;
auth_request http://xxx/sso/auth;#sso鉴权接口地址
proxy_set_header Host $host;
proxy_set_header Accept-Encoding "";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $http_connection;
proxy_set_header X-Real-IP $remote_addr; # //一层代理时是用户真实ip,二层代理时是第一台nginxip
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; # //一层代理时没有值,多层代理里面会存储多个ip值,第一个值就是真实用户ip
proxy_set_header X-Forwarded-Proto $scheme;
}
location /auth/authorize {
# tell nginx that this request requires authentication with oauth2_proxy
auth_request http://xxx/sso/auth;#sso鉴权接口地址
# redirect back to the frontend and tell it to use external_auth
return 301 /?external_auth=1;
}
}
Format it:
<script>
window.externalApp = {
getExternalAuth: function() {
window.externalAuthSetToken(true, {
"access_token": "第一步创建长期的令牌",
"expires_in": 248832000
});
},
revokeExternalAuth: function() {
window.externalAuthRevokeToken(false);
}
};
</script>
Implementation process
- Users access port 86 of nginx
- nginx will first request the address http://xxx/sso/auth for authentication, and if the response code is 200, it will forward the request to the hass address http://localhost:8123
- If the authentication fails and an unauthorized response code such as 401 is returned, nginx will directly return a 401 error to the browser, and access to hass is prohibited. Please log in to sso for authentication first.
- Here nginx replaces the content of the response when proxying hass, and adds the content
sub_filter
in it<head><script>window.externalApp.......
. This is to tell hass to perform external authorization authentication. It will execute the getExternalAuth function to obtain the token, and return my long-term token directly here. Because we have done authentication in nginx, we will no longer authenticate here.