Cloudflare Access Control Web 服务接入 Agent 指南

本文面向为真实上线 Web 服务接入 Cloudflare Access Control 的 coding agent。它优先回答“生产服务该怎么接入、应用内权限怎么做、Dev Access 已打开时怎样验证”。Dev Access 的安装、配置和启动不在本文展开。

定位说明

Cloudflare Access Control 提供的是域名级访问控制和可信身份输入;它不会规定业务应用必须有哪些接口、角色或权限模型。本文中的 /api/whoamirolespermissions、reader/member/admin 等,是 Web 服务接入 Access 后推荐采用的应用层最佳实践,用于让前端获取当前用户状态、让后端统一做权限判断和审计。

如果现有系统已经有等价的 current user 接口、RBAC/ABAC 模型或审计体系,可以复用现有设计;关键要求是身份来自服务端可信入口,敏感操作由后端鉴权,前端不能自行声明用户或角色。

Agent Contract

核心模型

Browser
  -> Cloudflare Access 登录与策略校验
  -> 受保护的生产域名 / staging 域名 / 可选临时测试域名
  -> Web 应用 origin
  -> 应用内 auth middleware
  -> 业务路由权限判断

Access policy 适合表达“哪些邮箱、邮箱域名、IdP group 或 service token 能进站”。应用内 role / permission 适合表达 reader、member、admin 等产品权限,以及所有权判断。

origin 可以部署在正式服务器、容器平台、PaaS、内网服务,或测试期的 Dev Access 临时域名后面。部署形态不应该改变应用认证代码的核心契约:服务端从 Cloudflare Access 身份中解析当前用户,再进入自己的权限系统。

身份与权限约定

约定 Agent 实现要求
邮箱规范化 读取 Cloudflare Access email 后统一 trim + lowercase。例如 Alice@Fstln.io 归一化为 alice@fstln.io
真人用户默认域 默认真人来自 fstln.io。外部顾问或客户必须进入显式 allowlist,并单独分配应用角色。
业务主键 数据库使用自己的 users.idemail 用作唯一登录标识和审计展示字段,Cloudflare sub 仅作为辅助审计字段。
角色绑定 用完整邮箱绑定角色,例如 alice@fstln.io -> admin,不要只用邮箱前缀。
权限判断 后端优先判断 permission,role 只是权限集合名称。敏感 API 必须重复鉴权。
机器访问 CI、Webhook、service token 不伪装成真人邮箱,单独设计机器身份和权限。

推荐角色模型

最小项目可以用两个邮箱列表,但新项目更推荐使用显式 roles -> permissions 配置,避免管理员是否继承成员权限这类隐式规则。

roles:
  users:
    alice@fstln.io:
      - admin
    bob@fstln.io:
      - member
    reader@fstln.io:
      - reader

  permissions:
    reader:
      - read
    member:
      - read
      - upload
      - delete_own
    admin:
      - read
      - upload
      - delete_own
      - delete_any
      - manage_users
      - view_admin

后端接入决策

最小可用模式

只在 origin 无法绕过 Cloudflare Access 保护边界时,读取邮箱 header。这个边界可以由内网、防火墙、反向代理或平台网络策略提供;关键是外部用户不能直接伪造 header 打到 origin。

const raw = req.headers.get("cf-access-authenticated-user-email");
const email = raw?.trim().toLowerCase();

生产加固模式

推荐验证 Cf-Access-Jwt-Assertion,至少校验签名、issuer、audience,以及时间类 claim。

CF_ACCESS_TEAM_DOMAIN=https://<team>.cloudflareaccess.com
CF_ACCESS_AUD=<access-application-aud-tag>

禁止事项

开发与部署模式选择

目标 模式 命令或入口 Agent 判断
日常功能开发、离线开发、快速切换角色 AUTH_MODE=dev AUTH_MODE=dev DEV_AUTH_EMAIL=member@fstln.io npm run dev 默认优先使用;它仍应走同一套后端 roles / permissions 解析逻辑。
正式上线或预发环境 AUTH_MODE=cloudflare 生产 / staging 域名绑定 Cloudflare Access application 这是本文主路径。应用代码验证 Access 身份,然后使用自己的 roles / permissions 系统。
测试期通过 Dev Access 临时域名验收 AUTH_MODE=cloudflare Dev Access 已 Running 后打开被测端口对应的 HTTPS URL 只是部署和访问方式,方便在真实 Access 登录下测试尚未正式上线的代码;不是 Access Control 的必要组成部分。
自动化集成或 E2E 测试 AUTH_MODE=test 测试专用 X-Test-Auth-Email,仅 test mode 生效 测试身份只替代认证入口,不能绕过权限和所有权判断。

生产服务 Cloudflare 配置

