简体中文
  • mcp
  • mcp-auth

MCP 服务器身份认证实现指南:使用最新规范

为 MCP 服务器认证遵循 2025-06-18 规范提供关键实现要点。

Yijun
Yijun
Developer

不要在用户认证上浪费数周时间
使用 Logto 更快地发布安全应用。几分钟内集成用户认证,专注于您的核心产品。
立即开始
Product screenshot

几天前(2025 年 6 月 18 日),MCP(Model Context Protocol,模型上下文协议)团队发布了最新版本的 MCP 规范 (2025-06-18)。本次更新对认证规范做出了关键改动。MCP 服务器今后不再作为 授权服务器 颁发 访问令牌,而是作为 资源服务器 来消费访问令牌并提供资源。

作为 MCP Auth(一个即插即用的 MCP Server 认证库)的维护者之一,我已经在本项目中支持了最新的 MCP 认证规范。结合我的实战经验,本文将手把手带你实现符合最新规范的 MCP 服务器认证功能。

本文将帮助你:

  • 理解新 MCP 认证规范下的 MCP 认证机制如何工作
  • 明确 MCP 认证规范要求下 MCP 服务器作为资源服务器需要实现什么
  • 为你的 MCP 服务器实现合规的认证支持提供实现指引
  • 指出你在实现 MCP 认证规范时容易忽略的问题和安全漏洞

请注意,本文:

  • 假定读者已经具备 JWT(JSON Web Token)基础知识。不会详细介绍 JWT 结构、签名验证等基础概念,具体细节可参考 Auth Wiki - JWT
  • 不深入讲解 MCP 认证规范依赖的各种 RFC,仅提供符合这些 RFC 要求的实现
  • 不涉及 MCP Client 和授权服务器的认证流程和交互细节。这部分通常由支持 MCP 规范的 LLM 客户端和授权服务器厂商实现,MCP 服务器开发者无需也无法干涉。具体可参考 OAuth Client授权服务器
  • 文章中提及的所有访问令牌均假设为 JWT,这是当前市场最广泛的格式。其它类型令牌需根据对应授权服务器厂商文档使用

MCP 认证机制如何运行?

