MCP 授权机制的现状、问题和解决思路
MCP 服务器(提供 AI 模型上下文的一方)需要一种机制来验证客户端(使用模型的一方)是否有权访问其资源。在该协议的设计中,这一机制是一种基于 OAuth 2.1的标准授权方案。简单来说,MCP 的授权流程是一个标准且安全的 OAuth 2.1 委托授权模式。它没有重新发明轮子,而是复用了业界成熟方案:客户端通过独立可信的授权服务器获取“通行证”(访问令牌),再用该“通行证”访问受保护的 MCP
MCP 授权流程介绍
MCP 服务器(提供 AI 模型上下文的一方)需要一种机制来验证客户端(使用模型的一方)是否有权访问其资源。在该协议的设计中,这一机制是一种 基于 OAuth 2.1 的标准授权方案。
核心组件
- MCP 服务器 (MCP Server):扮演 资源服务器 (Resource Server) 的角色,保护需要授权才能访问的资源(例如
tools/call
接口)。 - MCP 客户端 (MCP Client):需要访问 MCP 服务器资源的应用程序。
- 授权服务器 (Authorization Server):负责验证客户端身份并发放访问令牌(Access Token)的独立服务。
授权流程步骤 (Authorization Flow)
整个流程遵循标准的 OAuth 2.1 模式,可以概括为以下几个关键步骤:
- 首次请求(无令牌):
MCP 客户端第一次向 MCP 服务器发起请求时,请求中没有包含访问令牌。 - 返回认证挑战(WWW-Authenticate):
MCP 服务器发现请求没有有效令牌,于是拒绝该请求,并返回401 Unauthorized
。
最关键的是,响应头包含WWW-Authenticate
字段,该字段告诉客户端到哪里获取 Resource Metadata。 -
客户端请求授权:
- MCP 客户端解析
WWW-Authenticate
头,拿到 Resource Metadata 的地址。 - MCP 客户端请求 Resource Metadata,从中获取授权服务器地址和所需的 scope 等信息。
- MCP 客户端请求授权服务器的 Discovery Endpoint,获取服务器信息(如注册接口等)。
- (如果是第一次访问)MCP 客户端向该授权服务器动态注册(Dynamic Client Registration, DCR),得到客户端 ID。
- 客户端将用户重定向到授权服务器,并带上自己的客户端 ID、请求的权限范围(scope)、资源 URL(resource 参数)等信息,发起授权请求。
- MCP 客户端解析
- 授权服务器进行认证和授权:
授权服务器验证用户身份(例如登录)。用户同意授权后,授权服务器向客户端发放 授权码 (Authorization Code)。 - 客户端用授权码换取令牌:
客户端拿着授权码,向授权服务器的令牌端点(Token Endpoint)发起请求,以换取 访问令牌 (Access Token)(以及可选刷新令牌)。 - 携带令牌再次请求:
客户端成功获取访问令牌后,重新向 MCP 服务器发起之前的请求,并在Authorization
头中携带该访问令牌(通常是Bearer <token>
)。 - 服务器验证令牌并响应:
MCP 服务器收到带令牌的请求后,会与授权服务器通信(或使用本地缓存的公钥)验证令牌的有效性、签名、有效期以及权限范围。验证通过后,服务器处理请求并返回成功响应。
安全注意事项
该规范强调以下关键安全点:
- 令牌绑定与验证:令牌必须与特定受众(audience,即 MCP 服务器)绑定,防止被滥用。
- 通信安全:所有通信必须使用 TLS 加密,防止窃听。
- 防止令牌被盗:推荐使用短生命周期令牌,并遵循 OAuth 2.1 最佳实践。
- 防止开放重定向:确保重定向过程不被攻击者利用。
- 解决“困惑的副手”问题 (Confused Deputy Problem):确保客户端不被诱骗执行非预期操作。
总结
简单来说,MCP 的授权流程是一个 标准且安全的 OAuth 2.1 委托授权模式。它没有重新发明轮子,而是复用了业界成熟方案:客户端通过独立可信的授权服务器获取“通行证”(访问令牌),再用该“通行证”访问受保护的 MCP 服务器资源,确保安全性、标准化与互操作性。
MCP 授权机制的现状和问题
是不是觉得上面的内容像是 AI 生成的?其实就是我把 Gemini 2.5 Pro 的回复,补充若干缺失内容之后贴出来。老实说,AI 回复大体上是对的,只是漏了关键的几点,比如:
- MCP 服务器不是直接返回授权服务器的地址,而是返回 Resource Metadata 的地址。
- MCP 客户端也不是直接就能访问授权服务器,而是先去访问授权服务器的 Discovery Endpoint。
- MCP 客户端需要向授权服务器动态注册(DCR),才能拿到自己在这个服务器上的客户端 ID。
可见这套协议有一定复杂度,连 AI 也不能完整答对。
Gemini 的回复只是抛砖引玉的“砖头”,以下才是本文重点——聊聊 MCP 授权机制的一些现状和问题。
现状
所谓“现状”,就是生态整体尚未成熟。毕竟这是一个出现不到三个月的新机制(当前这版授权协议出现于 2025-06-18 版本的 MCP),而且基于 OAuth 的较新功能,上下游支持需要时间。
Cursor 算是一个主流 MCP 客户端实现。然而我基于 2025-08-13
版本的 Cursor 测试 MCP 授权机制,还是发现了两个 bug:
第一个 bug:Cursor 会丢失 Resource Metadata 的地址。复现步骤:
- Cursor 请求 MCP 服务器。MCP 服务器返回 401 和 Resource Metadata URL。
- Cursor 跟踪该 URL 并发现授权服务器。
- 授权服务器返回重定向响应要求登录。Cursor 打开浏览器供用户登录。
- 登录后,用户跳转回 Cursor。
- Cursor 丢失上下文,回退到使用默认的(众所周知的)Resource Metadata URL,不再使用第一步提供的那个 URL。
第二个 bug:在 Access Token 和 Refresh Token 同时过期后,Cursor 一直卡在加载状态,而不是提示用户重新登录。
授权服务器的支持也有限。为避免中间人攻击,MCP 授权要求 MCP 客户端在申请令牌时通过 resource
参数带上资源 URL,授权服务器需将该 URL 写入令牌的 aud
字段,这样 MCP 服务器才能检查令牌的目标是否与资源一致。该行为描述于 RFC 8707:https://www.rfc-editor.org/rfc/rfc8707.html
但主流授权服务器并未完全支持 RFC 8707,现状如下:
- Keycloak:对 RFC 8707 的支持进行中:https://github.com/keycloak/keycloak/discussions/35743#discussioncomment-13515660
- Azure AD:尚未正确支持 RFC 8707。详情:https://github.com/modelcontextprotocol/inspector/issues/685
- Auth0:部分支持,但使用
audience
参数而非 MCP SDK 使用的resource
。详情:https://community.auth0.com/t/rfc-8707-implementation-audienc... - Ory:与 Auth0 相同。详情:https://www.ory.sh/docs/hydra/guides/audiences
问题
在生态尚待完善的同时,MCP 授权机制仍有若干未解决的问题。
首先是当前 MCP 协议和 SDK 中仅实现主流的 Authorization Code Flow。这种 Flow 需要用户交互登录,对当前以 Code Copilot、AI Chat 为主的场景足够。但在 AI Agent 大规模自动运行的未来场景中,缺乏 Machine-to-Machine 授权模式是行不通的。好在 OAuth 已定义多种适用于 M2M 的 Flow,MCP 只需引入即可。
更大的问题在于现行 OAuth 流程依赖客户端动态注册。如果客户端无法在授权服务器上注册,就无法申请令牌。这一机制在 MCP 授权过程中是核心,但现实落地困难,原因有三:
- 多数情况下,注册新身份不只是填表,还需绑定邮箱、手机号等,纯自动化 DCR 难以满足合规要求。
- 当前只支持 Authorization Code Flow,还能通过用户登录补充注册所需信息(例如登录成功后分配客户端 ID);未来若需支持 M2M,则此“人工回填”变通方式失效。
- 动态客户端注册并非 OAuth 主流用法。要安全支持 DCR,现有授权服务器需调整实现方式,例如将客户端 ID 绑定具体用户。
针对基于 OAuth 的授权机制的若干缺陷,社区有人提出基于 HTTP Message Signing 的补充方案:https://github.com/modelcontextprotocol/modelcontextprotocol/issues/1415。该方案中,客户端为每个 MCP 服务器准备一对公私钥及其衍生的指纹(fingerprint)。MCP 服务器需已知客户端公钥(预先获知,或在 initialize
请求时携带)。请求时客户端附带指纹及对参数的签名,服务器据此验证请求完整性与客户端身份。
引入 OAuth 的初衷是降低 MCP 服务器实现成本,以便扩展生态。但随着 MCP 场景扩展,最终会到达一个转折点——服务器需承担比客户端更多的责任。客户端类型繁多且不易统一升级,用户规模增大后势必出现版本碎片化。相比 DCR,HTTP 消息签名使用的公私钥可以随时创建,并可在现有身份体系下提前分发,无需授权服务器投入大量支持。事实上,HTTP Message Signing 在某些场景下可弱化甚至替代授权服务器角色,由 MCP 客户端与服务器直接协商认证细节。OAuth 最初的目标是为第三方提供通用认证授权服务,而 MCP 的认证并非一定要依赖第三方账号体系,直接在 MCP 客户端和服务器之间完成全部认证会更便捷。举例而言:为防中间人攻击,OAuth 模式下客户端申请令牌时需带上资源 URL,授权服务器再把该 URL 写到令牌的 aud
字段,MCP 服务器再比对;采用 HTTP Message Signing 时,客户端直接在请求中带上资源 URL 与签名即可,不需多绕一层。
在 MCP 服务器侧承担更多身份验证还有其他好处:服务器可以更快升级,并通过中间件降低复杂度。
最后需要指出,MCP 授权协议作用于 MCP 客户端与 MCP 服务器之间。当 tools/call
调用第三方服务时,第三方通常需要最终操作者身份。例如某 MCP 服务器提供一个具有“删除资源”能力的 Tool,底层调用既有删除服务 API。为确保删除操作由用户本人发起,删除服务必须识别用户身份。有两种思路:
- 专门为 MCP 构建面向 AI Agent 的身份体系,由 MCP 服务器将其映射到删除服务使用的统一身份体系。
- 更低成本方式:MCP 客户端与服务器之间不做(或最小)认证,MCP 服务器仅转发凭证给 Tool,由 Tool 自行认证。前述例子中,若操作者身份通过
Authorization
头传递,则 MCP 服务器执行tools/call
时将该头转发给删除服务,后者基于既有身份体系解析身份。这无需构建新身份体系即可让 MCP 客户端执行删除操作。潜在问题在于:在客户端视角,MCP 服务器的资源 URL 与删除服务的资源 URL 可能不同,若不同 URL 使用不同凭证,还需额外对齐。
真正的总结
当前 MCP 授权采用 OAuth,受限于生态成熟度与动态客户端注册的落地难度,只能说是“可用”,离“易用”尚有距离。只有在保持协议安全治理前提下,结合实际降低接入摩擦,MCP 授权机制才能从“可用”走向“可演化、可扩展、可治理”的基础设施。
更多推荐
所有评论(0)