ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Authelia 统一认证网关:用 TaoToken 打通 OpenID Connect 与双因素认证

Authelia 统一认证网关:用 TaoToken 打通 OpenID Connect 与双因素认证 1. 从一堆后台密码说起Authelia 到底解决什么问题如果你手里维护着 GitLab、Grafana、Jenkins、Portainer 这一串内部服务大概率经历过这种场面每个应用一套账号密码策略各不相同有人离职要挨个后台删账号某个服务甚至压根没有登录页只能靠反向代理里写个 basic auth 硬扛。Authelia 就是冲着这个场景来的——它是一个开源的认证授权网关自己不直接对外提供服务而是挂在 nginx、Traefik、Caddy 这类反向代理后面所有请求先过它这一关认证通过才放行到后端应用。它主要做三件事统一登录入口、双因素认证2FA、基于用户/用户组/路径/方法的细粒度访问策略。认证方式上第一层是账号密码第二层可以接 TOTP 验证码、WebAuthn 安全密钥YubiKey 这类 FIDO2 设备、Passkeys 无密码登录。反向代理兼容性也够广nginx、Traefik、Caddy、HAProxy、Envoy 都有现成的 ForwardAuth 接法。更关键的是Authelia 通过了 OpenID Certified 认证能作为标准 OpenID Provider 给支持 OIDC 的应用发身份这就把「反向代理层认证」和「应用层单点登录」两件事合到了一起。这篇面向的是已经有反向代理、有多个应用后台、想把登录收敛到一层网关的运维场景。我会给出configuration.yml的骨架、OIDC 客户端注册片段、双因素策略配置并演示怎么通过统一 Key/API 通道完成一次登录验证和回调排查。适合已经能跑起 Docker Compose、看得懂 YAML、但还没把认证层真正落地的人。2. 前置准备TaoToken 通道与 Authelia 目录结构在动手写配置之前先把两样东西备齐一个是 Authelia 的运行环境一个是统一 Key/API 通道。后者用于在验证阶段调用模型对话或编码能力做联调避免在多个应用之间来回切换凭证。TaoToken 的入口是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_end API 基址是 https://taotoken.net/api 注册后在控制台生成 Key 即可。Authelia 这边我建议用 Docker Compose 起目录结构保持清晰authelia/ ├── docker-compose.yml ├── configuration.yml ├── users_database.yml ├── secrets/ │ ├── jwt_secret │ ├── session_secret │ ├── storage_encryption_key │ └── oidc_hmac_secret └── data/ └── db.sqlite3几个 secret 文件用openssl rand -base64 48生成权限设成600别提交到 Git。users_database.yml里放用户和密码哈希哈希用官方命令生成docker run --rm authelia/authelia:latest \ authelia hash-password 你的密码输出的$argon2id$...整串贴进users_database.yml的password字段。这一步别偷懒用明文Authelia 只认哈希。TaoToken 的 Key 拿到后先存到环境变量里后面验证阶段会用到export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api注意Key 只放环境变量或密钥管理里不要写进configuration.yml或提交到仓库。Authelia 的配置文件里也不该出现任何第三方 API Key。3. 可复制配置configuration.yml 骨架与 OIDC 客户端注册先给一份能跑起来的最小configuration.yml骨架重点看default_redirection_url、session、storage、access_control、identity_providers这几块。# configuration.yml host: 0.0.0.0 port: 9091 log: level: info theme: dark default_redirection_url: https://auth.example.com totp: issuer: example.com period: 30 skew: 1 authentication_backend: file: path: /config/users_database.yml password: algorithm: argon2id iterations: 1 salt_length: 16 parallelism: 8 memory: 64 session: name: authelia_session secret: /secrets/session_secret expiration: 1h inactivity: 5m domain: example.com same_site: lax regulation: max_retries: 3 find_time: 2m ban_time: 5m storage: local: path: /data/db.sqlite3 encryption_key: /secrets/storage_encryption_key access_control: default_policy: deny rules: - domain: grafana.example.com policy: two_factor subject: - group:dev - group:ops - domain: portainer.example.com policy: two_factor subject: - group:ops - domain: public.example.com policy: one_factor identity_providers: oidc: hmac_secret: /secrets/oidc_hmac_secret issuer_private_key: /secrets/oidc_private.pem access_token_lifespan: 1h authorize_code_lifespan: 1m id_token_lifespan: 1h refresh_token_lifespan: 90m clients: - client_id: grafana client_name: Grafana client_secret: $pbkdf2-sha512$... public: false authorization_policy: two_factor redirect_uris: - https://grafana.example.com/login/generic_oauth scopes: - openid - profile - email - groups userinfo_signed_response_alg: noneaccess_control里default_policy: deny是安全底线别改成bypass。规则从上往下匹配two_factor表示必须过第二层认证one_factor只验密码。subject支持user:和group:两种写法用户组在users_database.yml里用groups字段定义。OIDC 客户端注册这块client_secret同样用哈希生成方式和用户密码一样docker run --rm authelia/authelia:latest \ authelia hash-password 客户端密钥redirect_uris必须和应用实际回调地址完全一致差一个斜杠都会在回调时报invalid_redirect_uri。authorization_policy: two_factor表示这个 OIDC 客户端登录时也强制双因素和反向代理层的策略是独立的。反向代理以 nginx 为例ForwardAuth 接法location /authelia { internal; proxy_pass http://authelia:9091/api/verify?rdhttps://auth.example.com; 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_pass_request_body off; } location / { auth_request /authelia; auth_request_set $user $upstream_http_remote_user; auth_request_set $groups $upstream_http_remote_groups; proxy_set_header Remote-User $user; proxy_set_header Remote-Groups $groups; error_page 401 302 https://auth.example.com/?rd$scheme://$http_host$request_uri; proxy_pass http://grafana:3000; }auth_request把每个请求先打到 Authelia 的/api/verify返回 2xx 放行401 就跳登录页。X-Original-URL这一串头必须带全否则 Authelia 拿不到原始请求信息策略匹配会出错。4. 验证请求一次完整登录与回调排查配置写完docker compose up -d起服务先看日志有没有报错docker compose logs -f authelia正常启动会打印Authelia is listening on 0.0.0.0:9091。然后访问https://grafana.example.com应该被重定向到https://auth.example.com。输入用户名密码如果策略是two_factor会进入第二因素页面用 TOTP 应用扫码绑定后输入 6 位验证码。验证 OIDC 流程时Grafana 侧配置[auth.generic_oauth] enabled true name Authelia client_id grafana client_secret 你的客户端密钥 scopes openid profile email groups auth_url https://auth.example.com/api/oidc/authorize token_url https://auth.example.com/api/oidc/token api_url https://auth.example.com/api/oidc/userinfo点 Grafana 登录页的 Authelia 按钮会跳到 Authelia 授权页确认后回调到https://grafana.example.com/login/generic_oauth。如果回调成功Grafana 会拿到id_token和userinfo用户自动登录。联调阶段如果想快速验证身份信息是否正确可以用 TaoToken 的模型对话能力做一次请求校验把拿到的userinfo丢进去做结构化解析。API 调用示例curl -s https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d { model: gpt-4o-mini, messages: [ {role: user, content: 解析这段 userinfo JSON列出 sub、email、groups 字段{\sub\:\u1\,\email\:\aexample.com\,\groups\:[\dev\]}} ] }返回里能看到模型把字段拆好了说明 OIDC 返回的身份信息结构没问题。这一步不是必须的但在排查groups没传对、email为空这类问题时比翻日志快。回调排查重点看三处Authelia 日志里oidc相关的error行、Grafana 日志里oauth相关行、浏览器 Network 面板里callback请求的响应体。常见的是invalid_redirect_uri和invalid_client前者对回调地址后者对client_secret哈希。5. 本篇常见错排查报错一invalid_redirect_uri。九成是redirect_uris和应用实际回调地址不一致。注意协议、域名、端口、路径、结尾斜杠都要完全匹配。Grafana 的回调是/login/generic_oauth别写成/login/generic_oauth/。报错二invalid_client。client_secret必须是哈希后的值不是明文。如果你在 Grafana 里填的是明文Authelia 侧存的是哈希两边对不上。正确做法是 Grafana 填明文Authelia 的configuration.yml里填哈希。报错三登录后无限重定向。通常是session.domain设错了。如果 Authelia 在auth.example.com应用在grafana.example.comsession.domain要设成example.com这样 cookie 才能跨子域共享。设成auth.example.com就会导致应用侧拿不到 session反复跳登录。报错四two_factor策略下 TOTP 验证码总是不对。检查服务器时间TOTP 依赖时间同步差超过 30 秒就会失败。totp.skew: 1允许前后一个周期但别依赖它兜底。用ntpdate或chronyd把时间校准。报错五access_control规则不生效。规则是从上往下匹配第一条命中就停。如果你把default_policy写在规则前面或者规则顺序反了就会出现该拦的没拦。另外subject里的组名要和users_database.yml里的groups完全一致大小写敏感。报错六OIDC 授权页报consent相关错误。检查scopes里有没有openid这是 OIDC 的必需 scope。缺了它Authelia 不会走 OIDC 流程。6. 把登录收敛到一层网关之后Authelia 落地之后最直观的变化是新增一个内部应用时不用再单独配账号体系了。反向代理里加一段auth_requestaccess_control里加一条规则OIDC 客户端注册一个应用侧填四个 URL 就能接上单点登录。用户那边只记一套密码加一个 TOTP运维这边只维护一份users_database.yml。如果你还在用 basic auth 硬扛或者每个应用单独发账号可以先把 Grafana 或 Portainer 接进来试一次。配置骨架和 OIDC 片段上面都能直接抄回调排查按第 5 节的顺序对一遍基本能跑通。统一 Key/API 通道在联调阶段用来快速验证身份信息结构比翻日志省事。接入文档和 API Keys 在控制台里都能找到模型对话入口适合做身份信息的结构化校验长期跑编码和 Agent 任务的话可以看 Coding Plan。
返回列表