为真正上线的 Web 服务接入 Access Control 时,先定义正式域名和应用身份边界。origin 部署在哪里是独立问题;它可以是服务器、容器平台、PaaS、负载均衡后的服务,或其他受控网络入口。

配置项 约定
Access application 在 Cloudflare Zero Trust 中创建 Self-hosted application,绑定生产或预发域名,例如 app.example.comstaging.example.com
Access policy 只表达谁可以进入这个域名,例如公司邮箱域名、指定邮箱、Google Workspace group、service token。
Team domain 用于后端 JWT 验签,例如 https://<your-team-name>.cloudflareaccess.com
AUD tag 使用当前 Access application 的 Application Audience (AUD) Tag。每个 application 使用自己的 AUD。
Origin 入口 按项目部署方案配置,可以是公开 origin、内网反向代理、平台入口或 Cloudflare Tunnel。这是部署路由问题,不是应用如何使用 Access Control 的逻辑。无论哪种方式,应用都应验证 JWT,或确保外部请求无法绕过 Access 直接到达 origin。
应用内权限 不要把业务权限都塞进 Access policy。后端根据 email / user id 映射 roles 和 permissions,并在敏感接口重复校验。

Dev Access 已打开时怎么测

前提:Dev Access 已经按它自己的使用说明完成配置并处于 Running 状态。本文不说明如何安装、导入配置或启动 Dev Access,只说明 Web 服务接入 Access Control 后如何借它验收。

  1. AUTH_MODE=cloudflare 启动被测 Web 服务,确保后端使用当前测试域名对应的 CF_ACCESS_TEAM_DOMAINCF_ACCESS_AUD
  2. 在 Dev Access 中打开或复制被测端口对应的 HTTPS URL。例如本机服务监听 3000,就打开 Dev Access 给出的 3000 端口 URL。
  3. 浏览器应先进入 Cloudflare Access 登录;登录成功后才回到你的 Web 服务页面。
  4. 访问应用的 /api/whoami 或等价当前用户接口,确认返回的是 Cloudflare Access 身份解析出的 email、roles、permissions。
  5. 分别用 reader、member、admin 等测试身份验证页面入口和后端 API 权限;无权限操作必须由后端返回 403。
  6. 如需确认 Dev Access 自身是否正常,只使用 Dev Access 使用说明里的 test 页;不要把 test 页结果当成你的业务应用鉴权已通过。

Security Boundaries

测试与验证

配置验证

应用 auth 测试

常见故障

现象 优先检查
Cloudflare Bad Gateway 检查项目自己的 origin route、负载均衡、健康检查、防火墙或平台 ingress。Access 登录成功只说明用户通过了边缘策略,不代表 origin 一定可达。
直接访问 localhost 不跳 Google 登录 这是预期行为。Access 登录只在请求经过 Cloudflare 边缘和受保护 hostname 时发生。浏览器本地开发可用 AUTH_MODE=dev,真实登录验收要访问受 Access 保护的生产、预发或 Dev Access 测试域名。
登录成功但应用认为未登录 检查后端读取的 header 名、JWT 验签的 CF_ACCESS_TEAM_DOMAINCF_ACCESS_AUD,以及当前域名是否使用对应 Access application 的 AUD。

Agent 执行清单

  1. 先确认任务是生产 Web 服务 Access 接入、应用权限实现,还是 Dev Access 已 Running 后的应用验收。
  2. 如果改 auth middleware,保证身份只来自服务端中间件,权限判断在后端执行,前端只消费后端 current user 结果。
  3. 如果涉及生产或预发 Access 接入,列出 Access application domain、Access policy、team domain、AUD tag、origin 防绕过策略或 JWT 验签策略。
  4. 如果只是 Dev Access 已 Running 后的应用验收,只确认被测端口 URL、Access application、AUD、policy 和应用运行模式,不在本文引入 Dev Access 安装或配置操作。
  5. 如果需要管理员配置,列出生产 Access 配置项,不要求用户把 secret 发到聊天中。
  6. 提交前补充或运行认证、权限、JWT 验签、角色和所有权相关测试。

文档分工检查

文档 只负责 不负责
install.html 下载安装 macOS app、处理首次打开和系统安全提示。 Access Control 代码接入、角色权限设计、业务应用测试。
dev-access.html 导入 Dev Access 配置、启动 Dev Access、确认 Dev Access 自身 Running 和 test 页可用。 业务 Web 服务如何实现 Access middleware、roles、permissions、JWT 验签。
本文 真实 Web 服务如何接入 Cloudflare Access Control,以及 Dev Access 已打开时如何验证业务应用。 安装 Dev Access、导入配置、解释本机 proxy/tunnel 细节。

此文件描述 Web 服务接入 Cloudflare Access Control 的开发约定,不替代 Cloudflare 官方文档或管理员控制台配置。