回路 / The Loop — 提出有价值的问题,比直接获取答案更重要。
这个专题收集和整理我与 Gemini、ChatGPT、Claude 等 AI 的对话记录。每一篇对应一次完整的提问与回答过程。通过留存这些层层追问,还原日常思考的真实轨迹。
交互式图解 — 本文配套两份可交互的可视化资料,帮助理解认证流程:
- MCP OAuth 认证时序图 — 动态时序图,展示从员工发起指令到工具执行完成的 21 步全流程
- MCP 认证架构总览 — 系统架构拓扑图,展示各组件的安全职责划分
概要
这是一场围绕企业级 AI Agent 多用户身份认证的深度对话。从”多人共用一个 Agent 时,身份验证和 Token 该放在哪一层”出发,逐步深入到 MCP(Model Context Protocol)协议对工具层认证的标准化定义,最终完整推演了一个远程 MCP 工具从 401 挑战到动态授权再到恢复执行的全链路时序流程。
核心结论:企业多用户场景下,凭证必须与大模型的认知空间(Context Window)彻底解耦——Token 存 KMS 不存 Session,身份注入发生在 Harness 拦截层,工具调用通过 OAuth 2.1 + RFC 8707 资源指示器实现定向锁定。认知空间可共享,但执行空间和数据空间必须绝对隔离。
Q: 企业 Agent 服务多个员工时,每个人的身份验证在哪一层处理?Token 存在哪里?
身份验证不能侵入大模型的推理层(Orchestration),也不能让大模型直接接触敏感 Token。它由三个组件联合完成:
Harness 层(控制核心) — 作为安全网关,负责拦截上游请求、提取用户身份标识(User ID),并在调用工具时动态注入凭证。
Session 层(状态与上下文) — 多用户隔离的天然边界。Session 数据库采用 Tenant_ID + User_ID + Session_ID 复合主键索引。
Tools / MCP 层(执行代理) — 升级为”身份感知型工具网关”。工具定义本身是静态的 Schema,但执行时接受 Harness 传递的动态身份上下文。
Token 存储原则
强烈建议不要将 Token 存在 Session 账本中。 原因很直接:Session 账本会作为历史记录完整喂给大模型(即 messages 数组),如果直接存放明文 Token,一旦被 Prompt Injection 攻击利用就会泄露凭证。
标准的分离存储方案:
| 存储组件 | 存放内容 | 安全策略 |
|---|---|---|
| Session 数据库 | 仅存放 User_ID、Tenant_ID 及脱敏后的对话上下文 | ACL 隔离,禁止跨用户读取 |
| KMS / Vault | 各用户对应外部工具的 Access_Token、Refresh_Token | 以 User_ID + Tool_ID 为联合加密主键;仅对 Harness 进程开放 |
Q: 凭证在运行时是怎么流转的?
遵循**“前端透传、中枢换取、即用即抛”**原则:
- 身份透传 — 员工发起请求时,上游客户端(如企业微信)在 HTTP Header 中携带身份凭证(
X-User-JWT或加密的 User-ID)到达 Harness - Session 绑定 — Harness 校验凭证后,读取或创建该用户的专属 Session
- 权限剪枝(SLM 阶段) — 小模型在工具剪枝时,以该用户的 RBAC 角色作为硬过滤条件。无权限的工具直接剔除,不会进入最终 Payload
- 动态 Token 注入 — LLM 决定调用工具后,Harness 拦截响应,临时向 KMS 调取该用户专属 Token,封装进工具请求的 Authorization Header
这样做的好处:大模型永远接触不到明文凭证,Token 的生命周期被限定在单次工具调用的 HTTP 请求中。
Q: 多用户之间的隔离具体怎么做?
三个维度的刚性隔离:
上下文隔离(Context Isolation)
Harness 从 Session 数据库拉取历史流水时,查询语句强制绑定当前 User_ID。确保大模型推理员工 A 的请求时,上下文中绝不混入员工 B 的交互历史。
计算沙箱隔离(Compute Isolation)
如果指令触发了代码执行(如在 Sandbox 中运行 Python 生成报表):
- 严禁多用户共享同一个沙箱实例
- 为每个活跃的用户 Session 动态拉起完全隔离的微型容器
- Token 作为该容器的单次环境变量注入,执行完毕即刻销毁
审计与阻断隔离(Audit & Policy Enforcement)
Harness 与 Tools/MCP 之间架设独立的审计拦截器:
- 所有发往工具层的请求,自动补全
operator: User_A字段 - 工具服务器在执行高危动作前,二次校验操作人的业务权限
最终效果:认知空间(LLM)共享,但执行空间(Harness + Sandbox)与数据空间(Session + KMS)绝对隔离。
Q: MCP 协议本身对工具层的身份校验是怎么定义的?
MCP 根据传输模式做了明确的分层处理:
STDIO 模式(本地进程)
当 MCP Server 作为本地子进程运行时,不采用网络认证协议。身份和凭证完全依赖启动进程时注入的环境变量,安全性由操作系统的用户权限和进程隔离保证。
HTTP + SSE 模式(远程服务)
MCP 将自身映射到 OAuth 2.1 框架中:
| OAuth 2.1 角色 | 架构组件映射 | 职责 |
|---|---|---|
| Resource Owner | 企业员工 | 拥有数据访问决策权 |
| Client | Harness 控制层 | 代表员工发起工具调用 |
| Resource Server | MCP Server / 工具层 | 校验 Token、执行业务逻辑 |
| Authorization Server | 企业 IAM / IDaaS | 统一验证身份、发放凭证 |
协议遵循**“网络传输层负责鉴权,协议消息层保持纯净”**的原则:JSON-RPC 消息本身不包含明文凭证,而由底层 HTTP Header(Bearer Token)或操作系统进程环境来承载。
Q: RFC 8707 资源指示器在这里起什么作用?
解决一个关键的安全威胁:令牌挪用(Token Substitution)。
假设一个恶意或已被攻破的低权限 MCP Server 获取了员工的 Access Token,它可能拿着这个 Token 去请求另一个高权限 MCP Server(比如财务系统)。RFC 8707 资源指示器阻断了这种横向移动:
- 定向范围申请 — Harness 向认证中心请求 Token 时,必须携带
resource参数指定目标 MCP Server 的规范化 URI(如resource=https://api.wecom.internal/mcp/v1/crm) - 受限受众绑定 — 生成的 JWT Token 内部
aud(Audience)字段只指向该特定 MCP Server - 工具端硬阻断 — MCP Server 收到 Token 后,即使签名合法且未过期,如果
aud不匹配自身,必须拒绝执行
效果:每个 Token 被锁定在单一的工具服务器上,无法跨服务横向滥用。
Q: 当 LLM 要调用一个尚未授权的远程 MCP 工具时,完整的动态授权流程是什么样的?
这是一个 21 步的全链路流程,分为四个阶段:
阶段一:意图推理与凭据缺失发现(步骤 1-7)
- 员工发起业务指令(如”修改 CRM 中的客户状态”)
- Harness 组装 Payload 发起推理
- LLM 决定调用工具(Tool Call:
crm_update) - Harness 根据
User_ID + Tool_ID向 KMS 检索 Access Token - KMS 返回为空(未授权或已过期)
- Harness 向 MCP Server 发起匿名探测调用
- MCP Server 返回
HTTP 401 Unauthorized,Header 携带WWW-Authenticate及受保护资源元数据(PRM)地址
阶段二:推理挂起与用户授权(步骤 8-11)
- Harness 挂起大模型推理循环,向前端推送 OAuth 授权卡片
- 员工点击卡片,跳转企业 IAM 完成登录和授权确认
- IAM 发放单次临时授权码(Authorization Code)
- 前端自动回传 Authorization Code 给 Harness
关键设计:Harness 不会将 401 错误直接丢给大模型,避免模型产生幻觉或反复重试。认知与执行解耦。
阶段三:限域令牌换取与解耦存储(步骤 12-14)
- Harness 携带 Code +
resource参数向 IAM 申请令牌(RFC 8707 限制) - IAM 返回专属 Access Token(内部绑定特定
aud与scope) - Token 写入 KMS 高安全隔离区,建立 User_ID 与该工具的绑定关系
即便该员工在企业 IAM 中拥有全系统管理员权限,发放的 Token 也仅在 CRM 资源范围内生效。
阶段四:流程恢复与物理动作执行(步骤 15-21)
- Harness 携带 Bearer Access Token 重新发起工具调用
- MCP Server 校验 Token 签名、有效期及
aud匹配,执行业务逻辑 - 返回工具执行结果 JSON
- Harness 将结果作为追加流水写入 Session 数据库
- 工具结果送回大模型,恢复下一轮推理
- LLM 生成最终文本回复
- Harness 向前端输出最终话术
后续调用优化:只要 Token 未过期,系统在步骤 4 就会命中 KMS 缓存,直接跳转至步骤 15 执行,实现无感的秒级工具调用。
Q: 受保护资源元数据(PRM)具体长什么样?
每个远程 MCP Server 必须通过标准路径(.well-known/oauth-protected-resource)或认证挑战中暴露 PRM JSON 描述:
{
"resource": "https://api.wecom.internal/mcp/v1/crm",
"authorization_servers": [
"https://iam.wecom.work/oauth/v2"
],
"scopes_supported": ["crm.read", "crm.write"],
"bearer_methods_supported": ["header"],
"auth_flows_supported": ["authorization_code", "token_exchange"]
}
这个文档告诉 Harness:要调用这个工具,你需要去哪个认证中心、申请什么范围的权限、用什么授权流程。整个过程是自动发现的,不需要硬编码配置。
参考资料
- MCP Authorization Specification — MCP 官方协议中关于远程服务认证的完整规范定义,包含 OAuth 2.1 流程、动态发现和 PKCE 要求
- OAuth 2.1 Draft (IETF) — OAuth 2.1 标准草案,整合了 OAuth 2.0 的最佳实践并移除了不安全的授权类型
- RFC 8707 - Resource Indicators for OAuth 2.0 — 资源指示器规范,允许客户端在请求 Token 时显式指定目标资源 URI,防止 Token 被跨服务挪用
- RFC 9728 - OAuth Protected Resource Metadata — 受保护资源元数据发现机制,MCP Server 通过此标准向客户端声明认证要求
- Anthropic Engineering Blog - Managed Agents — Managed Agents 架构设计,本文 Harness 层概念的工程出处