<!-- title: 工具授权重构：scope到能力令牌最小权限 -->

# 工具授权重构：scope到能力令牌的最小权限

## 概述

把一个能调付款、改库、发邮件的自主 Agent 丢进生产环境，第一道塌方的不是模型智商，而是**授权模型**。2026 年业界逐渐达成一个共识：OAuth 的 Authorization Code Flow（RFC 6749）从根上是为「人」设计的——人在点同意按钮时就知道自己要什么；而 Agent 是在推理时才决定调哪个动作，这往往发生在授权数小时甚至数天之后。这条「同意时机 vs 决策时机」的结构裂缝，让绝大多数 Agent 实际跑在**过度授权**之上：宽 scope、共享凭证池、零 per-agent 边界。修复方向不是再叠一层 prompt 护栏，而是把工具调用从「拥有令牌就能调」重构成「逐调用鉴权 + scope-action 映射 + 能力弱化 + 机器主体身份」的能力模型。本文拆解这条重构链路上的八个断层与三道闸门。

## 一、为什么 OAuth Scope 撑不住 Agent 的最小权限

最小权限（Principle of Least Privilege）是安全圈最古老的规则，但 Agent 天生违反它。一个面向 MCP 生态的 Agent 默认拿到三样危险东西：**宽 OAuth scope**（为了省事直接给 `repo:*`、`billing:write`）、**共享凭证池**（多个 Agent 复用同一组 API key）、**零 per-agent 权限边界**（Agent 的身份就是用户的身份）。

结构性的病根在于时机错配。传统 OAuth 流程里，资源拥有者是人类，授权发生在「我知道我要干嘛」的瞬间，scope 粒度可以粗。Agent 模式下，授权发生在部署或连接时，而真正用哪个工具、传什么参数，是 LLM 在第 N 步推理时才决定的——模型可能把「读邮件」的权限临时用来「转发附件给外部联系人」。这不是 bug，是**架构层面的语义错位**：scope 是静态声明，action 是动态涌现，二者之间缺一层翻译。

| 失效模式 | 表现 | 后果 |
|---------|------|------|
| 宽 scope | `files:rw` 一把梭 | 删库与读文件同权 |
| 共享凭证 | 多 Agent 复用 token | 无法定位误操作来源 |
| 继承式身份 | Agent=用户身份 | 用户全权=Agent 全权 |
| 一次性同意 | 部署时全勾选 | 推理时无二次校验 |

## 二、多维度授权模型对比

| 模型/机制 | 颗粒度 | 委托安全 | 同意时机 | 审计能力 | 生产成熟度 |
|----------|--------|---------|---------|---------|-----------|
| OAuth 2.0 scope（人本） | 粗（资源级） | 弱（令牌即全权） | 一次性 | 中 | 极高 |
| MCP OAuth 2.1 + DCR | 中（工具级） | 中 | 连接时 | 中高 | 高（2026 主流） |
| Scope-Action Map | 细（动作级） | 中 | 逐调用 | 高 | 中高 |
| Capability Token（能力令牌） | 极细（单操作） | 强（可弱化 attenuation） | 逐调用 | 高 | 中 |
| Token Exchange 降权（RFC 8693） | 细（派生令牌） | 强（downscope） | 逐调用 | 高 | 中高 |
| SPIFFE/SVID 工作负载身份 | 系统级主体 | 强（mTLS+短证书） |  issuance 时 | 极高 | 高（云原生） |
| CIMD（MCP 客户端身份） | 客户端级 | 中高 | 注册时 | 中高 | 上升中 |

## 三、断层一：scope-action map——静态声明到动态动作的翻译层

这是 2026 年被反复提到的核心模式：**不要让 Agent 直接消费 OAuth scope，而是在中间架一张「scope → 允许动作」的映射表**。它的价值在于把「令牌持有的能力」和「本次调用是否被允许」解耦。即便令牌带着 `repo:write` 这种宽 scope，映射表仍可在单次调用上拒绝 `repo:delete` 这类高危动作，或要求额外同意。

```python
# scope-action map：把宽 scope 收窄到具体动作
SCOPE_ACTION_MAP = {
    ("files.read",   "download"):  {"allow": True},
    ("files.read",   "list"):      {"allow": True},
    ("files.write",  "upload"):    {"allow": True, "require_consent": False},
    ("files.write",  "delete"):    {"allow": False, "reason": "需逐次同意"},
    ("billing.read", "invoice"):   {"allow": True},
    ("billing.write","charge"):    {"allow": True, "require_consent": True, "max_amount": 100},
}

def authorize(tool, action, ctx):
    rule = SCOPE_ACTION_MAP.get((ctx.scope, action), {"allow": False})  # deny-by-default
    if not rule["allow"]:
        raise PermissionDenied(rule.get("reason", "默认拒绝"))
    if rule.get("require_consent"):
        ctx.must_pause_for_human_approval(timeout_s=300)
    return rule
```

