摘要
- RFC 10017 的 Backend for Frontend 是机密 OAuth 客户端。访问令牌与刷新令牌留在服务端,由 Cookie 会话关联,浏览器 JavaScript 因而不能窃取已有令牌,也不能单凭截获的授权码换取新令牌。
- 同一设计没有阻止恶意同源代码使用用户的活动会话调用合法 BFF 入口。剩余后果是客户端劫持:它弱于可携带到别处使用的令牌窃取,但威力取决于前端、BFF 与资源服务器实际开放了哪些动作。
- 可复核部署必须连接完整的请求—决定凭据:来源与前端版本、会话和 Cookie 策略、CSRF 结果、BFF 入口、允许的目标/路径/方法、令牌 audience 与 scope、资源服务器授权、响应处理、异常策略与补救责任人。
一次红队演练结束后,安全团队得到两个看似矛盾的结论。
浏览器里没有访问令牌,HttpOnly Cookie 也没有被脚本读走;与此同时,测试脚本仍然成功下载了只对登录用户开放的资料,并修改了一项账户设置。若审计只问“令牌有没有泄漏”,答案是成功。若它问“恶意代码能否借用户权限行动”,答案还没有结束。
整个过程可能没有绕过任何凭据检查。恶意代码运行在合法应用的同一来源,调用前端本来就能调用的 BFF 入口。浏览器自动附带会话 Cookie;BFF 找到对应令牌,转发请求;资源服务器按收到的主体和权限作出决定。错误意图沿正确管道到达。
这正是 RFC 10017《浏览器应用的 OAuth 2.0》划出的边界。该文件于2026年8月作为 IETF 最佳现行实践发布,作者是 Aaron Parecki、Philippe De Ryck 与 David Waite。2026年8月31日保存的 IETF Datatracker 将 Parecki 记为 SCIM 工作组联合主席,并列出包括 RFC 10017 在内的两份 RFC;他本人的网站则记载其身份标准工作、对 oauth.net 的维护及对 IETF OAuth 工作组的参与。
这些资料说明他为何值得追踪,却不把集体标准变成个人发明,更不证明任何具名系统已正确部署。BFF 的实际边界最终由每个运营者的运行配置和代码决定。
威胁从代码已经运行之后开始
许多 OAuth 安全讨论先争论把令牌放在内存、localStorage 还是 Cookie。RFC 10017 先接受一个更难的条件:攻击者已经能在应用执行环境中运行 JavaScript 或 WebAssembly。
这段代码不是站在来源外面的陌生调用者。它拥有与正常前端相同的浏览器权限,可以读取可访问的存储、调用函数、修改控制流程、操作同源上下文,也可以向后端发送请求。输出编码、依赖治理、Subresource Integrity、Content Security Policy 与来源隔离仍是第一道防线,因为只有阻止恶意代码执行,才能从根本上阻止客户端劫持。架构选择回答的是第一道防线失守后还能保住什么。
RFC 将 OAuth 相关路径拆成四类:一次性窃取现有令牌;持续捕获不断更新的令牌;不碰旧令牌而另启授权流程取得新令牌;以及完全不取走令牌,只从用户浏览器代理请求。
最后一类最容易被“安全存储”叙事遗漏。若浏览器或外部组件会为请求自动附上凭据,恶意代码只需模仿合法调用。凭据不可导出,并不等于凭据所代表的动作不可调用。
令牌离开 JavaScript,权限没有消失
RFC 10017 按安全性从高到低列出三种主要浏览器 OAuth 架构,BFF 位于第一位。服务端组件承担 OAuth 职责,作为机密客户端运行,并代理全部资源服务器交互。
这个流程建立两段不同关系。授权服务器把访问令牌及可能的刷新令牌发给 BFF;BFF 再用 Cookie 与浏览器建立会话。前端要访问受保护资源时,把请求连同 Cookie 发给 BFF。BFF 解析会话,移除出站请求中的 Cookie,选取正确访问令牌,再调用资源服务器。
这一设计确实消除了三条强攻击路径。JavaScript 没有现成令牌可取;持续执行也捕获不到轮换后的令牌流;攻击者即使得到新的授权码,也缺少机密客户端凭据,不能独立完成换取,PKCE 又保护授权码交易的另一面。
HttpOnly 还防止脚本直接读出会话状态,使客户端劫持不自动升级为可带走的会话劫持。攻击者失去来源内执行位置或用户关闭浏览器后,它的能力可能随之终止,这与可从另一台机器使用的 Bearer Token 明显不同。
但用户赋予应用的有限权限仍然存在,只是由服务端会话表示,并通过 BFF 入口提供。已经获得同源执行权的恶意代码仍可在会话有效时调用这些入口。RFC 因而把“通过用户浏览器代理请求”列为 BFF 模型下仍可行的攻击,把结果称为客户端劫持。
准确表述这条限制不是贬低 BFF。它让改进能够被正确检验:BFF 移除了浏览器中的独立、可携带权限,却无法在同一执行环境里自动区分好代码与坏代码。
BFF 是出口必须枚举的权限翻译器
BFF 把带会话的入站请求翻译成带访问令牌的出站请求。若这个翻译器允许任意目标,它就把安全隔离变成了令牌泄露代理。
RFC 10017 因此要求严格控制出站请求。BFF 必须验证目标主机,保存获准资源服务器的明确允许清单;动态路由必须严格验证主机与路径,避免用户输入把服务变成开放代理;按入口限制 HTTP 方法还能进一步缩小攻击面。
“允许这个主机”仍然太粗。同一主机可能同时有用户路径和管理路径;对 GET 安全的入口换成 DELETE 就可能危险;请求体里的回调地址、下游 URL 或重定向会在首个目标通过验证后越界。真正可审核的出口是一个组合:资源身份、scheme 与 host、路径模板、方法、请求结构、重定向规则、令牌 audience 和 scope。
资源服务器不是 BFF 的附属说明,而是另一个拥有最终决定权的主体。它仍应验证签发者、audience、到期时间与权限,并对具体对象和动作实施授权。宽权限令牌加宽代理入口,会让客户端劫持接近完整账户操作;窄入口和对象级授权,才能保留“应用能看本人账单”和“来源内任何代码能管理所有账户”的差异。
这也是最小初始规范的适用方式。共同标准可以规定机密客户端、受保护 Cookie、CSRF 防御和受限代理,却不可能替每家业务发布统一入口图。运营者必须公开或保留本地允许集合,不能用“符合 BFF 标准”代替可达动作清单。
Cookie 加固保护会话身份,不证明用户意图
会话 Cookie 之所以敏感,是因为它把浏览器连接到服务端令牌。RFC 要求 Secure 和 HttpOnly,建议 SameSite=Strict、路径 /、不设置 Domain,并在适用时使用 __Host-Http- 一类由 HTTP 设置的前缀。若客户端会话对象包含令牌材料,还应加密,避免令牌以明文落在本地持久存储。
这些控制分别回答:脚本能否读 Cookie?不安全传输会不会携带它?子域能否设置或共享它?读取浏览器文件的恶意软件能否看见令牌明文?它们都没有回答“这次请求是否代表用户当下意图”。
Cookie 认证还把 CSRF 纳入设计。BFF 必须提供适当防御。SameSite=Strict 在没有其他应用共享同一 site 时可能足够,但 site 比 origin 宽;同一可注册域下的两个子域属于同站却不同源。一个被接管的兄弟子域仍可能制造请求伪造。
CORS 只有在请求必经预检时才能完整承担这项工作。浏览器可以先发送 safelisted request,再禁止调用来源读取响应。RFC 建议要求自定义请求头,使跨源脚本必须预检;选择这套机制后,BFF 必须检查每个入站请求都带有该头。框架自带的防伪或 double-submit Cookie 也可以形成另一种方案。
CSRF 与同源恶意代码不能混为一谈。防伪令牌可区分合法来源和外部来源,却不能区分合法前端与已经在合法来源里运行的恶意代码。把“CSRF 检查通过”写成“用户同意”,就是把控制项提升成它从未拥有的授权主体。
剩余攻击的大小取决于应用实际能做什么
客户端劫持不等于直接令牌窃取。RFC 指出,它的能力较弱:攻击者不能直接控制令牌,仍受客户端和下游资源服务器策略限制,也需要用户浏览器保持在线并继续执行。严格的 CORS、有限的 BFF 入口与对象级授权都能成为实际边界。
前提是这些边界真实存在。架构图不能证明它们。运营者需要列出每个 BFF 入口、可到达的下游 host/path/method、所选令牌和 scope、预期对象授权及返回数据,并用恶意同源脚本实际测试,而不只是静态审阅配置。
BFF 同时是天然观察点。它看得到所有代理请求和响应。RFC 10017 指出,可以在这里做异常检测与限速,以减轻客户端劫持后果。正常应由人慢速完成的动作突然成批出现、罕见入口顺序、异常对象集合、新前端调用旧入口,或刷新令牌失效后会话仍持续操作,都应触发调查。
集中可见性也带来隐私代价。若第三方托管 BFF,它能观察前端与资源服务器之间的全部流量。数据最小化、保留期限、租户隔离和运维访问必须与安全策略一起设计。把令牌移到服务器降低了浏览器暴露,却也集中流量知识和执行权。
会话寿命还应服从其代表的授权关系。RFC 建议把 Cookie 会话最长寿命与刷新令牌最长寿命对齐,并在活动会话的刷新令牌失效时撤销会话。服务端会话便于直接撤销,却带来复制或粘性会话成本;客户端会话更易扩展,但实际控制更多依赖令牌的撤销和到期。
建立请求到决定的完整凭据
不要把访问令牌、刷新令牌、客户端秘密或完整 Cookie 写进日志。可复核不等于泄密。
对每个敏感动作,保留可关联但不可充当凭据的会话标识、创建与到期时间、Cookie 策略版本、认证及授权码交易、BFF 客户端身份、前端构建版本。记录入站入口、规范化方法和路径模板、CSRF/origin/CORS 结果与请求结构校验。
随后保存翻译过程:出站资源服务器、路径模板、方法、允许策略版本,以及不含秘密的令牌指纹或标识、签发者、audience、scope 与到期时间;相关时记录刷新、轮换、撤销或失效事件。最后保留资源服务器授权结果、状态码、响应变换、限速/异常判断、变更责任人与补救路径。
这套凭据能区分一个“令牌安全”徽章掩盖的多种故障。令牌外泄不同于会话被盗;CSRF 不同于同源恶意执行;开放代理错误不同于资源服务器权限过宽;正确拒绝也不同于 BFF 路由故障。它们的责任人和修复方式并不相同。
Running-Code Primacy 给出最后测试:在受控环境中让恶意脚本进入应用来源,验证它读不到令牌和会话状态,不能独立启动令牌流程,不能越出获准目标/路径/方法,不能突破下游对象授权;当它尝试“允许但异常”的动作时,系统还必须留下可读告警与凭据。
BFF 的成功要同时证明两件事:令牌不能离开,剩余请求权限足够窄、可观察,而且能够撤销。
来源
会员简报
档案背景详情
使用相应会员等级登录,即可解锁完整简报与来源注释。
仅限 Strategic Circle
Strategic Circle
所有读者均可浏览。加入并登录后可解锁档案简报。
加入 Strategic Circle仅限 Leadership Alliance
Leadership Alliance
符合条件的 IP 资产所有者和管理层可登录查看 Leadership Alliance 简报。
加入 Leadership Alliance
