用 authentik 把 AD 账号接到 Cloudflare 控制台
用 authentik 把 AD 账号接到 Cloudflare 控制台
这次身份集成最终打通了 Windows AD → authentik → Cloudflare 控制台。域用户用 AD 身份登录 authentik,再点击应用卡片进入 Cloudflare。最后一个障碍竟然是卡片的地址:普通控制台首页只是书签,并不会自动发起这套 SSO。
本文基于 2026 年 9 月 16 日的部署记录。authentik 为 2026.8.2,连接两台可写域控和一台云端 RODC;完整控制台登录已由用户实际确认。下文域名统一为示例,不包含口令或客户端密钥。
把目录、密码和联合认证分开
AD DS ── LDAPS ── authentik ── OIDC ── Cloudflare Access
↓
Cloudflare Dashboard SSOAD 提供目录和密码验证,authentik 提供 OIDC 身份结果,Cloudflare 使用这个结果。这里只复用了已有 authentik,没有部署 AD FS。邮件域验证属于 Cloudflare 控制台 SSO 的另一层要求。
公网浏览器通过 HTTPS 访问反向代理,authentik 到域控则走 WireGuard 私网。在排查“Hub 通,远端 VPS 不通”时发现:操作系统有 wg0 路由,却没有匹配目标的 Peer AllowedIPs。路由与 Peer 选择必须同时验证。
下面地址属于文档网段,运行前替换为目标域控私网地址。
ip route get 192.0.2.10
wg show wg0 allowed-ips
wg show wg0 latest-handshakeshealthy 不代表登录页面可用
本次使用官方 Compose 的 PostgreSQL、server、worker,容器入口绑定回环地址,再由反向代理提供 HTTPS。依赖应随版本核对,不能直接复制旧版 Redis 部署。
初始容器全部 healthy,根路径返回 302,但最终页面 500。应用日志为:
PermissionError: [Errno 13] Permission denied: '/templates/if/flow.html'原因是宿主机空模板目录由 root 创建、权限 700,应用 UID 1000 无法遍历。调整该目录访问权限后,最终页面恢复 200;没有递归放开秘密文件。
curl -sS -L -o /dev/null \
-w 'HTTP=%{http_code} final=%{url_effective}\n' \
https://sso.example.com/跟随重定向能发现“根页面正常,登录页面失败”,但 200 仍不能替代真实登录。
LDAP Source:用专用读取账号,避免密码缓存
服务账号放在独立 OU,使用默认目录读取权限,没有授予 DCSync、改密或写目录权限。它是普通绑定账号,不是 gMSA;没有额外 MemberOf 也不代表没有主组身份。
| 项目 | 本次选择 |
|---|---|
| Server URI | 三台域控的 ldaps://FQDN |
| Bind CN | 专用账号 UPN |
| Base DN | DC=corp,DC=example,DC=com |
| 对象唯一标识 | objectSid |
| 用户与组同步 | 开启 |
sync_users_password | False,关闭向 LDAP 回写 |
password_login_update_internal_password | False,不在成功登录后更新本地密码 |
delete_not_found_objects | False |
姓名、邮箱和 UPN 使用对应映射。SID 保持身份关联,删除后重建同名用户会获得新 SID。按名称排除服务账号只是筛选方式,正式授权仍需要应用策略或准入组。authentik AD 文档
636 可连接,TLS 仍可能失败
三台域控最初都能连 TCP 636,却返回 no peer certificate available。检查必须覆盖服务器证书、私钥、Server Authentication EKU、FQDN SAN 和客户端信任链。
本次使用企业 CA,但 LDAPS 并不强制要求 AD CS。server 负责登录,worker 负责同步,两边都需正确解析 FQDN、信任 CA。只导入 CA 公钥证书,不能导入 CA 私钥。
最终通过 Source 配置要求 CERT_REQUIRED,逐台完成服务账号绑定和用户查询;移除可信 CA 的负向测试被拒绝。这个负对照比“连接加密成功”更能证明没有绕过身份校验。
本版本实际使用随机 ServerPool,URI 顺序不表示主用与备用。该行为来自已部署版本的代码,升级后应重新核对。
OIDC 报错:界面提示不等于根因
提供方使用 confidential client、openid email profile scopes,以及严格回调:
https://<team>.cloudflareaccess.com/cdn-cgi/access/callback回调不是 authentik 域名,也不是 dash.cloudflare.com。
首次 Cloudflare 测试提示 Application ID is likely incorrect,但 authentik 日志显示 Invalid grant_type for provider。Client ID 与回调都正确,实际错误是程序化创建提供方时 grant_types=[]。将允许类型修正为 authorization_code 后,重新发起完整授权流程,测试成功。旧 callback 带旧 state,不能反复刷新充当新测试。
使用该应用的 discovery 和 JWKS 核对公开端点:
https://sso.example.com/application/o/cloudflare/.well-known/openid-configuration
https://sso.example.com/application/o/cloudflare/jwks/元数据可读与授权码交换成功是两个验收步骤。authentik Cloudflare 集成
控制台 SSO 还需要邮件域连接器
Cloudflare 的身份提供方测试成功后,还需验证并启用自有邮箱域的 Dashboard SSO Connector。它要求控制邮箱域 DNS,不能注册自己不控制的公共邮箱域。当前官方文档说明该功能对所有套餐免费,并要求准备具有 SSO Connector Edit 权限的恢复 API Token。Cloudflare 控制台 SSO
本次保留原 Outlook 超级管理员,另用自有域邮箱作为日常 SSO 用户。邮件转发帮助接受邀请,但它不是完整邮箱服务。AD 的 mail、authentik 的 email、Cloudflare 成员邮箱必须一致。
在账户级成员设置创建连接器,添加平台生成的 TXT,验证后还要启用。“域已验证”与“连接器已启用”不是同一个状态。
最后检查 authentik 应用卡片:它仍指向 https://dash.cloudflare.com/,日志没有对应授权请求。改为 Cloudflare 实际生成的 SSO App Endpoint:
https://<team>.cloudflareaccess.com/cdn-cgi/access/sso/saml/<generated-id>地址路径含 saml 不表示 authentik 提供方已改成 SAML。应复制本账户真实生成的入口,不能手工猜 ID。随后同浏览器登录 authentik、点卡片、选择 IdP、确认授权、返回控制台,用户确认成功。
按边界排查登录,避免来回改凭据
可以把完整登录分为四次交接:浏览器到 authentik、authentik 到目录、authentik 到 Cloudflare 身份配置、Cloudflare 身份到控制台账号权限。每个边界留时间与请求标识,先确认失败发生在哪一段,再决定修改哪份配置。
| 失败位置 | 先看什么 | 为什么 |
|---|---|---|
| 首页 500 或资源无法加载 | server/worker 日志、数据库、代理转发 | 此时尚未到 AD 密码验证 |
| 用户可同步却密码失败 | LDAPS 信任链、FQDN、绑定测试与 flow | 读取目录对象与验证用户密码用的身份不同 |
| IdP 测试可登录,控制台找不到连接 | 邮件域连接器、已验证邮箱与账号权限 | 成功的 IdP 测试不自动覆盖控制台路由 |
| 应用卡片仍跳旧入口 | Launch URL 与提供者生成入口 | 手写 URL 会绕开应有交接 |
| 仅旧浏览器能登录 | 缓存会话、新浏览器验证与错误日志 | 旧 session 可能掩盖当前凭据或配置失败 |
LDAP 读取账号只需要完成指定范围的目录读取;用户认证与组映射要另测。同步出现用户名但缺正确邮箱,可能使后面的身份匹配失败。不能为了“先能登录”关闭所有邮件域或组限制;每次改过滤条件先记录新增/移除范围,确认没有把不该用 SSO 的账号一起放进去。
用证书与负对照建立真正的 LDAPS 验收
在 authentik 实际运行环境检查 CA 与名称,不只在管理员电脑上测试。下面是 TLS 诊断参考,FQDN 和 CA 文件须替换;服务器 CA 信任不会因为端口 636 开着而自动建立。
openssl s_client -connect dc1.corp.example.com:636 \
-servername dc1.corp.example.com \
-CAfile /path/to/ad-ca.pem \
-verify_hostname dc1.corp.example.com -verify_return_error </dev/null检查链、SAN、有效期和验证结果之后,再用应用实际库进行正确口令、错误口令和禁用测试用户的绑定对照。上面的 TLS 命令不验证 LDAP 权限;一个库允许连接池轮询多个 DC,也不证明每个 DC 的证书都可信。三台应分别验收,记录实际选中的服务器,避免随机池把一台错误藏成偶发失败。
更新 CA 或叶子证书后,还要确认 server、worker 和持久挂载使用了新内容,并做一次新连接。单独重启一容器、已有连接还在使用旧状态时,页面成功不能证明所有路径已更新。更新失败应恢复原信任配置,保留验证日志;不要以跳过校验作为验收结果。
禁用 AD 用户不会自动撤销所有会话
临时账号实验结果如下,测试对象最终均已清理:
| 操作 | 观察 |
|---|---|
| AD 新建账号并手动同步 | 用户及映射属性出现 |
| AD 禁用账号再同步 | authentik 对象仍存在、仍 active |
| 对禁用账号用正确密码绑定 AD | 拒绝 |
| AD 删除账号再同步 | authentik 对象仍保留 |
过滤器排除了禁用用户,且未启用删除缺失对象。新的密码验证失败,并不能证明已有 authentik 会话和应用令牌全部立即失效。停用要另外设计状态同步、会话撤销和受控回收。
完整 SSO 已跑通,但部署记录仍有运维缺口:MFA 尚未强制、HTTPS 续签部署钩子缺失、CA 私钥与数据库恢复备份不完整、服务账号轮换未闭环,小内存 VPS 也需要资源告警。成功登录不能代替这些验收。
排查时按层推进:最终页面 → LDAPS 身份验证 → 目录同步 → OIDC 回调 → 邮件域连接器 → 实际启动入口。这样比在每个失败页面上重新输入密码更容易找到原因。
本文日期采用主 KB 首次 Git 提交日期 2026-09-16(UTC+8),提交 9682da8。操作与评测时间在正文单独注明;写作期间未连接或修改生产设备。