这张表的工程意义在于**可审计、可测试**：安全团队可以 review 整张表，而不是去读散落在 prompt 里的护栏指令。它把「最小权限」从一句口号变成了一个可以被 CI 校验的数据结构。缺点是维护成本随工具数线性增长——这正是后面 CIMD 与能力令牌要补的位。

## 四、断层二：能力令牌与弱化（attenuation）

OAuth 令牌是「持有即全权」的 bearer token——谁拿到令牌，谁就拥有令牌的全部权限，没有降级机制。能力安全模型（object-capability）走另一条路：**权限绑定在一个不可伪造的令牌句柄上，且可以弱化（attenuate）后转交**。Agent 拿到一个「能删除指定 file_id」的能力令牌，转给子 Agent 时可以进一步收窄成「只能删除这一个文件」，而不是把完整 `files:write` 权限递过去。

```python
# 能力令牌：单操作、可弱化、短时效
capability = issue_capability(
    principal="agent:researcher-01",
    action="files.delete",
    resource="file:doc_8842",          # 绑定到具体资源
    constraints={"expires_in": 300},   # 5 分钟过期
)
# 委托给子 Agent 前做 attenuation（弱化），无法扩权
child_cap = attenuate(capability, resource="file:doc_8842", max_calls=1)
```

能力模型的杀手锏是**委托可控**：多 Agent 协作时，权限沿调用链自然衰减而非膨胀。这一点 OAuth 单独做不到——OAuth 的 scope 是声明式的，无法在委托链上做结构性收窄，只能靠 token exchange 模拟。代价是能力令牌需要一套独立的颁发、撤销、过期基础设施，落地成本高于直接复用 OAuth。

## 五、断层三：Token Exchange（RFC 8693）与降权派生

如果你不想抛弃 OAuth 栈，又想要能力模型式的「按需收窄」，答案在 RFC 8693——**令牌交换**。Agent 用一个宽授权令牌，向授权服务器换取一个**降权派生令牌（downscoped token）**，再拿派生令牌去调工具。派生令牌只包含本次调用真正需要的 scope，且可短时效。

```python
# 每次工具调用前，用宽令牌换取极窄的派生令牌
derived = token_exchange(
    subject_token=broad_user_token,     # 用户委托给 Agent 的宽令牌
    scopes=["files.read"],              # 只为这一步申请
    audience="mcp://filesystem.local",
    lifetime_seconds=120,
)
resp = call_tool("download", args={...}, bearer=derived)
```

这条路径的好处是**完全活在 OAuth 2.1 生态内**，云厂商（AWS、Azure、GCP）的 STS/Workload Identity Federation 都原生支持 token exchange 语义，审计侧也能在日志里看到「哪个宽令牌换出了哪个窄令牌」。它是当前企业生产里最务实的折中：不推翻 OAuth，但堵住了「宽令牌直达工具」的口子。短板在于每次调用多一次 token exchange 往返，需要靠本地短缓存（按 audience+scope 维度）摊薄延迟，否则工具调用 RTT 会显著拉长。

## 六、断层四：给 Agent 一个机器主体身份（SPIFFE/SVID）

前几层解决的是「令牌里装什么权限」，但还有一个被忽视的问题：**Agent 本身没有身份**。它要么借用户的壳，要么用一把静态 API key。2026 年从云原生圈借来的答案是 SPIFFE——为每个工作负载签发一个 SVID（SPIFFE Verifiable Identity Document），通常是一张带短 TTL 的 mTLS 证书。Agent 进程拿到 SVID 后，它就是一个**可被验证的机器主体**，而不是「某个用户授权的某个匿名调用」。

这层的价值在两点。第一，**审计可追责**：每一次工具调用都能定位到一个具体的 Agent 实例（`spiffe://corp/agent/researcher-01`），不再是共享凭证池里一团浆糊。第二，**mTLS 双向认证**：工具服务器也验证调用方身份，恶意或被污染的工具服务器无法轻易冒充合法 Agent 反向攻击。SPIFFE 与前几层是正交叠加的——SVID 解决「我是谁」，scope-action/capability 解决「我能做什么」。多 Agent 系统里，这一层几乎是从「能跑」到「敢上生产」的分水岭。

