客户端ID元数据文档:MCP未来身份验证架构的革命

本文深入探讨了Model Context Protocol生态系统中身份验证的演进。传统的动态客户端注册机制因其有状态、复杂和扩展性问题而不再适用。新兴的客户端ID元数据文档作为无状态的替代方案,通过基于域的信任模型和简化流程,解决了服务器无限数据库增长、客户端冒充等安全与扩展性挑战,并支持公共与机密客户端的不同验证方式,为构建大规模、开放且安全的系统指明了方向。

客户端ID元数据文档是MCP客户端注册的未来

在将Model Context Protocol客户端连接到新服务器时,会遇到一个常见问题——“注册墙”。服务器如何信任一个从未见过的应用?如何获取其名称和徽标以显示在同意屏幕上?对于MCP这样的开放生态系统,任何客户端都可以连接到任何服务器,这是一个关键挑战。

传统的OAuth解决方案——动态客户端注册,是有状态的、复杂的,并且会产生大量的操作开销。它并不完全适合这种模型。社区现在正在转向一个更简单、更安全的默认方案:客户端ID元数据文档。这种新方法在SEP-991中提出,基于一份新的IETF草案,是一种无状态的替代方案,更适合MCP。

什么是动态客户端注册?

传统的OAuth解决方案——动态客户端注册确实有效,但社区已得出结论,它并不完全适合像MCP这样的大规模开放系统。

可以把DCR想象成一个拥有非常严格保安的办公楼。每个进入的人(一个客户端实例)都必须到登记台,填写一份包含其信息(元数据)的长表格,然后等待秘书(授权服务器)归档。秘书然后将此表格归档到一个巨大的实体文件柜中,并给这个人一张新的、唯一的身份证。

这个系统在规模扩大时会崩溃。想象一下如果有一百万人出现。秘书会不堪重负,文件柜(数据库)会溢出。更糟糕的是,系统将每次访问都视为一个新的人。如果同一个人(客户端实例)穿着不同的外套(在新设备上运行)出现,他们必须填写一份新表格并获得一张新的身份证。如果来自同一家公司(同一个应用)的10,000人访问,你的文件柜现在有10,000份表格需要管理。这就是“无限数据库增长”问题。

它也是一个安全风险。“登记台”(/register端点)对所有人开放,允许攻击者通过数百万份垃圾表格进行DDoS攻击。他们还可以在表格上写一个假名字(如“官方编码应用”)来欺骗你的用户。最后,服务器必须永远管理这个庞大的、不断增长的文件柜,而客户端必须为它访问的每个办公楼持有不同的身份证。

什么是客户端ID元数据文档?

社区正在转向一个更简单、更现代的默认方案:客户端ID元数据文档。这种新方法正在被添加到MCP中,并基于一份新的IETF草案。

