框架内部:MCP 的 OAuth 签发方绑定,以及为什么协议安全最后落在字符串比较上
MCP 2026-07-28 规范通过六项 SEP 加固 OAuth,而最关键的问题其实很朴素:这条响应到底来自哪台服务器。本文拆解混淆攻击模型、已经导致 MCP 客户端故障的真实签发方问题,以及实现方现在必须改什么。
本页目录
先给三个数字,然后再解释。第一,OAuth 元数据文档里的 issuer 字段,本质上就是一个字符串。第二,今年夏天,Atlassian、Context7 和 Home Assistant 都曾经为各自 MCP 授权端点返回过元数据,其中这个字符串和获取该元数据时使用的 URL 对不上,结果严格校验的客户端直接拒绝连接。第三,MCP 规范现在交付的修复,核心机制其实就是“比较这个字符串,不一致就拒绝”。就这么简单。但它堵上的攻击,是 OAuth 里最麻烦的一类:混淆攻击,而 MCP 的部署方式又天然把这种风险放大了。
这是一篇“框架内部”文章,所以我们直接钻进管道里看:签发方绑定的问题到底是什么、影响哪些流程,以及 2026-07-28 这一版规范包要求每个 MCP 客户端和服务器实现者做什么。同一版本里的无状态传输改动拿走了大多数标题,认证加固拿到了六项 SEP,却几乎没有报道。这个关注顺序其实反了。只要你运行的 MCP 服务器里握着真实凭据,这一部分决定的就是一个搞错服务器的客户端,会不会把 token 交到错误的人手里。
要点速览 - MCP 把传统 OAuth 的拓扑倒了过来:一个客户端在运行时发现并连接多个授权服务器。这个结构恰好就是混淆攻击最擅长利用的拓扑。 - 2026-07-28 规范包包含六项 SEP。最关键的两项是 SEP-2468(按照 RFC 9207 校验授权响应中的iss参数)和 SEP-2352(把每一份已注册客户端凭据绑定到签发它的授权服务器)。 - 这不是理论问题。今年夏天,Atlassian 和 Context7 的 MCP 端点都曾在真实环境返回签发方不匹配的元数据,导致严格客户端直接失败。规范正在追赶已经发生在生产里的故障。 -iss校验现在已经是推荐做法,而且正在走向强制。今天就把它做进去。如果一台本应支持该机制的服务器没有返回iss,应该拒绝,而不是耸耸肩继续。 - 即使这整套措施全部落地,它加固的仍然只是客户端到服务器之间的认证。智能体身份、逐请求授权、委托链来源和审计仍然不属于协议范围,需要你自己解决。
发生了什么
2026 年 5 月 21 日,MCP 维护者锁定了 2026-07-28 规范的候选版本;最终规范于 7 月 28 日发布,此后 SDK 维护者进入十周验证窗口。大多数讨论都集中在无状态化转向。藏在下面的,是 Tigera 对这次版本的详细解读所总结的一组 OAuth 加固措施,共六项 Spec Enhancement Proposal:
|
SEP |
要求 |
防止的故障 |
|---|---|---|
|
2468 |
校验授权响应中的 |
多授权服务器之间的混淆攻击 |
|
2352 |
把注册凭据绑定到对应签发方;迁移后重新注册 |
凭据被重放到错误授权服务器 |
|
837 |
动态客户端注册时声明 |
桌面和 CLI 客户端因 localhost 重定向 URI 被拒绝 |
|
2207 |
为 OIDC 类服务器明确刷新 token 流程 |
各实现自行发明不同的 token 续期方式 |
|
2350 |
明确权限提升流程中的 scope 累积规则 |
已授予权限范围究竟如何保留的歧义 |
|
2351 |
明确 |
元数据发现的互操作故障 |
三项偏维护性质的 SEP(2207、2350、2351)主要是在补充说明,而认证规范里的“说明清楚”本身就很重要。两个 SDK 如果连元数据文档放在哪里都理解不同,那是互操作故障,不是脚注。不过真正承重的是 2468 和 2352,它们问的其实是同一个问题:客户端怎么知道自己究竟在和哪台服务器说话?
MCP 2026-07-28 规范包包含六项 OAuth 加固 SEP:签发方校验(2468)、签发方绑定凭据(2352)、动态客户端注册中的客户端类型声明(837),以及刷新 token 流程(2207)、scope 累积(2350)和发现行为(2351)的明确化,详见 Tigera 的分析。候选版本于 5 月 21 日锁定,最终规范于 2026 年 7 月 28 日发布。
漏洞模型:一个客户端,多个签发方
经典 OAuth 通常假设的是“很多客户端,一个授权服务器”:成千上万个应用连接一个身份提供方,由一个 token 签发方负责发放凭据。所谓混淆攻击,也就是诱骗客户端把一条授权响应错误归因到另一台服务器,在这种世界里过去相对边缘,因为大多数客户端一辈子只会和一个签发方通信。
MCP 基本把这套结构反过来了。一个客户端,也就是宿主应用,会连接很多 MCP 服务器。每台 MCP 服务器背后都可能是不同授权服务器,这些服务器在运行时发现,而且还经常通过动态客户端注册当场完成注册。规范作者说得很直接:签发方校验 SEP 针对的是“一类在 MCP 的单客户端、多服务器部署模式中更常见的混淆攻击”,这段话见 Tigera 的文章引述。当你的客户端同时在十几台授权服务器上持有注册信息时,攻击者根本不需要破解任何密码学。他只需要让客户端把一条响应认成另一台服务器发的。
攻击过程大致是这样。你的智能体宿主正在和正常服务器 A 走授权流程,这时收到了一条实际上来自攻击者控制的服务器 B 的响应。如果没有签发方检查,客户端可能继续对 B 完成交换,从而泄露授权码;也可能接受 B 签发的 token,再把它交给后续系统。RFC 9207 是 2021 年为经典 OAuth 加上的修复,它在授权响应中增加明确的 iss 参数,让客户端能够拒绝来自非预期签发方的任何响应。SEP-2468 则把这项要求引入 MCP。SEP-2352 处理更安静的另一半:凭据。在它之前,客户端可能持有由签发方 A 生成的 client ID,而某个资源迁移到签发方 B 后,客户端又把 A 的凭据拿去给 B。有时它居然能工作,但“有时能工作”绝对不是你希望认证系统拥有的属性。所以 2352 要求注册状态按授权服务器分别保存,与 issuer 值绑定,迁移时重新注册。
这也不是 MCP 第一次补这一类问题。2025-06-18 版规范已经把 Resource Indicators(RFC 8707)设为强制,以确保 token 只为某一个明确服务器签发;MCP 授权规范也早就禁止接受发给其他资源的 token,或把它们继续向下游透传。2026-07-28 这一包沿着同一个方向继续走:默认更少信任,绑定关系更明确。如果你读过我写的 MCP 与 API 对比,这正是我在那里谈过的灵活性成本。运行时发现让 MCP 变得可组合,同时也制造了这些身份问题。
MCP 的“一个客户端连接多个服务器”拓扑,恰好就是混淆攻击最容易利用的部署模式。攻击者无需破解密码学,只要让客户端把响应或凭据错误归因到另一台授权服务器。SEP-2468 通过 RFC 9207 的 iss 参数把响应绑定到签发方,SEP-2352 则把注册凭据绑定到签发它们的服务器,详见 Tigera 的分析和 RFC 9207。规范正在追赶生产故障
如果这些听起来还很抽象,其实一点也不。整个夏天,真实 MCP 部署里已经不断出现 issuer 字符串问题,严格客户端也早就在因此报错。
7 月,opencode 客户端用户发现,连接 Atlassian 的 Rovo MCP 服务器时,OAuth 在发现阶段就失败。受保护资源元数据正确公布了租户专属授权服务器,但从那个地址返回的元数据文档却把 issuer 写成共享根地址 https://auth.atlassian.com,而不是实际获取元数据时使用的租户路径。RFC 8414 第 3.3 节要求 issuer 必须与获取元数据时使用的 URL 完全一致,只去掉 .well-known 后缀。因此 opencode 的严格校验拒绝连接是正确行为,登录也因此完全被阻断。这是 Atlassian 侧的规范合规问题,而且已经通过真实端点得到确认。Context7 的 MCP 端点在 6 月遇到了同类问题:对外公布的授权服务器与 Clerk 子域名元数据里的 issuer 不一致,官方 MCP Go SDK 因此拒绝继续流程。Home Assistant 的元数据则完全省略了 issuer 字段,以另一种方式弄坏了 MCP 客户端。
这三个问题都不是实际发生的混淆攻击,而是互操作故障。但这恰恰说明问题在哪里。阻止攻击者假服务器的那个字符串比较,同样也会阻止一台配置马虎的真实服务器,所以整个生态马上会对那些过去一直写错、却侥幸被放过的元数据变得严格得多。WorkOS 对混淆攻击的文章把运维层面的现实说得很清楚:很多 OAuth 库现在仍然默认不启用 RFC 9207 校验。文章还提到 CVE-2026-59208,认为如果账户查找是限制在已经确认的签发方命名空间里,而不是全局匹配一个 sub 声明,就可以直接阻止该漏洞。我会把这个 CVE 的具体关联视为 WorkOS 的报告判断,而不是我独立验证过的事实,但无论如何,背后的防御原则本身就是标准做法。
真实 MCP 部署整个夏天都在签发方校验上出错:Atlassian 的 Rovo MCP 服务器返回的元数据,其 issuer 与实际获取元数据的租户 URL 不一致(opencode issue #39332);Context7 的端点公布了一台授权服务器,元数据却声明另一台(Context7 issue #2723);Home Assistant 则完全省略 issuer 字段。RFC 8414 第 3.3 节要求 issuer 值与元数据获取 URL 完全一致,因此严格客户端拒绝这三种情况都是正确行为。
实现者必须做什么
如果你维护 MCP 客户端:
现在就校验每一次授权响应里的
iss。 如果它和当前流程中的签发方不一致,直接拒绝。如果服务器宣告支持 RFC 9207 却没有返回这个参数,也要拒绝。规范已经明确表示,未来版本会要求拒绝缺失iss的响应,所以今天就按强制要求实现。按授权服务器分区保存注册状态。 每个客户端 ID、客户端密钥和刷新令牌,都要和签发它的 issuer 值一起存储。如果某个资源的受保护资源元数据开始指向新的授权服务器,重新注册,绝不要把旧凭据拿去重放。
动态客户端注册时声明
application_type。 SEP-837 解决的是一类很具体的故障:桌面或 CLI 客户端被默认当成web应用,然后因为 localhost 重定向 URI 被拒。只多一个字段,就能消掉一整类真实问题。账户查找必须限定到签发方。 一个
sub声明只应该在你已经验证过的签发方命名空间里匹配账户,绝不能全局匹配。
如果你运行 MCP 服务器,或者运行挡在它前面的授权服务器:返回的元数据中,issuer 必须与实际获取它的 URL 完全一致,包括租户路径;按照 RFC 9728 实现受保护资源元数据;并继续校验 token 确实是为你的资源签发的。如果你在越来越多 MCP 服务器前面自托管智能体,还要考虑规模问题:N 个智能体乘 M 个服务器,就意味着 N 乘 M 份与签发方绑定的注册。十个智能体时也许还能靠表格管理,一百个智能体时你需要的是注册表,而规范对注册表没有任何意见。那部分属于你的平台。
根据 Tigera 的 SEP 分析和 WorkOS 的混淆攻击指南,实现者必须校验授权响应中的iss,拒绝不匹配以及在应支持时缺失的值;按 issuer 分区存储凭据并在迁移时重新注册;动态客户端注册时声明application_type;账户查找也必须限定到已验证的签发方。一级 SDK 预计会在规范十周验证窗口内完成支持。
这份规范仍然没有回答什么
再把这六项 SEP 看一遍,会发现它们有一个共同点:全都在加固一个 OAuth 客户端和一个授权服务器之间的交换。这个工作必须做。但正如 Tigera 的分析说得很直白,token 认证的是客户端,不是智能体。一个宿主背后放 200 个智能体,它们共享的仍然是同一个客户端身份。签发方绑定完全不会告诉你,到底是哪一个智能体、代表谁、基于什么判断在客户端后面发起动作。scope 解决的是“能不能进门”,不是逐请求策略。委托链也一样,智能体调用智能体再调用服务器,每一跳都可以完全符合 OAuth,但端到端仍然没人说得清责任归属。而且这套规范也没有要求任何参与方把过程记录下来。对协议来说,这个范围划分是正确的;对企业来说,答案还远远不完整。
我不是在贬低这项工作。没有签发方校验的 MCP,就像不校验证书的 HTTP,而这个洞现在终于在补。但剩下的四个缺口,也就是智能体身份、逐请求授权、委托来源和审计,属于治理层。它们不会因为你继续等下一版规范就自动出现。它们和我在智能体治理里与客户讨论的那些问题完全一样:要么由智能体周围的环境强制执行,要么就没人执行。
常见问题
MCP 的 OAuth 签发方绑定问题是什么?
MCP 客户端会连接很多在运行时发现的授权服务器,因此容易受到混淆攻击,也就是把一条响应或一份凭据错误归因到另一台服务器。2026-07-28 版规范通过两项要求解决这个问题:客户端校验授权响应中的 iss 参数(SEP-2468,引入 RFC 9207),以及把每一份注册凭据绑定到它的签发方(SEP-2352)。
这是 MCP 协议本身的漏洞吗?
这是协议部署模式放大的一类漏洞,现在已经在规范层补上。今年夏天生产环境出现的故障,也就是 Atlassian、Context7、Home Assistant 返回签发方不匹配或缺失的元数据,属于实现错误,但它们很好地暴露了“完全不校验”这种模型有多脆弱。严格校验正在成为基线。
哪些流程会受影响?
任何客户端同时注册到多个授权服务器时使用的授权码流程、跨服务器动态客户端注册、资源从一台授权服务器迁移到另一台之后的凭据使用,以及通过 .well-known 文档完成的元数据发现。单服务器部署从来不是主要风险,智能体带来的多服务器拓扑才是。
什么时候会变成强制要求?
2026-07-28 规范已经定稿。SDK 支持会在 5 月候选版本锁定后的十周验证窗口内陆续落地,而且规范已经明确表示,未来版本会要求拒绝没有 iss 的响应。现在新做的任何实现,都应该直接把它当成强制要求。
最后怎么判断
OAuth 安全很多时候就是很无聊的字符串比较,只是后果一点也不无聊。MCP 现在终于正面撞上了这个事实。2026-07-28 这一版,把一个五年前就存在的 OAuth 修复引进了一种“单客户端、多服务器”的协议,而正是这种形状让修复变得格外紧迫。更巧的是,真实部署也刚好开始在野外不断撞上同一检查。升级 SDK,校验 iss,把注册绑定到签发方。然后再问那个规范正确地没有替你回答的问题:如果你签发的 token 被拿去做了一次你根本不会批准的工具调用,背后又是一个你连名字都说不出来的智能体,谁会拦住它,记录又在哪里?这个答案不会从规范里冒出来。它来自你围绕规范搭建的智能体框架。
如果你正在为 MCP 部署梳理认证和身份,这也是我经常和客户讨论的问题。联系我。
来源
Tigera,《MCP 的认证加固:六项新 OAuth SEP 修复了什么,又还缺什么》:https://www.tigera.io/blog/mcps-auth-hardening-what-the-six-new-oauth-seps-fix-and-what-they-still-dont/ (发布于 2026 年 7 月 28 日,检索于 2026 年 8 月 29 日)
WorkOS,《OAuth 混淆攻击与 RFC 9207:从未真正进入 token 交换的签发方检查》:https://workos.com/blog/oauth-mix-up-attacks-rfc-9207 (发布于 2026 年 7 月 20 日,检索于 2026 年 8 月 29 日)
Model Context Protocol,授权规范:https://modelcontextprotocol.io/specification/2025-11-25/basic/authorization (发布于 2025 年 11 月 25 日,检索于 2026 年 8 月 29 日)
RFC Editor,RFC 9207《OAuth 2.0 授权服务器签发方识别》:https://www.rfc-editor.org/rfc/rfc9207.html (发布于 2021 年 12 月 16 日,检索于 2026 年 8 月 29 日)
opencode 仓库,issue #39332,《MCP OAuth:Atlassian 认证失败,RFC 8414 issuer 不匹配》:https://github.com/anomalyco/opencode/issues/39332 (发布于 2026 年 7 月 28 日,检索于 2026 年 8 月 29 日)
Context7 仓库,issue #2723,《MCP OAuth 端点的 OAuth 元数据 issuer 不匹配》:https://github.com/upstash/context7/issues/2723 (发布于 2026 年 6 月 5 日,检索于 2026 年 8 月 29 日)
Home Assistant Core,issue #147059,OAuth 元数据缺少 issuer:https://github.com/home-assistant/core/issues/147059 (发布于 2025 年 6 月 17 日,检索于 2026 年 8 月 29 日)
modelcontextprotocol/modelcontextprotocol 仓库:https://github.com/modelcontextprotocol/modelcontextprotocol (检索于 2026 年 8 月 29 日)
继续阅读
Agent Field Notes
获取下一期。
为需要真正运行这些系统的人,解释 Agent Harness、运行时、安全与治理。