授权
1. 介绍
1.1 目的和范围
模型上下文协议 (Model Context Protocol) 在传输层提供授权功能,使 MCP 客户端能够代表资源所有者向受限的 MCP 服务器发出请求。本规范定义了基于 HTTP 传输的授权流程。
1.2 协议要求
授权对于 MCP 实现是可选的。当支持时:
- 使用基于 HTTP 传输的实现应该符合本规范。
- 使用 STDIO 传输的实现不应该遵循本规范,而应该从环境中检索凭据。
- 使用替代传输的实现必须遵循其协议的既定安全最佳实践。
1.3 标准合规性
此授权机制基于下面列出的既定规范,但实现了其功能的选定子集,以确保安全性和互操作性,同时保持简单性:
- OAuth 2.1 IETF 草案 (draft-ietf-oauth-v2-1-13)
- OAuth 2.0 授权服务器元数据 (RFC8414)
- OAuth 2.0 动态客户端注册协议 (RFC7591)
- OAuth 2.0 受保护资源元数据 (RFC9728)
2. 授权流程
2.1 角色
受保护的 MCP 服务器充当 OAuth 2.1 资源服务器,能够使用访问令牌接受和响应受保护的资源请求。
MCP 客户端充当 OAuth 2.1 客户端,代表资源所有者发出受保护的资源请求。
授权服务器负责与用户交互(如有必要)并颁发用于 MCP 服务器的访问令牌。授权服务器的实现细节超出了本规范的范围。它可以与资源服务器托管在一起或作为单独的实体。授权服务器发现部分 指定了 MCP 服务器如何向客户端指示其相应授权服务器的位置。
2.2 概述
授权服务器必须实现 OAuth 2.1,为机密客户端和公共客户端提供适当的安全措施。
授权服务器和 MCP 客户端应该支持 OAuth 2.0 动态客户端注册协议 (RFC7591)。
MCP 服务器必须实现 OAuth 2.0 受保护资源元数据 (RFC9728)。MCP 客户端必须使用 OAuth 2.0 受保护资源元数据进行授权服务器发现。
授权服务器必须提供 OAuth 2.0 授权服务器元数据 (RFC8414)。MCP 客户端必须使用 OAuth 2.0 授权服务器元数据。
2.3 授权服务器发现
本节描述 MCP 服务器向 MCP 客户端宣告其关联授权服务器的机制,以及 MCP 客户端可以确定授权服务器端点和支持功能的发现过程。
2.3.1 授权服务器位置
MCP 服务器必须实现 OAuth 2.0 受保护资源元数据 (RFC9728) 规范来指示授权服务器的位置。MCP 服务器返回的受保护资源元数据文档必须包含 authorization_servers
字段,其中包含至少一个授权服务器。
authorization_servers
的具体使用超出了本规范的范围;实现者应咨询 OAuth 2.0 受保护资源元数据 (RFC9728) 以获取实现细节指导。
实现者应注意,受保护资源元数据文档可以定义多个授权服务器。选择使用哪个授权服务器的责任在于 MCP 客户端,遵循 RFC9728 第 7.6 节"授权服务器" 中指定的指南。
MCP 服务器必须在返回 401 未授权时使用 HTTP 头 WWW-Authenticate
来指示资源服务器元数据 URL 的位置,如 RFC9728 第 5.1 节"WWW-Authenticate 响应" 中所述。
MCP 客户端必须能够解析 WWW-Authenticate
头并适当响应来自 MCP 服务器的 HTTP 401 未授权
响应。
2.3.2 服务器元数据发现
MCP 客户端必须遵循 OAuth 2.0 授权服务器元数据 RFC8414 规范来获取与授权服务器交互所需的信息。
2.3.3 时序图
以下图表概述了一个示例流程:
2.4 动态客户端注册
MCP 客户端和授权服务器应该支持 OAuth 2.0 动态客户端注册协议 RFC7591,以允许 MCP 客户端在没有用户交互的情况下获取 OAuth 客户端 ID。这为客户端自动向新的授权服务器注册提供了标准化方式,这对 MCP 至关重要,因为:
- 客户端可能事先不知道所有可能的 MCP 服务器及其授权服务器。
- 手动注册会为用户带来阻力。
- 它使无缝连接到新的 MCP 服务器及其授权服务器成为可能。
- 授权服务器可以实现自己的注册策略。
任何不支持动态客户端注册的授权服务器需要提供获取客户端 ID(以及,如果适用,客户端凭据)的替代方式。对于这些授权服务器之一,MCP 客户端将必须:
- 硬编码一个客户端 ID(以及,如果适用,客户端凭据),专门供 MCP 客户端在与该授权服务器交互时使用,或者
- 向用户呈现一个 UI,允许他们在自己注册 OAuth 客户端后输入这些详细信息(例如,通过服务器托管的配置界面)。
2.5 授权流程步骤
完整的授权流程如下进行:
2.5.1 资源参数实现
MCP 客户端必须实现 OAuth 2.0 的资源指示器,如 RFC 8707 中定义的,以明确指定请求令牌的目标资源。resource
参数:
- 必须包含在授权请求和令牌请求中。
- 必须标识客户端打算使用令牌的 MCP 服务器。
- 必须使用 MCP 服务器的规范 URI,如 RFC 8707 第 2 节 中定义的。
2.5.1.1 规范服务器 URI
在本规范中,MCP 服务器的规范 URI 定义为 RFC 8707 第 2 节 中指定的资源标识符,并与 RFC 9728 中的 resource
参数保持一致。
MCP 客户端应该为他们打算访问的 MCP 服务器提供最具体的 URI,遵循 RFC 8707 中的指导。虽然规范形式使用小写的方案和主机组件,但实现应该接受大写的方案和主机组件以提高健壮性和互操作性。
有效规范 URI 的示例:
https://mcp.example.com/mcp
https://mcp.example.com
https://mcp.example.com:8443
https://mcp.example.com/server/mcp
(当路径组件对于标识单个 MCP 服务器是必要的时候)
无效规范 URI 的示例:
mcp.example.com
(缺少方案)https://mcp.example.com#fragment
(包含片段)
注意: 虽然
https://mcp.example.com/
(带尾随斜杠) 和https://mcp.example.com
(不带尾随斜杠) 根据 RFC 3986 技术上都是有效的绝对 URI,但实现应该一致地使用不带尾随斜杠的形式以获得更好的互操作性,除非尾随斜杠对特定资源具有语义意义。
例如,如果访问位于 https://mcp.example.com
的 MCP 服务器,授权请求将包含:
&resource=https%3A%2F%2Fmcp.example.com
无论授权服务器是否支持此参数,MCP 客户端必须发送此参数。
2.6 访问令牌使用
2.6.1 令牌要求
向 MCP 服务器发出请求时的访问令牌处理必须符合 OAuth 2.1 第 5 节"资源请求" 中定义的要求。具体来说:
MCP 客户端必须使用 OAuth 2.1 第 5.1.1 节 中定义的 Authorization 请求头字段:
httpAuthorization: Bearer <access-token>
请注意,即使授权是同一逻辑会话的一部分,授权必须包含在从客户端到服务器的每个 HTTP 请求中。
访问令牌不得包含在 URI 查询字符串中
示例请求:
httpGET /mcp HTTP/1.1 Host: mcp.example.com Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
2.6.2 令牌处理
MCP 服务器在其作为 OAuth 2.1 资源服务器的角色中,必须按照 OAuth 2.1 第 5.2 节 中的描述验证访问令牌。MCP 服务器必须根据 RFC 8707 第 2 节 验证访问令牌是专门为它们作为预期受众而颁发的。如果验证失败,服务器必须根据 OAuth 2.1 第 5.3 节 错误处理要求进行响应。无效或过期的令牌必须收到 HTTP 401 响应。
MCP 客户端不得向 MCP 服务器发送除由 MCP 服务器的授权服务器颁发的令牌之外的其他令牌。
授权服务器必须只接受对其自己资源有效的令牌。
MCP 服务器不得接受或传输任何其他令牌。
2.7 错误处理
服务器必须为授权错误返回适当的 HTTP 状态代码:
状态代码 | 描述 | 使用 |
---|---|---|
401 | 未授权 | 需要授权或令牌无效 |
403 | 禁止 | 无效范围或权限不足 |
400 | 错误请求 | 格式错误的授权请求 |
3. 安全考虑
实现必须遵循 OAuth 2.1 第 7 节"安全考虑" 中列出的 OAuth 2.1 安全最佳实践。
3.1 令牌受众绑定和验证
RFC 8707 资源指示器通过将令牌绑定到其预期受众当授权服务器支持该功能时提供关键的安全优势。为了启用当前和未来的采用:
- MCP 客户端必须在授权和令牌请求中包含
resource
参数,如资源参数实现部分中指定的 - MCP 服务器必须验证呈现给它们的令牌是专门为其使用而颁发的
安全最佳实践文档 概述了为什么令牌受众验证至关重要以及为什么明确禁止令牌传递。
3.2 令牌盗窃
获得客户端存储的令牌或服务器上缓存或记录的令牌的攻击者可以通过对资源服务器看起来合法的请求访问受保护的资源。
客户端和服务器必须实现安全的令牌存储并遵循 OAuth 最佳实践,如 OAuth 2.1,第 7.1 节 中概述的。
授权服务器应该颁发短期访问令牌以减少泄露令牌的影响。对于公共客户端,授权服务器必须按照 OAuth 2.1 第 4.3.1 节"令牌端点扩展" 中的描述轮换刷新令牌。
3.3 通信安全
实现必须遵循 OAuth 2.1 第 1.5 节"通信安全"。
具体来说:
- 所有授权服务器端点必须通过 HTTPS 提供服务。
- 所有重定向 URI 必须是
localhost
或使用 HTTPS。
3.4 授权码保护
已经获得授权响应中包含的授权码的攻击者可以尝试兑换授权码以获取访问令牌或以其他方式使用授权码。(在 OAuth 2.1 第 7.5 节 中进一步描述)
为了减轻这种情况,MCP 客户端必须根据 OAuth 2.1 第 7.5.2 节 实现 PKCE。PKCE 通过要求客户端创建秘密验证器-挑战对来帮助防止授权码拦截和注入攻击,确保只有原始请求者可以将授权码交换为令牌。
3.5 开放重定向
攻击者可能制作恶意重定向 URI 以将用户引导到钓鱼网站。
MCP 客户端必须向授权服务器注册重定向 URI。
授权服务器必须根据预注册的值验证确切的重定向 URI 以防止重定向攻击。
MCP 客户端应该在授权码流程中使用和验证状态参数,并丢弃任何不包含或与原始状态不匹配的结果。
授权服务器必须采取预防措施防止将用户代理重定向到不受信任的 URI,遵循 OAuth 2.1 第 7.12.2 节 中列出的建议。
授权服务器应该只有在信任重定向 URI 时才自动重定向用户代理。如果 URI 不受信任,授权服务器可以通知用户并依赖用户做出正确的决定。
3.6 混淆代理问题
攻击者可以利用充当第三方 API 中介的 MCP 服务器,导致混淆代理漏洞。通过使用被盗的授权码,他们可以在没有用户同意的情况下获得访问令牌。
使用静态客户端 ID 的 MCP 代理服务器必须在转发到第三方授权服务器之前为每个动态注册的客户端获得用户同意(这可能需要额外的同意)。
3.7 访问令牌权限限制
如果服务器接受为其他资源颁发的令牌,攻击者可以获得未经授权的访问或以其他方式危害 MCP 服务器。
此漏洞有两个关键维度:
- 受众验证失败。 当 MCP 服务器不验证令牌是否专门为其预期时(例如,通过受众声明,如 RFC9068 中提到的),它可能接受最初为其他服务颁发的令牌。这打破了基本的 OAuth 安全边界,允许攻击者在不同于预期的服务中重用合法令牌。
- 令牌传递。 如果 MCP 服务器不仅接受具有错误受众的令牌,而且还将这些未修改的令牌转发给下游服务,它可能会导致"混淆代理"问题,其中下游 API 可能错误地信任令牌,就好像它来自 MCP 服务器或假设令牌已被上游 API 验证。有关其他详细信息,请参阅安全最佳实践指南的令牌传递部分。
MCP 服务器必须在处理请求之前验证访问令牌,确保访问令牌专门为 MCP 服务器颁发,并采取所有必要步骤确保不会将数据返回给未经授权的各方。
MCP 服务器必须遵循 OAuth 2.1 - 第 5.2 节 中的指南来验证入站令牌。
MCP 服务器必须只接受专门为它们预期的令牌,必须拒绝不包含它们在受众声明中的令牌或以其他方式验证它们是令牌的预期接收者。有关详细信息,请参阅安全最佳实践令牌传递部分。
如果 MCP 服务器向上游 API 发出请求,它可能充当它们的 OAuth 客户端。在上游 API 中使用的访问令牌是一个单独的令牌,由上游授权服务器颁发。MCP 服务器不得传递从 MCP 客户端收到的令牌。
MCP 客户端必须实现并使用 RFC 8707 - OAuth 2.0 的资源指示器 中定义的 resource
参数,以明确指定请求令牌的目标资源。此要求与 RFC 9728 第 7.4 节 中的建议保持一致。这确保访问令牌绑定到其预期资源,并且不能在不同服务中被滥用。