与文件柜不同,CIMD的工作方式类似于保安检查驾驶执照。客户端实例(这个人)只需出示其client_id(其执照),这只是一个安全的HTTPS URL。授权服务器(保安)查看该URL,然后访问它(例如,https://app.example.com/oauth.json)以“读取”执照。

这是一种只读的“按需获取”模型。CIMD只是一个简单的JSON文件,由应用程序在其自己的域上托管。该文件的URL就是client_id

流程很简单:

  1. 客户端托管元数据:客户端应用程序(例如,“代码代理”)在其自己的可验证域上托管一个简单的静态JSON文件。此URL是其全局的、永久的client_id
  2. URL作为身份标识:客户端在授权请求中发送此URL作为client_id
  3. 服务器端验证:MCP服务器收到此client_id。如果服务器支持CIMD,它会执行一个HTTP GET请求到该URL以获取JSON。然后服务器进行验证。它会检查JSON结构、必需字段,并且(最重要的)确保文件内部的client_id属性与获取它的URL完全匹配。
  4. 安全同意和访问:如果验证成功,服务器会显示一个包含已验证的client_namelogo_uri的同意屏幕。然后服务器将此元数据缓存一段时间(例如,24小时)。这意味着对于来自该客户端的后续请求,它不需要再次获取。

这种方法既支持公共客户端,也支持机密客户端。MCP提案为公共客户端提供了明确的指导,而IETF草案则使机密客户端无需共享密钥即可进行身份验证。

  • 公共客户端:这些应用无法保密。它们在元数据中设置"token_endpoint_auth_method": "none",并依赖PKCE来确保安全。
  • 机密客户端:这些应用可以保护私钥。它们使用"token_endpoint_auth_method": "private_key_jwt",并提供jwks_uri来验证其身份。

CIMD如何阻止客户端冒充

关键问题是:什么能阻止位于falseurl.com的网络钓鱼者在登录时直接使用https://app.example.com/oauth.json作为其client_id

答案是redirect_uri验证。

网络钓鱼应用发送授权请求。它使用合法应用的client_id,但包含其自己的恶意redirect_uri

服务器收到此请求。它从client_id URL获取元数据文件。

服务器打开这个合法的JSON文件,查看其redirect_uris列表。

1
2
3
4
5
6
7
{
  "client_id": "https://app.example.com/oauth.json",
  "client_name": "Example MCP Client",
  "redirect_uris": [
    "https://app.example.com/callback"
  ]
}

服务器将网络钓鱼者请求的URI与文件中的列表进行比较。

服务器看到https://falseurl.com/callback不在允许的URI列表中。

服务器中止请求。网络钓鱼者无法接收授权码,攻击失败。

此检查确保只有控制元数据文件中列出的域的应用才能接收用户的凭据。

CIMD如何支持机密客户端

使用DCR时,机密客户端从服务器获取一个client_secret。使用CIMD时,客户端使用自己的私钥来证明其身份。它通过在元数据文件中包含诸如token_endpoint_auth_methodjwks_uri等属性来告诉服务器如何检查其身份。当客户端需要进行身份验证(例如,在令牌端点)时,它用其私钥签署一个JWT。然后服务器从jwks_uri获取公钥来验证签名。这使得服务器可以在没有预注册密钥的情况下信任客户端。

以下是一个使用JWT进行身份验证的机密客户端的简单示例:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
{
  "client_id": "https://app.example.com/oauth/client-metadata.json",
  "client_name": "Example MCP Client",
  "client_uri": "https://app.example.com",
  "logo_uri": "https://app.example.com/logo.png",
  "redirect_uris": [
    "http://localhost:3000/callback"
  ],
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "private_key_jwt",
  "jwks_uri": "https://app.example.com/oauth/jwks.json"
}

CIMD如何解决DCR在MCP中的问题

这种“驾驶执照”模型解决了DCR的主要问题。“登记台”消失了,这消除了注册泛滥的攻击向量。URL是应用程序的单一标识符,而不是每个实例的标识符,这解决了数据库扩展问题。信任现在基于域,这意味着位于falseurl.com的网络钓鱼者无法出示app.example.com的有效“执照”。它也简单得多,因为服务器不再需要客户端数据库,并且有效期由HTTP缓存处理。

CIMD的安全风险有哪些?

CIMD是一种权衡,而非神奇的解决方案。它消除了“文件柜”风险,但开启了一个新的风险:服务器端请求伪造。授权服务器现在必须从一个陌生人那里获取URL。恶意应用可能提供一个指向内部服务的URL,如https://169.254.169.254/https://localhost:8080。为防止此风险,必须加固获取器。阻止内部和回环IP范围,使用积极的超时设置,并限制响应大小(例如,5kb)以避免资源耗尽攻击。

此模型还有两个薄弱点:

  1. 本地主机问题:如果应用运行在https://localhost:1234上,服务器无法确定哪个应用正在监听该端口。
  2. “未验证域”问题:CIMD只证明应用拥有my-shady-app.com,并不证明该应用是可信的。IETF草案建议服务器可以建立自己的信任策略,例如对新或未知域显示额外警告。

MCP身份和安全的未来

DCR是一个有用的标准,但并不完全适合MCP这个庞大的、联邦化的世界。CIMD是一个巨大的改进。

目前对MCP的提议是将CIMD设为默认值,而将DCR作为特定情况下的可选方案。

CIMD的局限性是真实存在的。社区已经在讨论下一步:在这个模型中添加软件声明。软件声明本身并不能解决本地主机问题,因为网络钓鱼者可以复制它。它的力量来自于信任模型。服务器必须被配置为信任该声明的签名者。这可以是应用商店、操作系统或受信任的供应商注册表。

当与平台级证明结合时,此模型允许客户端证明它是什么,而不仅仅是在哪个端口上。这创建了一个更难伪造的可验证信任链。

身份需要是联邦式的和可互操作的。通过支持像CIMD这样的提案,并探索像软件声明这样的新解决方案,我们可以构建一个既具有扩展性又安全的网络。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计