## 七、断层五：CIMD——MCP 客户端身份与注册

MCP 协议在 2026 年补上的关键一环是**客户端身份**。Scalekit 等厂商力推的 CIMD（MCP Client Identity）解决的是：当一个 Agent 作为 MCP 客户端去连一堆工具服务器时，服务器怎么知道这个客户端是谁、能调哪些工具？答案是把 MCP 客户端也纳入 OAuth 2.1 + 动态客户端注册（DCR，RFC 7591）的体系——客户端注册时声明自己的工具白名单与 scope 上限，服务器据此签发受限令牌。

```yaml
# MCP 客户端注册声明（CIMD 风格）
client:
  id: agent://researcher-01
  registered_scopes: [files.read, search.query]   # 上限，不能再多
  tool_allowlist: [search, read_doc]               # 只暴露这些工具给模型
  max_delegation_depth: 2                          # 委托链深度上限
  audit_sink: https://audit.corp/mcp
```

CIMD 的实战意义在于**工具可见性管控**：与其把 14K 个 MCP 工具全注册给模型再指望护栏兜底，不如在客户端注册阶段就把模型能看到的工具收窄到一个白名单。这是「最小权限」在工具枚举层的落地——模型连「有这个工具」都不知道，自然谈不上误调。它把攻防界担心的工具污染面也顺带收窄了：不可见的工具，污染了也无法被 Agent 触发。

## 八、断层六：JIT 同意流与高风险调用的检查点

宽 scope 之所以危险，是因为同意发生在「一切尚未发生」的部署时刻。修复办法是**把部分同意推迟到推理时刻**——即「按需/增量同意」（just-in-time consent）。Agent 推理到「我需要 delete 这个文件」时，运行时发现 scope-action map 标了 `require_consent`，就触发一次结构化的人机交互检查点（HITL），而不是默默执行。

```mermaid
flowchart TD
    A[Agent 推理: 选定工具+动作] --> B{鉴权网关 deny-by-default}
    B -->|未命中 allow| X[拒绝 + 审计]
    B -->|命中 allow| C{scope-action map}
    C -->|低风险| E[Token Exchange 降权派生]
    C -->|高风险 charge/delete| D[JIT 同意检查点 HITL]
    D -->|人拒绝| X
    D -->|人批准| E
    E --> F[工具执行 + 能力令牌]
    F --> G[审计日志: principal+scope+action+结果]
    G --> H[返回结果给 Agent]
```

JIT 同意流最大的工程敌人是**同意疲劳**——如果每步都弹窗，UX 崩溃，用户会养成无脑点同意的肌肉记忆，反而比一次性授权更危险。所以实践中要做**风险分级**：低风险动作静默放行，只对「金额超阈值」「不可逆删除」「外发数据」「跨租户访问」这四类触发检查点。这与零信任里的「just-in-time, just-enough access」是同一套逻辑，只是触发源从人变成了模型。

## 九、断层七：三种失效模式与 deny-by-default 闸门

零信任 Agent 权限模型要堵的三种失效模式可以一句话概括：**宽令牌直达工具**、**权限沿委托链膨胀**、**误操作无法定位**。对应的三道闸门是：鉴权网关默认拒绝（deny-by-default）、委托链深度上限 + 弱化、全链路审计。其中 deny-by-default 是底线——scope-action map 里**未显式 allow 的，一律拒绝**。这与大多数 Agent 框架默认的「注册了就能调」截然相反。

```python
# 鉴权网关中间件（FastAPI 风格）
@app.middleware("http")
async def authz_gate(request, call_next):
    principal = request.state.principal      # 来自 SPIFFE/SVID
    tool, action = parse_invocation(request)
    rule = SCOPE_ACTION_MAP.get((principal.scope, action))  # 未命中即 None
    if rule is None or not rule["allow"]:
        audit.log(principal, tool, action, verdict="DENY")
        return JSONResponse({"error": "denied by default"}, 403)
    if delegation_depth(principal) > MAX_DEPTH:
        return JSONResponse({"error": "delegation too deep"}, 403)
    return await call_next(request)
```

审计回路是第三道闸门里最容易被低估的一环。它不只是写日志，而是要能回答「这个文件是谁删的、用了哪个派生令牌、委托链经过哪些 Agent」。没有这条回路，前两道闸门出了事也无法追责，最小权限就退化成一句写在 PPT 里的口号。

## 十、变现与训练营评估

