MCP 授权机制拆解:OAuth 2.1 落进 MCP 的完整流程(2026-07-28 规范版)
MCP 授权规范逐条拆解:角色映射(服务器=资源服务器、客户端=OAuth 客户端)、RFC9728 发现、三种客户端注册方式、iss 响应校验表、resource 参数与 canonical URI、token 使用红线与 step-up 授权流。
操作步骤
发现保护资源元数据
对受保护 MCP 服务器请求 RFC9728 Protected Resource Metadata,取得授权服务器位置;再经 RFC8414 或 OIDC Discovery 获取授权服务器端点与能力(两种发现机制客户端都必须支持)。
获取 client ID
按优先级走三种注册机制之一:Client ID Metadata Documents、预注册、或动态客户端注册(RFC7591,已弃用,仅作兼容)。
发起带 resource 的授权请求
授权请求与 token 请求都必须携带 RFC8707 resource 参数,取值为 MCP 服务器的 canonical URI(小写 scheme/host、推荐无尾斜杠);PKCE verifier 与 issuer 记录到同一请求上下文。
校验授权响应
按 RFC9207 校验 iss:元数据声明支持而响应缺 iss 时拒绝响应;iss 存在时与记录值做严格字符串比较(不做大小写折叠或规范化);该校验同样适用于错误响应。
正确使用 token
每个请求用 Authorization: Bearer 头携带 token,禁止放 query string;只向目标 MCP 服务器发送其授权服务器签发的 token,并始终带 resource 参数。
处理 scope 挑战
初始 scope 按 401 挑战优先、scopes_supported 兜底;运行期收到 403 + insufficient_scope 时按 WWW-Authenticate 给出的 scope 走 step-up 授权,重授权保留既有 scope。
MCP 的远程服务器要接真实用户与真实数据,授权就是绕不开的一层。2026-07-28 规范版的 Authorization 章节(2026-09-03 核对)把这件事标准化:MCP 不发明新协议,而是站在 OAuth 2.1 草案与一排 RFC 的肩膀上,规定了一个选择性子集——MCP 服务器扮演什么角色、客户端如何发现授权服务器、怎么注册、token 怎么带、scope 怎么最小化。本文按实现者的视角把规范拆成可执行的规则,所有 MUST / SHOULD 均引自规范原文。
1. 先分清:谁扮演什么角色,谁需要 OAuth
规范的角色映射非常干净:
| MCP 世界 | OAuth 世界 |
|---|---|
| 受保护的 MCP 服务器 | OAuth 2.1 资源服务器(Resource Server) |
| MCP 客户端 | OAuth 2.1 客户端(Client) |
| 授权服务器 | 与用户交互并签发 access token;实现细节不在规范范围内 |
授权是可选能力,但按传输方式区别对待:
- HTTP 传输的实现 SHOULD 遵循本规范;
- stdio 传输的实现 SHOULD NOT 遵循——凭据从环境变量获取(与《MCP 调试实战:Inspector、日志规范与连接问题排查链》里"环境变量继承受限"的机制是同一套);
- 其他传输 MUST 遵循各自协议的安全最佳实践。
2. 标准基座:MCP 用了 OAuth 生态的哪几个件
规范声明自己基于以下标准的选择性子集(完整清单引自规范):
| 标准 | 在 MCP 授权里的角色 |
|---|---|
| OAuth 2.1(draft-ietf-oauth-v2-1-13) | 基座:授权服务器 MUST 实现 |
| RFC 6750 | Bearer token 使用 + WWW-Authenticate scope 挑战 |
| RFC 8414 / OIDC Discovery | 授权服务器元数据发现(二选一必须提供,客户端两种都必须支持) |
| RFC 7591 | 动态客户端注册(已弃用,仅为兼容保留,降级为 MAY) |
| RFC 8707 | resource 参数:显式指定 token 的目标资源 |
| RFC 9728 | Protected Resource Metadata:服务器 MUST 实现、客户端 MUST 使用 |
| RFC 9207 | iss 参数:授权响应校验 |
| Client ID Metadata Documents(草案) | 注册机制优先项(SHOULD 支持) |
3. 发现与注册:两条 MUST 与三种注册方式
发现:受保护 MCP 服务器 MUST 实现 RFC 9728,通过 Protected Resource Metadata 声明自己的授权服务器;客户端 MUST 使用该元数据完成发现,再对授权服务器做元数据发现拿到端点与能力。
注册:发起授权前,客户端 MUST 通过三种机制之一获得 client ID——Client ID Metadata Documents、预注册、或动态客户端注册(RFC 7591)。注意规范给动态注册的定性:已弃用(deprecated),仅为兼容不支持 Client ID Metadata Documents 的授权服务器而保留;新实现 SHOULD 走 Client ID Metadata Documents。
4. 授权响应校验:iss 的四种组合
客户端在重定向用户代理前,必须把"已验证元数据里的 issuer"与 PKCE verifier 存进同一条请求记录;响应校验依赖这条记录的真实性。授权服务器 SHOULD 在响应里带 iss 参数(RFC 9207),并用元数据的 authorization_response_iss_parameter_supported 声明。客户端的处理规则(规范原表):
| 声明支持 iss | 响应里有 iss | 客户端动作 |
|---|---|---|
| true | 有 | 与记录 issuer 做简单字符串比较(RFC 3986 §6.2.1) |
| true | 无 | 拒绝该响应 |
| false / 未声明 | 有 | 同样与记录 issuer 比较 |
| false / 未声明 | 无 | 继续 |
三个细节:比较不得做大小写折叠、默认端口省略、尾斜杠或百分号规范化;规范预告未来版本会把 iss 从 SHOULD 升级为 MUST,建议实现者现在就发并校验;校验同样适用于错误响应——iss 不匹配时客户端 MUST NOT 展示或使用响应里的 error / error_description / error_uri(防注入)。
5. resource 参数:token 只为这个服务器签发
客户端 MUST 实现 RFC 8707 的 resource 参数:授权请求与 token 请求都要带,取值为目标 MCP 服务器的 canonical URI(小写 scheme 与 host;实现方 SHOULD 接受大写以稳健互操作),且无论授权服务器是否支持都必须发送。
合法 canonical URI 示例(引自规范):
https://mcp.example.com/mcp
https://mcp.example.com
https://mcp.example.com:8443
https://mcp.example.com/server/mcp(路径用于区分服务器时)
无效示例:
mcp.example.com (缺 scheme)
https://mcp.example.com#fragment (含 fragment)
规范还建议:带尾斜杠与不带在 RFC 3986 下都合法,但统一用无尾斜杠形式以获得更好的互操作性(除非尾斜杠对该资源有语义)。授权请求中的形态如 &resource=https%3A%2F%2Fmcp.example.com。
6. token 使用红线
请求侧(MCP 客户端):
GET /mcp HTTP/1.1
Host: mcp.example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
- token 必须放在
Authorization: Bearer请求头,且客户端到服务器的每个请求都要带; - token MUST NOT 出现在 URI query string。
服务器侧(MCP 服务器 = 资源服务器):
- 按 OAuth 2.1 校验 token,并 MUST 校验 audience(RFC 8707 §2——这个 token 是不是签给本服务器的);
- 无效或过期 token 返回 HTTP 401;
- 客户端 MUST NOT 向 MCP 服务器发送非其授权服务器签发的 token;
- 服务器 MUST NOT 接受或转发任何其他 token——这是 Token Passthrough 反模式(见《MCP 安全指南:官方 8 类攻击面与缓解清单》)在授权规范里的正式条款。
7. scope:最小化与 step-up
初始授权的 scope 选择优先级(客户端 SHOULD 遵循最小权限):
- 首选 401 响应
WWW-Authenticate里的scope(RFC 6750 §3); - 没有则用 Protected Resource Metadata 的
scopes_supported(未定义则省略 scope 参数)。
两条 MUST 级约束:客户端 MUST NOT 假定挑战 scope 与 scopes_supported 有任何集合关系(子集/超集都可能),挑战里的 scope 对当前操作权威;scopes_supported 的定位是基础功能的最小集,额外权限通过 step-up 授权流增量获取。服务器返回 401 时的标准形态:
HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://mcp.example.com/.well-known/oauth-protected-resource",
scope="files:read"
8. 运行期权限不足与错误码
| 状态码 | 语义 | 使用场景 |
|---|---|---|
| 401 | Unauthorized | 需要授权,或 token 无效/过期 |
| 403 | Forbidden | scope 无效或权限不足 |
| 400 | Bad Request | 授权请求畸形 |
运行期持 token 但权限不足:服务器返回 403 + WWW-Authenticate 带 error="insufficient_scope"、所需最小 scope 集合、以及 resource_metadata(与 401 响应保持一致)。客户端据此走 step-up:向用户/授权服务器补请求所需 scope,重授权时 SHOULD 保留既有 scope,避免丢掉其他操作已获权限。
refresh token 的配套规则也值得记:客户端 MUST 保密传输与存储、SHOULD 在客户端元数据 grant_types 里声明 refresh_token、可在授权服务器 scopes_supported 含 offline_access 时请求之;并且 MUST NOT 假定一定会签发——决定权在授权服务器;服务器侧则 SHOULD NOT 把 offline_access 放进 WWW-Authenticate 或 scopes_supported(它不是资源访问需求)。
9. 常见错误与排查
- stdio 服务器套 OAuth:规范明确 stdio SHOULD NOT 走这套——凭据走环境变量,别把 HTTP 授权流程硬套给本地进程。
- token 进了 query string:规范明令禁止;只走 Authorization 头。
- 漏发 resource 参数:"授权服务器不支持就不发"是错的——MUST 发,且用 canonical URI。
- audience 不校验:不校验 audience 就接受了可能面向别的资源的 token,正是 Token Passthrough 类风险的入口。
- iss 比较前做规范化:大小写折叠、尾斜杠、端口省略都会破坏比较语义——简单字符串比较。
- 把 scopes_supported 当全量目录请求:它是基础最小集,额外权限走 step-up。
10. 下一步
- 授权之外的实施层攻击面:《MCP 安全指南:官方 8 类攻击面与缓解清单》。
- 调试授权与连接问题:《MCP 调试实战:Inspector、日志规范与连接问题排查链》。
- 协议本体与三层架构:《Model Context Protocol 完全指南:MCP 工作机制与实战》。
关键要点
- 角色映射:受保护 MCP 服务器 = OAuth 2.1 资源服务器;MCP 客户端 = OAuth 2.1 客户端;授权服务器实现细节不在规范范围内(可与资源服务器同host,也可独立)
- 授权是可选能力:HTTP 传输 SHOULD 遵循本规范;stdio 传输 SHOULD NOT 使用(凭据从环境获取);其他传输 MUST 遵循各自协议的安全最佳实践
- 发现与注册:MCP 服务器 MUST 实现 RFC9728 Protected Resource Metadata,客户端 MUST 用它发现授权服务器;注册三选一——Client ID Metadata Documents(SHOULD 支持)、预注册、动态注册 RFC7591(MAY,已弃用仅为兼容保留)
- 授权码响应校验:客户端 MUST 记录 issuer 并按 RFC9207 校验 iss;四种组合的处理表(含 true+absent 时拒绝响应);不得做大小写折叠、默认端口省略等任何规范化
- token 红线:只走 Authorization: Bearer 头且每个请求都带;MUST NOT 放 URI query string;MUST 带 RFC8707 resource 参数(canonical URI,推荐无尾斜杠);服务器 MUST 校验 audience 且 MUST NOT 接受或转发其他 token
- scope 最小化 + step-up:401 的 WWW-Authenticate scope 对当前请求权威(客户端 MUST NOT 假定它与 scopes_supported 的集合关系);运行期权限不足返回 403 + error=insufficient_scope + 所需 scope
常见问题
官方参考
相关文章
MCP 调试实战:Inspector、日志规范与连接问题排查链
MCP 集成调试的官方方法:Inspector 交互式测试 UI 为什么是第一站、stdio 与 Streamable HTTP 的日志怎么打(notifications/message 已在 2026-07-28 规范版弃用)、启动失败三类根因与连接失败五步排查链。
阅读全文MCP 安全指南:官方 8 类攻击面与缓解清单
MCP 官方安全最佳实践拆解:Confused Deputy、Token Passthrough、SSRF、会话劫持、本地 Server 攻击、OAuth URL 校验、stdio 代理安全、权限最小化——每类攻击的原理与官方缓解要求。
阅读全文MCP 服务器开发实战:协议、调试、安全与生产部署
MCP 服务器 production 必备能力:协议深入(JSON-RPC 2.0 / lifecycle / capabilities 协商)、Inspector 调试、安全模式(prompt injection / OAuth scope / 审计)、三种传输选型(stdio / Streamable HTTP / SSE)实战。
阅读全文订阅 GPTMap Weekly
每周一封邮件,精选 OpenAI 重要更新、深度解读与最佳实践。无广告,可随时退订。