根据最新的 MCP 认证规范,MCP 认证流程如下图所示:

  1. MCP Client 向 MCP Server(如 https://github-tools.com)发起资源请求。由于用户尚未登录,请求头不会携带表示用户身份的 access token。

  2. MCP Server 发现请求头没有令牌,返回 HTTP 401 错误给 MCP Client,并在响应中加上带有 resource_metadata 字段的 WWW-Authenticate 头,提供 MCP Server 资源元数据的 URL。

  3. MCP Client 从 WWW-Authenticate 头里提取 resource_metadata 字段(如 https://github-tools.com/.well-known/oauth-protected-resource),然后据此请求 MCP Server 作为资源服务器暴露出的资源元数据。该元数据包含 authorization_serversscopes_supported 等信息,帮助 MCP Client 理解需要去哪个授权服务器获取什么权限的 access token 才能访问 MCP Server。

4-8. MCP Client 根据资源元数据里的授权服务器元数据地址请求授权服务器相关信息,然后基于此地址发起 OAuth 2.1 的授权流程,流程结束后获得 access token。

  1. MCP Client 将从授权服务器获取的 access token 带上,再次向 MCP Server 发起资源请求。

  2. MCP Server 验证令牌合法后,返回所请求的资源。之后 Client 与 Server 的进一步交互均基于有效的 token 进行认证。

下文将依照此流程,手把手讲解如何落地 MCP 服务器的认证机制。

处理无权访问请求:返回 401 错误与 WWW-Authenticate 头

如上流程所示,当 MCP Client 未携带 access token 向 MCP Server 发起请求时,MCP Server 需要返回一个 HTTP 401 Unauthorized 错误,并在 header 中加上带有资源元数据 URL 的 WWW-Authenticate 头。

根据 MCP 认证规范的错误处理 要求,除了 Client 请求未带 access token 的情况外,MCP Server 收到无效的访问令牌时,也要返回带有 WWW-Authenticate 头的 401 错误。

明白了该何时返回 401 后,如何构建 WWW-Authenticate 响应头呢?

根据 RFC9728 第 5.1 节WWW-Authenticate 头需包含 resource_metadata 参数,指明受保护的资源元数据地址。

其基本格式如下:

其中,Bearer 是认证方案,表示需要携带 Bearer Token 才能访问 OAuth 2.0 受保护的资源(见 MDN 文档)。resource_metadata 后面就是你的 MCP Server 提供资源元数据的完整 URL。

实际代码实现大致如下:

Client 收到这样的 401 响应后,会按照 WWW-Authenticate header 里的 resource_metadata URL 去请求 MCP Server 的资源元数据,再依赖元数据里的信息,向指定授权服务器发起授权请求,获取能访问 MCP Server 的 access token。

现在我们明白了什么时候返回 401 错误,以及需要返回 resource_metadata 地址,但还不知道资源元数据 URL 如何构造,和元数据里面到底需要包含哪些内容,下面会详细说明。

实现资源元数据发现机制

在 MCP 认证流程中,Client 收到 401 后,马上会向 MCP Server 查询资源元数据,因而 MCP Server 作为资源服务器要实现资源元数据发现能力。

确定元数据 endpoint 的 URL 路径

在 OAuth 体系中,我们用 URL 标识“资源指示符”,按 RFC9728 要求,资源元数据应托管于指定的 /.well-known 路径下。

若你的 MCP Server(如 https://github-tools.com)只提供单一服务,元数据 endpoint 应设置为:

如果在同一 host 下同时提供多个 MCP 服务,每个服务应各有独立的元数据 endpoint。例如企业平台 https://api.acme-corp.com 提供:

  • https://api.acme-corp.com/github - GitHub 集成服务
  • https://api.acme-corp.com/slack - Slack 集成服务
  • https://api.acme-corp.com/database - 数据库查询服务

则各自资源元数据 endpoint 应为:

  • https://api.acme-corp.com/.well-known/oauth-protected-resource/github
  • https://api.acme-corp.com/.well-known/oauth-protected-resource/slack
  • https://api.acme-corp.com/.well-known/oauth-protected-resource/database

这种设计的好处是每个服务可以配置不同的权限范围与授权服务器。例如:

  • GitHub 服务用 GitHub 的 OAuth,申请 github:readgithub:write 权限
  • Slack 服务用 Slack 的 OAuth,申请 slack:channels:readslack:messages:write 权限
  • 数据库服务用企业内授权,申请 db:query 权限

归纳起来,资源元数据 endpoint 的 URL 形如:

可按如下方式从资源标识符自动推导 endpoint:

构建资源元数据内容

确定了 endpoint 路径后,还需让该 endpoint 返回符合 RFC9728 规范的 JSON 格式元数据。

实际实现时主要关注 4 个核心字段:

  1. resource:资源指示符,应与 Client 要访问的资源一致
  2. authorization_servers:指定 MCP Client 应向哪些授权服务器申请 access token,按 MCP 认证规范,此字段必填
  3. scopes_supported:本资源服务器支持的所有权限范围列表
  4. bearer_methods_supported:服务器接受 access token 的方式,通常应设置为 ["header"],即 Client 应通过 HTTP Authorization 头传递令牌

结合实例,假设为 https://github-tools.com 配置资源元数据:

此配置告诉 MCP Client:目标资源是 https://github-tools.com,需要向 https://auth.github-tools.com 申请令牌,可选权限有 github:readgithub:writerepo:admin,拿到令牌后应通过 HTTP Authorization 头传递。

对大多数场景,配置上述四个基础字段就足够让 MCP Client 正常工作了。如需更复杂的选项,可参考 RFC9728 完整字段列表。

校验 access token

当 MCP Client 从授权服务器拿到 access token 后,会在请求时带上该凭证访问 MCP Server。

实际落地时,MCP Server 校验 access token 重点关注:

  1. 用 MCP Server 的配置判断 token 合法性,而不是单纯依赖 token 里带的 issuer 信息
  2. 严格校验 token 的 audience 是否是本 MCP 服务器自身,确保 token 的颁发目标正确
  3. 正确处理权限范围校验(scope 校验)

用 MCP Server 配置校验 access token

MCP Server 拿到访问令牌时,由于 token 内自带 issuer 信息,有些开发者会直接用 token 的 issuer 和服务器之间建立校验关系。尤其当 MCP Server 配置多个授权服务器时,资源元数据返回:

这时常见错误做法是:直接根据未验证 token 中的 issuer 字段拉取授权服务器配置,然后对 token 验证。攻击者可伪造恶意授权服务器,为 MCP Server 签发假 access token。如果服务器逻辑直接取 token 里的 issuer 验证,并信任恶意授权服务器,那伪造令牌就会被当作合法令牌认定。

正确做法:

  • 若只配置了单一授权服务器:明确只接受由后端配置的授权服务器签发的 token
  • 配置了多个授权服务器时:先解析未验证 token 的 issuer 字段,只能用后端“白名单”里的授权服务器进行进一步校验,如不存在直接拒绝该 token

示例 jose JWT 校验代码:

校验 token audience

MCP 认证规范 Token Audience Binding and Validation 部分明确要求:Client 向授权服务器申请 access token 时,必须声明请求将用于访问哪个资源服务器,MCP Server 校验 token 时必须严格比对当前 token 的 audience 字段。

这是基于 RFC 8707 Resource Indicators for OAuth 2.0 设计的。

简要流程:

  1. Client 申请令牌时明确指定 resource 参数(如 https://github-tools.com
  2. 授权服务器签发 token 时将 resource 写进 JWT 的 audience(aud)字段
  3. MCP Server 校验令牌时,必须精确比对 aud 字段是否等于自身的资源标识符

https://github-tools.com MCP Server 为例:

audience 校验是防止令牌滥用的关键安全机制。若省略这一环节,攻击者可携带用于别的服务的 access token 试图访问你的服务,若不做校验则会导致权限穿越。

权限范围(scope)校验

某些 MCP Server 还管理内部资源访问权限,不同用户 token 所含 scope 不同。

token 验证通过后,下一步要校验该 token 权限范围是否覆盖了当前操作的必需 scope。例如:

注意:按 MCP 认证规范错误处理规定,若 token 不具备访问当前资源所需 scope,需返回 403 Forbidden 响应。

总结

通过本文介绍,你已能为自己的 MCP Server 实现符合最新规范的认证功能。请牢记关键点:安全校验令牌、正确配置元数据、严格校验 audience。

如果你正在构建 MCP Server,欢迎试用 MCP Auth 库。本文涉及的所有认证功能都已实现,可助你高效集成认证支持。

有任何问题欢迎在 GitHub 讨论,让我们一起推动 MCP 生态发展!