OAuth2.1授权服务器

一个基于Node.js和Express.js实现的OAuth2.1授权服务器示例,支持MCP协议并与AWS Cognito等身份提供商集成。

  • by empires-security
  • JavaScript
  • 本地部署
  • 68 星标
  • 更新于
在 GitHub 查看 empires-security/mcp-oauth2-aws-cognito

使用说明

MCP+OAuth2.1+AWS认知示例

概述

此存储库演示了如何使用OAuth 2.1授权流保护模型上下文协议(MCP)服务器,该授权流完全由Node.js和Express.js实现。虽然此示例使用AWS Cognito作为后备授权服务器,但实现是 提供者不可知 并且可以与任何符合OAuth 2.1的授权服务器一起工作。

根据MCP授权规范(版本2025-11-25),该项目展示了:

  • MCP服务器充当 资源服务器 (RS)具有通用OAuth端点
  • 与提供商无关的OAuth 2.1实现(示例使用AWS Cognito)
  • OAuth 2.1授权代码流与PKCE和RFC 8707资源指示符
  • 受保护资源元数据(PRM)文档发现
  • 完全动态 授权服务器元数据发现
  • 动态客户端注册(DCR)支持
  • 客户端ID元数据文档(CIMD)支持
  • MCP 2025-11-25规范的增强安全功能
  • 三种客户端实现:
    • 具有预配置凭据的静态客户端
    • 具有动态注册功能的自动发现客户端(DCR)
    • 使用客户端ID元数据文档(CIMD)的元数据客户端

供应商不可知设计

此实现遵循OAuth 2.1标准,以确保与任何兼容的授权服务器兼容:

  • MCP 服务器:将标准OAuth元数据端点和代理暴露给支持授权服务器
  • 客户:动态发现授权服务器,无需硬编码特定于提供者的逻辑
  • 令牌验证:使用从授权服务器元数据中发现的JWKS URI和颁发者信息
  • 灵活的后端:虽然以Cognito为例,但可以替换任何OAuth 2.1服务器

了解新的MCP授权规范

新的MCP授权规范在资源服务器和授权服务器之间引入了清晰的分离,使其更容易与现有的身份提供者(如AWS Cognito、Okta、Auth0等)集成。

规范的关键组成部分:

  1. 受保护资源元数据(PRM) 文件

    • MCP服务器在以下位置提供此文档 /.well-known/oauth-protected-resource
    • 包含有关授权服务器、支持的作用域等的信息。
    • 遵循RFC9728(OAuth 2.0受保护资源元数据)
  2. 发现过程

    • 当客户端收到401 Unauthorized响应时,WWW-Authenticate标头包含指向PRM文档的指针
    • 客户端获取PRM文档以发现授权服务器URL
    • 客户端从发现的URL动态获取授权服务器元数据(没有硬编码端点)
  3. OAuth 2.1授权

    • 使用PKCE的授权码流
    • 经过身份验证的请求的承载令牌使用情况
    • 使用发现的JWKS URI和颁发者信息进行动态令牌验证
  4. 客户注册优先级 (第2025-11-25号部长级会议)

    • 预先注册 客户端凭据(如果服务器可用)
    • 客户端ID元数据文档 (如果授权服务器发布广告 client_id_metadata_document_supported: true)
    • 动态客户端注册 (RFC7591回退)
    • 提示用户手动配置(最后手段)
  5. 动态客户端注册(DCR)

    • 允许客户端自动向新的MCP服务器注册
    • 消除了手动客户端注册流程的需要
    • 遵循RFC7591(OAuth 2.0动态客户端注册协议)
  6. 客户端ID元数据文档(CIMD)

此实现展示了如何以与提供者无关的方式应用这些概念。该示例通过API网关端点和Lambda函数使用带有自定义动态客户端注册的AWS Cognito,但核心OAuth流可用于任何兼容的授权服务器。

建筑

Client → MCP Server → Authorization Server (e.g., AWS Cognito)
        (Resource Server)    (OAuth 2.1 Provider)
  1. 客户端发送没有令牌的请求。
  2. MCP服务器返回401 Unauthorized+WWW-Authenticate标头,指向PRM元数据。
  3. 客户端检索PRM,动态发现授权服务器URL。
  4. 客户端获取授权服务器元数据并执行OAuth 2.1授权代码流(使用PKCE)。
  5. 客户端获得访问令牌并重试向MCP服务器的请求。
  6. MCP服务器使用动态发现的JWKS验证令牌,并授予对受保护资源的访问权限。

有关详细概述,请参阅 架构概述.

图表:

动态客户端注册(DCR)

此实现包括对OAuth 2.1动态客户端注册的支持,允许客户端:

  1. 动态发现MCP服务器和授权端点
  2. 在授权服务器上注册自己
  3. 获取OAuth流的凭据

DCR流程的工作原理如下:

  1. 客户端发现MCP服务器的受保护资源元数据
  2. 客户端发现授权服务器(Cognito)
  3. 客户端向API网关中的DCR端点注册
  4. 注册将创建Cognito应用程序客户端并返回凭据
  5. 客户端将这些凭据用于标准OAuth 2.1流

