Technical documentation

审计日志显示“张三”操作了接口,不代表他没越权:多跳委托里的身份与权限分离

审计日志显示“张三”操作了接口,不代表他没越权:多跳委托里的身份与权限分离

多跳委托中身份追溯仅能还原最终操作者,无法自动验证中间每一跳是否越权,揭示了行动者身份与授权约束在信任边界内的分离真相。

多跳委托中谁在真正操作?身份可查不等于授权合规

审计日志显示的身份可查不等于授权合规,因为能追踪到最终执行者并不代表中间每一跳都未越权,二者发生在不同的时间窗口和信任边界内。

审计日志里清晰地写着“张三”调用了接口,这是否意味着张三的操作完全合规?在多跳委托场景下,能追踪到最终执行者,并不代表中间每一跳都未越权。很多时候,我们以为看清了链条,其实只看到了表象。这种错觉源于我们将“身份确认”与“权限校验”混为一谈,仿佛只要知道是谁按下了按钮,就默认他有权按下那个按钮。然而,在复杂的微服务架构中,这两个动作往往发生在不同的时间窗口和信任边界内。

act 声明无法解决越权问题

很多人误以为 RFC 8693 定义的 JWT act 声明是万能钥匙,能自动锁定所有权限边界。事实并非如此。该声明的设计初衷仅在于传递嵌套行动者的身份上下文,它负责回答“是谁”,却无力承载“凭什么”的约束条件[1]。

想象一下,父令牌拥有访问整个数据库的宽泛权限。在 OAuth 2.0 委托链传递过程中,中间节点可能利用这个宽泛权限去执行一个仅限特定子任务的子操作。此时,act 声明虽然如实记录了“这是子任务的操作者”,却无法标记这种权限被不当放大的越权行为[1]。由于缺乏对具体工具、参数及调用深度的显式表达,系统很容易陷入“谁操作了”与“是否被允许操作”脱节的困境。

更深层的问题在于,act 声明本质上是一个静态的身份传递机制,它假设“持有令牌即代表拥有全部权限”。但在实际的业务逻辑中,权限往往是动态且分层的。例如,一个管理员账号(Admin)委托给一个自动化脚本(Script A),Script A 又进一步委托给另一个临时服务(Service B)。如果 Service B 试图访问一个本应仅限 Script A 操作的敏感配置项,act 声明依然会忠实地记录 Service B 的身份,却不会自动拒绝这次请求,因为从令牌的签名角度看,它确实是由合法的父级签发的。IETF 草案明确指出,即使审计日志完整记录了链中行动者身份,也不能据此推导出每一跳均未越权,更不能假设撤权已传达到所有执行点[1]。身份可追溯性与逐跳授权约束的可验证性,本质上是两类独立的证据维度。单纯的身份记录,无法自动证明操作的合法性。

需要警惕的是,这一结论源自 Dapeng Liu 等人于 2026 年发布的 IETF Internet-Draft《Delegation Chain for OAuth 2.0》。该文档目前处于未获 IETF 采纳的草案状态,因此其关于 JWT act 声明能力边界的描述,应视为作者的技术主张,而非既定标准结论[1]。在将其作为安全设计的绝对依据前,必须保持审慎。

离线令牌让“多跳委托中谁在真正操作”更难验证

离线令牌一旦签发便独立于发行方指令运行,导致目录侧的撤权无法立即阻断所有执行点,使得多跳委托中的身份与权限验证变得极难实时确认。

当目录侧宣布某项权限失效时,你往往以为操作会立刻停止。事实却并非如此。在多跳委托场景中,授权持有人可能早已将权限拆解并派生为离线子令牌。这些令牌一旦发出,便带着独立的有效期和工具约束,像一张张已签发的支票,不再依赖发行方的实时指令。

衰减授权令牌带来的新挑战

Niki Aimable Niyikiza 在 2026 年提出的“可衰减授权令牌”机制,允许持有者离线派生具有更窄权限的子令牌[2]。这种设计看似完美:子令牌受父令牌的深度和生命周期限制,执行点甚至只需依赖根发行者的信任锚即可完成离线验证[2]。但这恰恰埋下了隐患。系统无法自动确认资源侧是否已经拒绝了这些“过期未死”的令牌。

关键在于,对于仍具剩余生命周期的离线令牌,目录侧发起的撤权事件,并不能直接构成资源侧拒绝的证明[3]。这就好比银行系统通知某张信用卡作废,但持卡人手中那张尚未过期的旧卡,若未被终端机实时联网校验,依然可能在下一笔交易中成功扣款。

