如何优雅地搭建自己的 SSO
本文最后更新于:2023年2月20日 中午
前言
本文主要介绍基于 Nginx Proxy Manager 搭建 Authelia,实现一个统一的认证界面(SSO)。
单点登录 (英语:Single sign-on,缩写为 SSO),又译为 单一签入 ,一种对于许多相互关连,但是又是各自独立的软件系统,提供 访问控制 的属性。当拥有这项属性时,当用户 登录 时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以 轻型目录访问协议 (LDAP)来实现,在服务器上会将用户信息存储到 LDAP 数据库中。相同的, 单一退出(single sign-off)就是指,只需要单一的退出动作,就可以结束对于多个系统的访问权限。
可以给例如 Frp、Tachidesk-Server 等只有基本访问认证(Basic access authentication)的应用添加一个更安全好用的认证界面。具体的效果可以参考一下 我的 Frp 面板。
Authelia is an open-source authentication and authorization server and portal fulfilling the identity and access management (IAM) role of information security in providing multi-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for common reverse proxies.
Authelia 是一个开源的认证和授权服务器和门户网站,履行信息安全的身份和访问管理(IAM)角色,通过一个门户网站为你的应用程序提供多因素认证和单点登录(SSO)。它可以作为普通反向代理的伴侣。
由于是基于 Nginx Proxy Manager,建议先看完前两篇相关教程:
步骤
1. Nginx 配置文件
保存文件 authelia-location.conf
和authelia-authrequest.conf
到容器内可以访问的位置 (./data)
。例如若保存到./data/authelia-location.conf
,则容器内可以用/data/authelia-location.conf
来引用。
authelia-location.conf
location /authelia {
set $upstream_authelia http://authelia:9091/api/verify;
## Essential Proxy Configuration
internal;
proxy_pass $upstream_authelia;
## Headers
## The headers starting with X-* are required.
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_set_header X-Original-Method $request_method;
proxy_set_header X-Forwarded-Method $request_method;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Uri $request_uri;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Content-Length "";
proxy_set_header Connection "";
## Basic Proxy Configuration
proxy_pass_request_body off;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503; # Timeout if the real server is dead
proxy_redirect http:// $scheme://;
proxy_http_version 1.1;
proxy_cache_bypass $cookie_session;
proxy_no_cache $cookie_session;
proxy_buffers 4 32k;
client_body_buffer_size 128k;
## Advanced Proxy Configuration
send_timeout 5m;
proxy_read_timeout 240;
proxy_send_timeout 240;
proxy_connect_timeout 240;
}
authelia-authrequest.conf
## Send a subrequest to Authelia to verify if the user is authenticated and has permission to access the resource.
auth_request /authelia;
## Set the $target_url variable based on the original request.
## Comment this line if you're using nginx without the http_set_misc module.
set_escape_uri $target_url $scheme://$http_host$request_uri;
## Uncomment this line if you're using NGINX without the http_set_misc module.
# set $target_url $scheme://$http_host$request_uri;
## Save the upstream response headers from Authelia to variables.
auth_request_set $user $upstream_http_remote_user;
auth_request_set $groups $upstream_http_remote_groups;
auth_request_set $name $upstream_http_remote_name;
auth_request_set $email $upstream_http_remote_email;
## Inject the response headers from the variables into the request made to the backend.
proxy_set_header Remote-User $user;
proxy_set_header Remote-Groups $groups;
proxy_set_header Remote-Name $name;
proxy_set_header Remote-Email $email;
## If the subreqest returns 200 pass to the backend, if the subrequest returns 401 redirect to the portal.
error_page 401 =302 https://auth.example.com/?rd=$target_url;
❗注意:
- 将
authelia-authrequest.conf
中的auth.example.com
替换为你自己的 单点登录 所在的域名。 - 你的单点登录域名和你想要保护的域名需要在同一个 二级域名 下(例如 test.example.com 和 auth.example.com)!
如果以上配置文件过时,可以直接复制 官方文档 中提供的配置。
2. 搭建 Authelia
Nginx Proxy Manager 的 docker-compose.yaml
中添加一个新的services
:
authelia:
image: docker.io/authelia/authelia:latest
container_name: authelia
restart: always
environment:
- TZ=America/New_York
volumes:
- ./authelia:/config
当前目录下创建 authelia
文件夹,并在该文件夹内编辑配置文件 configuration.yml
,参考官方 示例文件 和官方文档。注意一下几个重点:
authentication_backend
中的 Provider 如果用file
,则path
设定为/config/users_database.yml
。authentication_backend: file: path: /config/users_database.yml
在
authelia
文件夹中创建users_database.yml
并写入:users: yourusername: displayname: "yourdisplayname" password: "yourpassword" email: youremail groups: - admins - dev
注意 修改对应字段,其中密码可以用下面的命令生成[1]:
docker run --rm authelia/authelia:latest authelia hash-password 'yourpassword' # Digest: $argon2id$v=19$m=65536,t=3,p=4$f421js0DWuywLiGSCrtMWQ$JtwCybWIQJDB/fDD7Ix0YUDUeaWRMnCqRuQ/A5XpVJk
将
Digest:
之后的部分替换yourpassword
。对于上面的例子,你就可以用yourusername
和yourpassword
来登录你的网站了。access_control
中的default_policy
设定为one_factor
(如果要默认所有网站都用totp
或webauthn
,则设定为two_factor
)。如果你需要设定为deny
,则需要配置好各个网站的访问策略。
可以用 这个网站 生成配置文件中需要的 secrets。
至此 Authelia 的搭建基本完成,首先验证配置文件没有问题:
docker run --rm -v $(pwd)/authelia:/config authelia/authelia:latest authelia validate-config --config /config/configuration.yml
保证没有 errors,然后开始运行即可:
docker compose up -d
如果要给某个用户添加 TOTP,在完成上述步骤后,执行下面的命令并更新access_control
:
docker run --rm -v $(pwd)/authelia:/config authelia/authelia:latest authelia storage user totp generate yourusername --config /config/configuration.yml
删除某个用户的 TOTP 可以执行:
docker run --rm -v $(pwd)/authelia:/config authelia/authelia:latest authelia storage user totp delete yourusername --config /config/configuration.yml
注意替换 yourusername
为你的用户名。
3. 使用 Authelia
首先你需要在 Nginx Proxy Manager 添加一个网站作为你单点登录的入口,即上文的auth.example.com
(注意替换成你自己的域名)。
其他保持默认即可,并配置 SSL。
然后对于你想要添加登录的网站,例如 frp.dov.moe,创建一个 Custom Locations
最后在 Advanced 中引用配置
❗注意:上面两张图的文件不同!
保存后访问你的站点,你就可以看到默认跳转到登录界面了。
后记
如果对安全有更高要求,可以添加复杂的访问策略,同时用 LDAP 作为第一要素认证的 Provider。