MCP 授权加固:客户端为什么必须校验 iss
数据截至 2026-07,价格与限额以各官网为准。
如果你写的是 MCP 客户端,从这版规范开始,拿到授权服务器返回的授权码之后,不能直接拿去换 token——必须先看一眼响应里的 iss 参数是不是你预期的那个授权服务器。这不是”建议加固”,是写进规范的客户端义务;不做这一步,多授权服务器场景下你的客户端就是一个可以被诱导把授权码送错门的中间人受害者。
先承认一个很常见的误解:不少人觉得 MCP 的授权就是”套一层标准 OAuth,用现成的库跑一遍 authorization code + PKCE 流程就完事了”。这个想法在只有一个授权服务器、且客户端硬编码了它的地址时基本没问题。但 MCP 的现实是——一个客户端要同时连很多个 server,每个 server 又可能指向不同的授权服务器,这个”多对多”的拓扑恰恰是 OAuth 生态里最容易出事的形态。规范这次把授权这块单独拎出来加固,就是在补这个结构性的洞。
这次改了什么:授权加固是六块之一
2026-07-28 发布的新版 MCP 规范,官方的说法是自协议发布以来最大的一次修订,此前已经走过 release candidate 阶段。整体改动分六块:无状态协议内核、Extensions 框架、Tasks、MCP Apps、授权加固,外加一套正式的弃用策略。
授权这块由 6 个 SEP(Specification Enhancement Proposal,规范增强提案)共同完成,目标写得很直白:让授权规范更贴近真实世界里的 OAuth 2.0 / OpenID Connect 部署。换句话说,以前规范里那套授权描述,跟企业实际在用的 IdP(身份提供方)之间是有落差的,实现者要么自己脑补,要么各写各的。这 6 个 SEP 就是把落差填平。
其中被点名写进发布说明的一条,就是要求客户端按 RFC 9207 校验 iss 参数,对应 SEP-2468。本篇重点讲这一条,因为它是所有客户端实现都躲不掉的、且最容易被漏掉的一步。
iss 校验防的是什么:授权码被送错门
要理解为什么非校验不可,得先看没有 iss 时会发生什么。
一个 MCP 客户端连接多个 server 时,典型流程是:客户端发现某个 server 要求授权,跳到该 server 指定的授权服务器去做用户登录和同意,授权服务器带着授权码回调到客户端的 redirect URI,客户端再拿这个码去对应的 token 端点换访问令牌。
问题出在回调这一步不自带身份。回调只带回一个授权码和 state,客户端手里如果同时有好几个进行中的授权会话,它是靠 state 把回调对上某一次请求的。如果攻击者能影响客户端”这次该去哪个授权服务器”的判断——比如控制了一个恶意 MCP server,让它在元数据里声明自己用的是攻击者的授权服务器,然后设法让客户端把一次原本发往正规授权服务器的会话,和一次发往恶意服务器的会话搞混——客户端就可能把正规授权服务器发的授权码,拿去攻击者的 token 端点兑换。授权码一旦交出去,攻击者就能拿它去正规服务器换出真的令牌,代表用户访问真的资源。
这类攻击在 OAuth 安全文献里被称为 mix-up(混淆)攻击,核心特征就是:协议本身没有在授权响应里标明”这条响应是谁发的”,客户端只能靠自己的上下文猜。RFC 9207 做的事很简单——让授权服务器在授权响应里显式带上 iss,标明签发者身份;客户端收到后必须比对它是否等于本次授权流程预期的那个授权服务器,不一致就直接终止,不去换 token。
一句话概括:state 解决的是”这条回调对应我发出的哪一次请求”,iss 解决的是”这条回调到底是谁发来的”。两者防的不是同一件事,有了 state 不等于不需要 iss。
具体到代码,客户端要多做哪几件事
规范原文的表述以官方规范文档当前版本为准,这里只说工程上的落点,方便你对着自己的实现自查:
- 在发起授权前,把”预期签发者”记下来。 不是记 server 的地址,而是记你从授权服务器元数据里解析出来的签发者标识。它应该和这次授权会话(通常以 state 为键)绑定在一起存。
- 回调处理里增加一个硬校验分支。 拿到回调参数后,先取
iss,和第 1 步存下的预期值做精确字符串比对,不做归一化猜测、不做前缀匹配、不忽略大小写。不一致就当作攻击处理,丢弃授权码并终止流程。 - 缺失也要当失败处理。 如果授权服务器声明了支持这项能力却没返回
iss,或者你所处的部署要求必须有,那”没带iss”应该走失败分支,而不是默默降级成旧行为。降级容错是这类安全机制最常见的失效方式——代码写了校验,但一遇到没有就跳过,等于没写。 - 错误要能看见。 校验失败时的日志得能区分”iss 不匹配”和普通的授权失败,否则线上真出问题时你只会看到一堆语焉不详的 auth error。日志里别把授权码本身打出来,这一点和 API Key 怎么管才不泄漏 里讲的原则是一致的——凭证类字符串不进日志。
- 别把校验逻辑写在业务层。 如果你的客户端支持连多个 MCP server,这段校验应该收在统一的授权模块里,由框架强制执行,而不是让每个 server 的接入代码各写一遍。写多份就一定会有一份忘了写。
如果你用的是官方 SDK 且已经升到支持这版规范的版本,多数情况下这套校验由 SDK 内部完成,你要做的是确认自己没有绕过它——比如自己手搓了回调处理、或者为了调试临时关掉了校验然后忘了打开。
服务端和授权服务器这边要配合什么
iss 校验是客户端义务,但它成立的前提是授权服务器真的会返回。所以如果你是 MCP server 的部署方:
- 确认你对接的 IdP 支持 RFC 9207 定义的这项行为,并在元数据里正确声明。企业自建的老旧 IdP 未必开箱支持,这类升级往往需要单独排期,不要假设”我们用的是标准 OAuth 所以肯定有”。
- 元数据要能被客户端稳定发现。这版规范同时在推 MCP Server Cards——一个通过
.well-knownURL 暴露 server 元数据的标准,让注册表和爬虫不用真的建立连接就能发现能力。元数据发现这条链路做扎实,客户端才有可靠的”预期签发者”来源。 - 想让别人找得到你的 server,官方注册表是
registry.modelcontextprotocol.io,社区驱动、由 modelcontextprotocol 的 GitHub 组织维护,提供 server 发现、文档和 API 参考。
破坏性变更:这次真的会不兼容
这部分必须说清楚,因为它直接决定你的升级排期。
规范维护者 David Soria Parra 对这次修订的评价是,这是自加入授权以来最实质的变更,原话是 “A lot of things that made MCP are gone.”(很多曾经构成 MCP 的东西没了。)配套的事实是:2026-07-28 版本的 server 可能无法与旧 client 协同,反之亦然。
好消息是官方同时给出了正式的弃用策略,旧版本有 12 个月的窗口。这意味着你不需要今天就全量切换,但也不该无限期拖着——12 个月是窗口不是承诺永久支持。
务实的排期建议是这样:
- 先做客户端的
iss校验和授权模块升级。 这一条是纯加固,实现正确的话不会破坏与旧授权服务器的互通(对方不支持时按你的策略决定是拒绝还是有条件放行,但这个策略要显式写出来,不能是”忘了处理”)。 - 再评估协议内核的无状态化。 这版规范里 MCP 在协议层是无状态的,由另外 6 个 SEP 共同实现。实际收益很直接:以前需要粘性会话、共享 session 存储、网关做深度包检测才能跑的远程 server,现在可以直接放在普通轮询负载均衡后面,按
Mcp-Method头路由。这里有个容易读歪的地方——它说的是协议层不再要求会话追踪,不是”MCP 不能有状态了”,应用层自己的状态怎么存是另一回事。 - 注意 Tasks 已经移出核心。 用于长时间运行操作的 Tasks 特性从核心协议挪到了 extension。如果你的实现依赖它,升级时要按 extension 的方式重新引入。Extensions 框架也允许自建 extension 与官方认可的并存。
- 新旧混跑期要有明确的版本协商和降级路径。 既然新旧可能不互通,你的客户端在连到旧 server 时应该给出可读的错误提示,而不是抛一个底层解析异常。排查这类问题的思路可以参考 Claude Code 的 MCP 连不上、配置不生效怎么排查 里的分层排查方法:先确认协议版本能不能对上,再看授权,最后才怀疑业务参数。
为什么这轮加固值得认真对待
MCP 已经不是某一家的内部协议了。2025 年 12 月,Anthropic 把 MCP 捐给了 Linux 基金会下的 Agentic AI Foundation,成为厂商中立、社区治理的标准;OpenAI、Google、Microsoft、AWS 都已经把它接进各自的 agent 栈。按官方与行业公开资料的口径,目前有超过 10,000 个公开 MCP server 跑在生产环境里,SDK 月下载量超过 9,700 万——这些是公开资料汇总的量级参考,不是精确统计,别拿去做严肃的对外引用。
量级说明一件事:授权这块一旦有系统性缺陷,影响面不再是”某个 demo 项目”。规范把 iss 校验从可选做法提升为客户端义务,正是因为在这种规模下,指望每个实现者自己读安全文献补齐是不现实的。
诚实说局限
有几点必须讲明白:
- 这篇讲的是为什么要校验、工程上落在哪几个点,不是逐条复述规范原文。具体的字段名、错误码、必须/应当的措辞强度,请以官方规范文档和官方博客当前版本为准,规范正文才是唯一权威。
iss校验不是万能药。它防的是签发者混淆这一类问题,不替代 PKCE、不替代 redirect URI 精确匹配、不替代 token 的受众校验。这些是并列关系,不是二选一。- 这版规范发布时间很近,中文资料几乎为零,很多第三方教程和聚合站点上的信息已经过期——有的站点还把更早的版本当成当前稳定版在写。遇到和官方博客不一致的说法,一律以官方为准,不要因为某篇中文教程写得详细就采信它的版本号和时间线。
- 6 个授权 SEP 里,本篇只展开了被官方点名的
iss校验这一条。其余几条的具体内容请直接读规范,本篇不替它们下结论。
小结
iss 校验解决的是”这条授权响应到底是谁发来的”,它和 state 防的不是同一件事,有 state 不等于安全。新版规范把它定为客户端义务,源头是 MCP 一个客户端连多个 server、多个授权服务器的真实拓扑,这种形态天然容易踩混淆攻击的坑。工程落点只有几步:授权前记下预期签发者、回调时精确比对、缺失不降级、失败可观测、校验收在统一模块里。这轮修订整体有破坏性,新旧 client/server 可能不互通,但旧版本有 12 个月窗口,可以先做纯加固的授权部分,再排协议内核无状态化和 Tasks 移出核心带来的改造。最后一句老话:规范原文才是权威,这篇只帮你把该看的地方指出来。