目前的摘要材料并未证明现有设计已规定了撤销列表的缓存一致性或生产部署中的撤权收敛机制[2]。这意味着,当权限变更发生时,不同执行点获取最新状态的时机参差不齐。有的节点可能刚更新完缓存,而另一端的离线执行点却还在依据旧的信任链继续工作。

场景特征 在线验证模式 离线令牌模式
权限变更响应 立即生效,实时阻断 存在滞后,依赖本地缓存
验证依赖 必须连接目录服务 仅需信任锚与本地签名
撤销传播 即时同步 需额外机制(如短周期)
越权风险 低,状态实时一致 高,旧令牌可能继续生效
审计依据 权威且实时 可能存在时间差导致的误判

要解决这一矛盾,系统不能单纯依赖目录侧的撤销列表。它必须引入在线状态查询、强制缩短令牌生命周期,或者采用版本与纪元校验等额外控制手段[2]。否则,无论身份追溯得多么清晰,只要离线令牌撤销机制存在时间差,“谁在真正操作”的判断就永远无法脱离时间的迷雾。

如何在多跳委托中确保真正的授权控制

确保真正授权控制需解决身份与权限分离问题,即不能仅依赖身份追溯,必须建立机制证明撤权指令已传达到所有节点且中间每跳均未越权。

当审计日志清晰地记录了“谁在操作”,安全团队往往误以为风险已消除。事实是,身份可追溯并不等同于授权合规。在多跳委托场景下,即使能还原出最终执行者,也无法自动确认中间每一跳是否越权,更不能证明撤权指令已传达到所有节点[1]。这种“身份”与“权限”的分离,构成了最大的安全盲区。

要填补这一漏洞,系统必须主动将“身份可追溯性”与“逐跳授权约束可验证性”视为两个独立的安全维度进行设计。仅靠追踪链条上的行动者身份是不够的,关键在于如何验证每一步的授权边界。如果缺乏在线状态查询、短生命周期令牌或版本纪元校验等机制,离线令牌的存在会让目录侧的撤销动作失效[2][3]。这就像你锁上了大门,却忘了收回挂在门把手上的备用钥匙,只要钥匙还在有效期内,任何人都能进入。

下表对比了两种策略在应对离线撤销时的表现差异:

对比项 依赖离线验证的传统模式 强制在线/短周期的增强模式
撤销响应速度 延迟高,依赖令牌自然过期 即时生效,切断剩余生命周期的访问
越权检测能力 仅能追溯身份,无法验证约束 结合深度与约束条件实时校验
对网络依赖度 低,适合弱网环境 高,需建立可靠的在线查询通道
攻击面范围 大,离线派生的子令牌难以管控 小,通过短周期限制窗口期
审计复杂度 低,仅需记录操作主体 高,需记录完整的授权上下文

在架构设计层面,必须强制落实在线验证环节。在标准演进完成之前,这是防止权限失控的唯一手段。同时,审计建议需要升级:日志不仅要记录“谁操作”,还需详细记录当时的授权上下文,包括令牌深度、具体约束条件以及当时的撤销状态[1]。只有将这些信息完整留存,事后审计才能还原真相,判断某次操作是否真的符合授权要求。

FAQ: 常见疑问解答

Q: 既然 act 声明不能解决越权,为什么还要使用它? A: act 声明的核心价值在于“身份溯源”,它能帮助我们在发生安全事故后快速定位是谁触发了操作,而不是判断操作是否合法。它是审计的必要条件,但不是充分条件。

Q: 离线令牌撤销真的无法实现吗? A: 不是无法实现,而是标准协议本身没有强制规定缓存一致性。要实现秒级撤销,通常需要引入额外的机制,如短效令牌、在线状态检查(Online Status Check)或 CRL(证书吊销列表)的频繁轮询。

Q: 多跳委托场景下,如何平衡安全性与性能? A: 这是一个权衡问题。对于核心敏感操作,必须强制在线验证;对于非关键路径或弱网环境,可以接受一定的延迟,但必须配合较短的令牌生命周期来缩小风险窗口。


参考来源

  1. draft-liu-oauth-chain-delegation-00 - Delegation Chain for OAuth 2.0 · https://datatracker.ietf.org/doc/draft-liu-oauth-chain-delegation/(A级)
  2. draft-niyikiza-oauth-attenuating-agent-tokens-01 - Attenuating Authorization Tokens for Agentic Delegation Chains · https://datatracker.ietf.org/doc/draft-niyikiza-oauth-attenuating-agent-tokens/(A级)
  3. Revoke user access in an emergency in Microsoft Entra ID - Microsoft Entra ID | Microsoft Learn · https://learn.microsoft.com/en-us/entra/identity/users/users-revoke-access(A级)