实施说明: AWS Cognito本身不支持OAuth 2.0 DCR(RFC7591)中指定的动态客户端注册。该实施通过使用以下内容弥合了这一差距:

  • API网关端点提供DCR API接口
  • Lambda函数用于以编程方式创建Cognito应用程序客户端
  • DynamoDB用于存储注册数据

这种方法使我们能够保持对MCP规范DCR建议的合规性,同时利用AWS Cognito进行强大的身份验证和授权。

安全说明:此实现使用匿名DCR,无需额外身份验证。对于生产环境,考虑添加:

  • 注册请求的费率限制
  • 客户端身份验证(mTLS,初始访问令牌)
  • 新客户的审批流程
  • 动态注册客户端的有限范围访问

查看我们的 DCR安全建议 以增强注册过程的安全性。

客户端ID元数据文档(CIMD)

MCP授权规范(2025-11-25)引入了客户端ID元数据文档作为推荐的客户端注册方法。CIMD允许客户端使用HTTPS URL作为其 client_id,URL承载一个描述客户端OAuth元数据的JSON文档。

CIMD的工作原理

  1. 客户端在URL处发布元数据文档(例如。, http://localhost:3003/client-metadata.json)
  2. 在OAuth授权期间,客户端使用此URL作为其 client_id
  3. 授权服务器从URL获取元数据文档
  4. 服务器验证文档结构并重定向URI
  5. 客户端继续执行标准OAuth 2.1流程

CIMD元数据文档示例

{
  "client_id": "http://localhost:3003/client-metadata.json",
  "redirect_uris": ["http://localhost:3003/callback"],
  "client_name": "MCP CIMD Demo Client",
  "grant_types": ["authorization_code"],
  "response_types": ["code"],
  "token_endpoint_auth_method": "none"
}

CIMD授权代理

AWS Cognito本身不支持客户端ID元数据文档,就像它本身不支持DCR一样。此实现通过MCP服务器的授权代理透明地桥接CIMD:

  • MCP服务器发布广告 client_id_metadata_document_supported: true 授权服务器元数据
  • MCP服务器覆盖 authorization_endpoint 和 token_endpoint 在元数据中指向自身
  • 当客户端提供基于URL的 client_id:
    1. 代理获取并验证客户端的元数据文档
    2. 通过现有的DCR基础设施透明地创建Cognito应用程序客户端
    3. 使用映射的凭据将请求转发给Cognito
  • 当客户提出标准时 client_id (预注册或DCR):请求将原封不动地传递给Cognito

元数据客户端具有 零自定义代码 对于CIMD,它只是将其元数据URL用作 client_id 使用标准OAuth端点,就像任何符合规范的客户端一样。所有桥接都是在服务器端处理的。

CIMD安全

授权代理包括:

  • SSRF保护(阻止私有IP范围,在生产中强制HTTPS)
  • 严格 client_id 验证(必须与元数据URL完全匹配)
  • 重定向URI验证
  • 响应大小限制(64KB)和获取超时(5s)
  • 内存缓存以防止冗余获取

备注:在开发中, http://localhost URL是允许的。生产部署必须使用HTTPS。

快速开始

先决条件

  • 已安装Node.js 18+
  • AWS测试帐户,可访问:
    • Cognito授权服务器(1个用户池,2个应用客户端)
    • 用于DCR和CIMD桥的API网关/Lambda/DynamoDB(2个资源、2个功能、1个表)
    • 用于部署的CloudFormation(1个堆栈)
  • OAuth 2.1流程的基本知识

设置

  1. 克隆仓库

    git clone https://github.com/empires-security/mcp-oauth2-aws-cognito.git
    cd mcp-oauth2-aws-cognito
    
  2. 为客户端和服务器安装依赖关系

    npm run install:all
    
  3. 部署AWS资源

    npm run deploy
    
  4. 已生成评论 .env 文件位于:

    • src/client/.env
    • src/auto-client/.env
    • src/metadata-client/.env
    • src/mcp-server/.env
    • 与...比较 .env.example 文件
    • 如果需要,手动验证/更新CLIENT_SECRET

运行应用程序

  1. 启动所有服务(服务器+3个客户端)

    npm run dev
    
  2. 访问http://localhost:3000为了测试 预先注册的客户 OAuth流程

  3. 注册新用户

    • 点击“登录”按钮
    • 在Cognito托管的用户界面中选择“注册”
    • 创建新用户帐户
    • 通过输入发送到您电子邮件的确认码来验证您的帐户
    • 成功验证后,您将被重定向回应用程序
  4. 点击“获取MCP数据”按钮,向MCP服务器发出经过身份验证的请求

  5. 访问http://localhost:3002为了测试 DCR流量 (具有动态客户端注册的自动发现客户端)

  6. 访问http://localhost:3003为了测试 CIMD流程 (客户端ID元数据文档客户端)

清理

  1. 清理AWS资源
    npm run cleanup
    

有关详细的设置说明,请参阅 安装指南.

贡献

欢迎投稿!请随时提交拉取请求。

  1. 分叉存储库
  2. 创建功能分支(git checkout -b feature/amazing-feature)
  3. 提交您的更改(git commit -m 'Add some amazing feature')
  4. 推到分支(git push origin feature/amazing-feature)
  5. 打开拉取请求

参考文献

许可证

此项目根据MIT许可证获得许可-有关详细信息,请参阅许可证文件。

作者

  • 帝国安全实验室 🚀