工具授权这条线本身**不能直接做成 C 端训练营**（太偏安全工程），但它是所有「Agent 上生产」企业课的**核心模块**。变现逻辑在于：B 端付费意愿最高的恰恰是「敢不敢让 Agent 碰生产系统」这个问题。一个针对工程团队的 2 天工作坊，模块切成「OAuth scope 现状审计 → scope-action map 落地 → token exchange 接入 → CIMD 客户端注册 → JIT 同意与审计」，客单价能撑到中高端。差异化卖点是不讲 prompt 护栏（那已被讲烂），而是讲**身份与授权基础设施**——这是 2026 年市场上仍稀缺的角度。落地阻力主要在企业 OAuth 系统改造的协同成本，需要甲方 IAM 团队配合。

## 推荐方案

- **个人/原型 Agent**：MCP OAuth 2.1 + DCR 足矣，scope-action map 用一张静态表跑起来，不上 token exchange，先解决「工具可见性白名单」。
- **企业生产单 Agent**：OAuth 2.1 + scope-action map + token exchange 降权派生，三层叠加，低风险静默、高风险 JIT 同意。这是性价比最高的甜点位。
- **多 Agent 委托链**：在前者基础上加 SPIFFE/SVID 给每个 Agent 实例发机器身份，委托链上用能力令牌 attenuation 强制权限衰减，深度上限锁死。
- **高风险金融/支付**：全栈叠加——CIMD 客户端注册收窄工具可见性、能力令牌绑定单笔交易、JIT 同意带金额阈值、全链路审计接入 SIEM。这里没有捷径，任何一层缺位都是合规事故。
- **通用选型红线**：凡是把宽 user token 直接送进工具网关、且不做逐调用鉴权的方案，无论模型多强，都不应进生产。

## 参考来源

1. [Least Privilege for AI Agent Tool Calls: Scope-Action Maps — Scalekit](https://www.scalekit.com/blog/how-implement-least-privilege-ai-agent-tool-calls) — 提出 OAuth Authorization Code Flow 在「同意时机 vs 推理时机」上的结构性裂缝，给出 scope-action map 模式与 CIMD 支持。
2. [Agent Authentication & Delegated Access: OAuth Flows, Scoped Tokens — Zylos Research (2026)](https://zylos.ai/research/2026-04-11-agent-authentication-delegated-access-oauth-scoped-tokens/) — 系统梳理 Agent 身份基础设施从 OAuth 2.1 扩展、SPIFFE/SVID、token exchange 四个方向的补位。
3. [AI Agent Least Privilege: The Complete MCP Security Checklist for 2026 — ScopeGate](https://scopegate.dev/blog/ai-agent-least-privilege) — 详述 Agent 默认违反最小权限的根因（宽 scope、共享凭证、无 per-agent 边界）与清单式修复。
4. [MCP Authentication Patterns: OAuth 2.1, Capability Tokens, and Per-Tool Authorization — SystemHardening](https://www.systemshardening.com/articles/ai-landscape/mcp-authentication/) — 给出 MCP 服务器侧 OAuth 2.1、能力令牌、逐工具授权的问题模型与对比。
5. [MCP Access Control: How to Enforce Least Privilege Across AI Agent Tool Chains — AppSentinels](https://www.appsentinels.ai/blog/mcp-access-control-how-to-enforce-least-privilege-across-ai-agent-tool-chains/) — 阐述 OAuth 2.0 + 动态客户端注册作为 MCP 授权框架的落地与细粒度访问控制。

> [!tip] 51学通信知识星球
> **星主：爱卫生**（微信：gprshome201101）——公众号「51学通信」创办者，19 年通信行业运维与讲师经验，著有《GPRS网络信令实例详解》《EPC原理与实践》《5G核心网原理与实践》三本纸质书（各大电商平台有售）。
> **星球定位**：深耕 5G 核心网、IMS、NFV/AI、云原生等 ICT 领域，主打运维岗位与信令分析。
> **当前规模**：5200 篇主题 / 990 个回答，198 元/年。
> **加入福利**：加入星球后请加爱卫生微信，拉您进知识星球年度陪伴与答疑群——不限量回复您的各种问题，另有群内分享。
> **AI 加持**：51学通信知识星球已作为 skill 接入 WorkBuddy，使用 deepseek-4-flash 在海量星球帖子中精准找贴、找视频、找 FAQ 和案例，做总结、找文档和 PPT 等场景全覆盖。

![51学通信知识星球海报-扫码加入](https://wiki.500nian.com/images/zhixingqiu_qrcode.png)
