如何优雅地搭建自己的 SSO

本文最后更新于:2023年2月20日 中午

前言

本文主要介绍基于 Nginx Proxy Manager 搭建 Authelia,实现一个统一的认证界面(SSO)。

单点登录 (英语:Single sign-on,缩写为 SSO),又译为 单一签入 ,一种对于许多相互关连,但是又是各自独立的软件系统,提供 访问控制 的属性。当拥有这项属性时,当用户 登录 时,就可以获取所有系统的访问权限,不用对每个单一系统都逐一登录。这项功能通常是以 轻型目录访问协议 (LDAP)来实现,在服务器上会将用户信息存储到 LDAP 数据库中。相同的, 单一退出(single sign-off)就是指,只需要单一的退出动作,就可以结束对于多个系统的访问权限。

可以给例如 FrpTachidesk-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)。它可以作为普通反向代理的伴侣。

Authelia 单点登录

由于是基于 Nginx Proxy Manager,建议先看完前两篇相关教程:

步骤

1. Nginx 配置文件

保存文件 authelia-location.confauthelia-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;

❗注意:

  1. authelia-authrequest.conf 中的 auth.example.com 替换为你自己的 单点登录 所在的域名。
  2. 你的单点登录域名和你想要保护的域名需要在同一个 二级域名 下(例如 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。对于上面的例子,你就可以用yourusernameyourpassword来登录你的网站了。

  • access_control中的 default_policy 设定为 one_factor(如果要默认所有网站都用totpwebauthn,则设定为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。

参考文章


如何优雅地搭建自己的 SSO
https://blog.dov.moe/posts/61605/
作者
Dov
发布于
2023年2月19日
许可协议