MCP 授权流程介绍

MCP 服务器(提供 AI 模型上下文的一方)需要一种机制来验证客户端(使用模型的一方)是否有权访问其资源。在该协议的设计中,这一机制是一种 基于 OAuth 2.1 的标准授权方案。

核心组件

  1. MCP 服务器 (MCP Server):扮演 资源服务器 (Resource Server) 的角色,保护需要授权才能访问的资源(例如 tools/call 接口)。
  2. MCP 客户端 (MCP Client):需要访问 MCP 服务器资源的应用程序。
  3. 授权服务器 (Authorization Server):负责验证客户端身份并发放访问令牌(Access Token)的独立服务。

授权流程步骤 (Authorization Flow)

整个流程遵循标准的 OAuth 2.1 模式,可以概括为以下几个关键步骤:

  1. 首次请求(无令牌)
    MCP 客户端第一次向 MCP 服务器发起请求时,请求中没有包含访问令牌。
  2. 返回认证挑战(WWW-Authenticate)
    MCP 服务器发现请求没有有效令牌,于是拒绝该请求,并返回 401 Unauthorized
    最关键的是,响应头包含 WWW-Authenticate 字段,该字段告诉客户端到哪里获取 Resource Metadata。
  3. 客户端请求授权

    • MCP 客户端解析 WWW-Authenticate 头,拿到 Resource Metadata 的地址。
    • MCP 客户端请求 Resource Metadata,从中获取授权服务器地址和所需的 scope 等信息。
    • MCP 客户端请求授权服务器的 Discovery Endpoint,获取服务器信息(如注册接口等)。
    • (如果是第一次访问)MCP 客户端向该授权服务器动态注册(Dynamic Client Registration, DCR),得到客户端 ID。
    • 客户端将用户重定向到授权服务器,并带上自己的客户端 ID、请求的权限范围(scope)、资源 URL(resource 参数)等信息,发起授权请求。
  4. 授权服务器进行认证和授权
    授权服务器验证用户身份(例如登录)。用户同意授权后,授权服务器向客户端发放 授权码 (Authorization Code)
  5. 客户端用授权码换取令牌
    客户端拿着授权码,向授权服务器的令牌端点(Token Endpoint)发起请求,以换取 访问令牌 (Access Token)(以及可选刷新令牌)。
  6. 携带令牌再次请求
    客户端成功获取访问令牌后,重新向 MCP 服务器发起之前的请求,并在 Authorization 头中携带该访问令牌(通常是 Bearer <token>)。
  7. 服务器验证令牌并响应
    MCP 服务器收到带令牌的请求后,会与授权服务器通信(或使用本地缓存的公钥)验证令牌的有效性、签名、有效期以及权限范围。验证通过后,服务器处理请求并返回成功响应。

安全注意事项

该规范强调以下关键安全点:

  • 令牌绑定与验证:令牌必须与特定受众(audience,即 MCP 服务器)绑定,防止被滥用。
  • 通信安全:所有通信必须使用 TLS 加密,防止窃听。
  • 防止令牌被盗:推荐使用短生命周期令牌,并遵循 OAuth 2.1 最佳实践。
  • 防止开放重定向:确保重定向过程不被攻击者利用。
  • 解决“困惑的副手”问题 (Confused Deputy Problem):确保客户端不被诱骗执行非预期操作。

总结

简单来说,MCP 的授权流程是一个 标准且安全的 OAuth 2.1 委托授权模式。它没有重新发明轮子,而是复用了业界成熟方案:客户端通过独立可信的授权服务器获取“通行证”(访问令牌),再用该“通行证”访问受保护的 MCP 服务器资源,确保安全性、标准化与互操作性。

MCP 授权机制的现状和问题

是不是觉得上面的内容像是 AI 生成的?其实就是我把 Gemini 2.5 Pro 的回复,补充若干缺失内容之后贴出来。老实说,AI 回复大体上是对的,只是漏了关键的几点,比如:

  1. MCP 服务器不是直接返回授权服务器的地址,而是返回 Resource Metadata 的地址。
  2. MCP 客户端也不是直接就能访问授权服务器,而是先去访问授权服务器的 Discovery Endpoint。
  3. MCP 客户端需要向授权服务器动态注册(DCR),才能拿到自己在这个服务器上的客户端 ID。

可见这套协议有一定复杂度,连 AI 也不能完整答对。

Gemini 的回复只是抛砖引玉的“砖头”,以下才是本文重点——聊聊 MCP 授权机制的一些现状和问题。

现状

所谓“现状”,就是生态整体尚未成熟。毕竟这是一个出现不到三个月的新机制(当前这版授权协议出现于 2025-06-18 版本的 MCP),而且基于 OAuth 的较新功能,上下游支持需要时间。

Cursor 算是一个主流 MCP 客户端实现。然而我基于 2025-08-13 版本的 Cursor 测试 MCP 授权机制,还是发现了两个 bug:

第一个 bug:Cursor 会丢失 Resource Metadata 的地址。复现步骤:

  1. Cursor 请求 MCP 服务器。MCP 服务器返回 401 和 Resource Metadata URL。
  2. Cursor 跟踪该 URL 并发现授权服务器。
  3. 授权服务器返回重定向响应要求登录。Cursor 打开浏览器供用户登录。
  4. 登录后,用户跳转回 Cursor。
  5. 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,现状如下:

问题

在生态尚待完善的同时,MCP 授权机制仍有若干未解决的问题。

首先是当前 MCP 协议和 SDK 中仅实现主流的 Authorization Code Flow。这种 Flow 需要用户交互登录,对当前以 Code Copilot、AI Chat 为主的场景足够。但在 AI Agent 大规模自动运行的未来场景中,缺乏 Machine-to-Machine 授权模式是行不通的。好在 OAuth 已定义多种适用于 M2M 的 Flow,MCP 只需引入即可。

更大的问题在于现行 OAuth 流程依赖客户端动态注册。如果客户端无法在授权服务器上注册,就无法申请令牌。这一机制在 MCP 授权过程中是核心,但现实落地困难,原因有三:

  1. 多数情况下,注册新身份不只是填表,还需绑定邮箱、手机号等,纯自动化 DCR 难以满足合规要求。
  2. 当前只支持 Authorization Code Flow,还能通过用户登录补充注册所需信息(例如登录成功后分配客户端 ID);未来若需支持 M2M,则此“人工回填”变通方式失效。
  3. 动态客户端注册并非 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。为确保删除操作由用户本人发起,删除服务必须识别用户身份。有两种思路:

  1. 专门为 MCP 构建面向 AI Agent 的身份体系,由 MCP 服务器将其映射到删除服务使用的统一身份体系。
  2. 更低成本方式:MCP 客户端与服务器之间不做(或最小)认证,MCP 服务器仅转发凭证给 Tool,由 Tool 自行认证。前述例子中,若操作者身份通过 Authorization 头传递,则 MCP 服务器执行 tools/call 时将该头转发给删除服务,后者基于既有身份体系解析身份。这无需构建新身份体系即可让 MCP 客户端执行删除操作。潜在问题在于:在客户端视角,MCP 服务器的资源 URL 与删除服务的资源 URL 可能不同,若不同 URL 使用不同凭证,还需额外对齐。

真正的总结

当前 MCP 授权采用 OAuth,受限于生态成熟度与动态客户端注册的落地难度,只能说是“可用”,离“易用”尚有距离。只有在保持协议安全治理前提下,结合实际降低接入摩擦,MCP 授权机制才能从“可用”走向“可演化、可扩展、可治理”的基础设施。

Logo

更多推荐