项目介绍
MCP + OAuth2.1 + AWS Cognito 示例
概述
此仓库演示了如何使用 OAuth 2.1 授权流程来保护模型上下文协议(MCP)服务器,该实现完全基于 Node.js 和 Express.js。虽然此示例使用 AWS Cognito 作为后端授权服务器,但实现是供应商无关的,可以与任何符合 OAuth 2.1 的授权服务器一起工作。
基于 MCP 授权规范(版本 2025-06-18),该项目展示了以下内容:
- MCP 服务器作为具有通用 OAuth 端点的资源服务器(RS)
- 供应商无关的 OAuth 2.1 实现(示例中使用 AWS Cognito)
- 带有 PKCE 和 RFC 8707 资源指示符的 OAuth 2.1 授权码流
- 受保护资源元数据(PRM)文档发现
- 完全动态的授权服务器元数据发现
- 动态客户端注册(DCR)支持
- 来自 MCP 2025-06-18 规范的增强安全功能
- 两种客户端实现:
- 配置了预设凭证的静态客户端
- 具有动态注册的自动发现客户端
供应商无关设计
此实现遵循 OAuth 2.1 标准,以确保与任何合规授权服务器的兼容性:
- MCP 服务器:暴露标准 OAuth 元数据端点,并代理到后端授权服务器
- 客户端:动态发现授权服务器,无需硬编码的供应商特定逻辑
- 令牌验证:使用从授权服务器元数据中发现的 JWKS URI 和发行者信息
- 灵活的后端:虽然示例中使用了 Cognito,但任何 OAuth 2.1 服务器都可以替换
理解新的 MCP 授权规范
新的 MCP 授权规范引入了资源服务器和授权服务器之间的清晰分离,使得更容易与现有的身份提供商(如 AWS Cognito、Okta、Auth0 等)集成。
规范的关键组件:
-
受保护资源元数据(PRM)文档
- MCP 服务器在
/.well-known/oauth-protected-resource 提供此文档
- 包含有关授权服务器、支持的作用域等信息
- 遵循 RFC9728(OAuth 2.0 受保护资源元数据)
-
发现过程
- 当客户端收到 401 未授权响应时,WWW-Authenticate 头包含指向 PRM 文档的指针
- 客户端获取 PRM 文档以发现授权服务器 URL
- 客户端从发现的 URL 动态获取授权服务器元数据(没有硬编码的端点)
-
OAuth 2.1 授权
- 带有 PKCE 的授权码流
- 使用承载令牌进行认证请求
- 使用发现的 JWKS URI 和发行者信息进行动态令牌验证
-
动态客户端注册(DCR)
- 允许客户端自动注册到新的 MCP 服务器
- 消除了手动客户端注册过程的需求
- 使新服务的无缝发现和连接成为可能
- MCP 规范强烈建议实现 DCR,因为“客户端事先不知道 MCP 服务器的集合”
- 提供了一种标准化的方式来获取 OAuth 客户端凭据
- 遵循 RFC7591(OAuth 2.0 动态客户端注册协议)
此实现展示了如何以供应商无关的方式应用这些概念。示例使用 AWS Cognito 并通过 API Gateway 端点和 Lambda 函数进行自定义动态客户端注册,但核心 OAuth 流程适用于任何合规授权服务器。
架构
客户端 → MCP 服务器 → 授权服务器(例如,AWS Cognito)
(资源服务器) (OAuth 2.1 提供商)
- 客户端发送无令牌的请求。
- MCP 服务器响应 401 未授权 + WWW-Authenticate 头指向 PRM 元数据。
- 客户端检索 PRM,动态发现授权服务器 URL。
- 客户端获取授权服务器元数据并执行 OAuth 2.1 授权码流(带有 PKCE)。
- 客户端获得访问令牌并重试对 MCP 服务器的请求。
- MCP 服务器使用动态发现的 JWKS 验证令牌,并授予对受保护资源的访问权限。
详细概述,请参阅架构概述。
图表:
动态客户端注册(DCR)
此实现包括对 OAuth 2.1 动态客户端注册的支持,允许客户端:
- 动态发现 MCP 服务器和授权端点
- 注册自己到授权服务器
- 获取用于 OAuth 流程的凭据
DCR 流程如下:
- 客户端发现 MCP 服务器的受保护资源元数据
- 客户端发现授权服务器(Cognito)
- 客户端在 API Gateway 中注册 DCR 端点
- 注册创建一个 Cognito 应用客户端并返回凭据
- 客户端使用这些凭据进行标准的 OAuth 2.1 流程
实现说明:AWS Cognito 不原生支持 OAuth 2.0 DCR(RFC7591)中规定的动态客户端注册。此实现通过以下方式弥补这一差距:
- 使用 API Gateway 端点提供 DCR API 接口
- 使用 Lambda 函数编程地创建 Cognito 应用客户端
- 使用 DynamoDB 存储注册数据
这种方法允许我们遵守 MCP 规范的 DCR 建议,同时利用 AWS Cognito 进行强大的认证和授权。
安全说明:此实现使用匿名 DCR 而不附加额外的身份验证。对于生产环境,考虑添加:
- 对注册请求进行速率限制
- 客户端身份验证(mTLS,初始访问令牌)
- 新客户端的审批工作流
- 对动态注册的客户端限制作用域访问
查看我们的DCR 安全建议,以增强注册过程的安全性。
快速开始
先决条件
- 已安装 Node.js
- 具有以下访问权限的 AWS 测试账户:
- Cognito 用于授权服务器(1个用户池,2个应用客户端)
- API Gateway / Lambda / DynamoDB 用于 DCR(2个资源,2个函数,1个表)
- CloudFormation 用于部署(1个堆栈)
- 基本了解 OAuth 2.1 流程
设置
-
克隆仓库
git clone https://github.com/empires-security/mcp-oauth2-aws-cognito.git
cd mcp-oauth2-aws-cognito
-
安装客户端和服务器依赖项
npm run install:all
-
部署 AWS 资源
npm run deploy
-
查看生成的 .env 文件:
src/client/.env
src/auto-client/.env
src/mcp-server/.env
- 与
.env.example 文件比较
- 如需手动验证/更新 CLIENT_SECRET
运行应用程序
-
启动客户端和服务器
npm run dev
-
访问 http://localhost:3000 测试 OAuth 流程
-
注册新用户
- 单击“登录”按钮
- 在 Cognito 主机 UI 中选择“注册”
- 创建一个新的用户帐户
- 通过输入发送到您电子邮件的确认代码来验证您的帐户
- 成功验证后,您将被重定向回应用程序
-
单击“获取 MCP 数据”按钮,向 MCP 服务器发出认证请求
-
访问 http://localhost:3002 测试 DCR 流程,自动发现客户端具有动态客户端注册。
清理
- 清理 AWS 资源
npm run cleanup
详细设置说明,请参阅设置指南。
贡献
欢迎贡献!请随时提交拉取请求。
- 分叉仓库
- 创建您的功能分支 (
git checkout -b feature/amazing-feature)
- 提交更改 (
git commit -m '添加一些惊人的功能')
- 推送到分支 (
git push origin feature/amazing-feature)
- 打开拉取请求
参考资料
许可证
本项目根据 MIT 许可证发布 - 详情见 LICENSE 文件。
作者