Token导航 LogoToken导航TokenDH.com
MCP Dynamic Auth Example logo
安全风控stdio官方级别未说明来源级核验

MCP Dynamic Auth Example

MCP Server

一个基于AWS Cognito的OAuth 2.0授权服务器,为MCP应用提供安全认证和授权服务。

工具数

0

提示词数

0

GitHub Stars

0

资源数

0
PythonClaude安全Claude DesktopClaudeCursor

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

作者 / 组织

BradWebb101

提供方

BradWebb101

最后核验

2026/5/17 20:20

快速接入

先看主来源和安装命令,再打开仓库或文档;下面只保留这个条目的关键接入事实。

命令预览

pip install starlette uvicorn boto3 pyjwt requests

详细介绍

带有AWS Cognito集成的MCP OAuth服务器

这个项目实现了一个OAuth 2.0授权服务器,该服务器作为MCP(模型上下文协议)客户端和AWS Cognito之间的代理,为MCP应用程序提供安全的身份验证和授权服务。

注: 本仓库中的Flask实现是基于 AWS关于部署模型上下文协议服务器的指南

目录

概述

这个MCP OAuth服务器提供了一个符合标准的OAuth 2.0实现,其特点为:

  • 起着……的作用 授权服务器代理 在MCP客户端和AWS Cognito之间
  • 实施(方案/措施等) 动态客户端注册 (RFC 7591)
  • 支持 授权码流程 使用PKCE(RFC 7636)
  • 提供 令牌刷新 能力;才能;功能
  • 用途 DynamoDB(注:DynamoDB是亚马逊提供的一项完全托管的NoSQL数据库服务,这里直接保留原名,不进行翻译) 用于会话和令牌管理
  • 遵循;接着 RFC 8414 用于OAuth服务器元数据发现

为何选择这种架构?

这个代理层提供的是,让MCP客户端无需直接与Cognito集成,而是通过:

  1. 抽象客户无需了解Cognito的特定知识,即可通过标准的OAuth接口进行交互
  2. 灵活性在不更改客户端实现的情况下切换身份提供商
  3. 安全额外的验证和PKCE(Proof Key for Code Exchange,代码交换的证明密钥)强制执行
  4. 控制自定义作用域、速率限制和审计功能
  5. MCP特异性特征可以添加MCP特定的声明或功能

建筑

┌─────────────┐         ┌─────────────────┐         ┌──────────────┐
│             │         │                 │         │              │
│ MCP Client  │ ◄─────► │  MCP OAuth      │ ◄─────► │   AWS        │
│ (e.g.,      │         │  Server         │         │   Cognito    │
│  Cursor)    │         │  (This Project) │         │   (IdP)      │
│             │         │                 │         │              │
└─────────────┘         └─────────────────┘         └──────────────┘
                               │
                               ▼
                        ┌─────────────┐
                        │  DynamoDB   │
                        │  (Sessions  │
                        │  & Tokens)  │
                        └─────────────┘

关键组件:

  • MCP 客户端任何需要认证的应用程序(例如,Cursor IDE、Claude Desktop)
  • MCP OAuth 服务器这个应用程序 - 处理OAuth流程并管理会话
  • AWS Cognito身份提供者 - 验证用户身份并颁发令牌
  • DynamoDB(亚马逊的分布式NoSQL数据库服务)客户端注册、会话和令牌映射的持久化存储

OAuth流程详解

让我们使用AWS Cognito作为身份提供商,逐步了解完整的OAuth流程。此示例展示了用户如何使用MCP客户端进行身份验证。

第一阶段:发现与注册

步骤1:元数据发现(可选)

客户端首先发现服务器的功能:

GET /.well-known/oauth-authorization-server
Host: mcp-server.example.com

回应:

{
  "issuer": "https://mcp-server.example.com",
  "authorization_endpoint": "https://mcp-server.example.com/authorize",
  "token_endpoint": "https://mcp-server.example.com/token",
  "registration_endpoint": "https://mcp-server.example.com/register",
  "jwks_uri": "https://cognito-idp.us-west-2.amazonaws.com/us-west-2_xxxxx/.well-known/jwks.json",
  "response_types_supported": ["code"],
  "grant_types_supported": ["authorization_code", "refresh_token"],
  "scopes_supported": ["openid", "email", "profile", "mcp-server/read", "mcp-server/write"],
  "code_challenge_methods_supported": ["S256"]
}

这告诉客户端应将授权请求发送到何处以及支持哪些功能。

步骤2:动态客户端注册

如果客户端未预先注册,则会自动进行注册:

POST /register
Content-Type: application/json

{
  "client_name": "My MCP Client",
  "redirect_uris": ["cursor://callback", "http://localhost:3000/callback"]
}

服务器操作:

  1. 验证重定向URI(必须为HTTPS、localhost或自定义协议,如 cursor://)
  2. 生成一个唯一的 client_id (通用唯一标识符)
  3. 在DynamoDB中存储客户端信息
  4. 返回客户端凭据

回答:

{
  "client_id": "550e8400-e29b-41d4-a716-446655440000",
  "client_id_issued_at": 1729526400,
  "client_secret_expires_at": 0,
  "client_name": "My MCP Client",
  "redirect_uris": ["cursor://callback", "http://localhost:3000/callback"]
}

第二阶段:授权流程(OAuth 舞蹈)

步骤3:授权请求

客户端通过将用户重定向到授权端点来启动OAuth流程:

GET /authorize?
  client_id=550e8400-e29b-41d4-a716-446655440000
  &redirect_uri=cursor://callback
  &response_type=code
  &state=client_state_xyz123
  &code_challenge=E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM
  &code_challenge_method=S256
  &scope=openid%20email%20profile

服务器操作:

  1. 验证请求

- 核对以确认 client_id 存在于DynamoDB中 - 验证 redirect_uri 匹配已注册的URI(统一资源标识符) - 确保 response_type 是“代码”

  1. 创建一个会话
   sessionId = "7f8e9d0c-1234-5678-90ab-cdef12345678"

   // Store in DynamoDB
   {
     client_id: "550e8400-e29b-41d4-a716-446655440000",
     redirect_uri: "cursor://callback",  // Client's callback
     state: "client_state_xyz123",        // Client's CSRF token
     code_challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
     code_challenge_method: "S256",
     scope: "openid email profile",
     created_at: 1729526400
   }
  1. 重定向到 Cognito
   302 Redirect to:
   https://my-app.auth.us-west-2.amazoncognito.com/oauth2/authorize?
     client_id=YOUR_COGNITO_CLIENT_ID
     &response_type=code
     &redirect_uri=https://mcp-server.example.com/callback  ← Server's callback!
     &state=7f8e9d0c-1234-5678-90ab-cdef12345678            ← Session ID!
     &scope=openid%20email%20profile

关键见解发送到Cognito的重定向URI是 MCP服务器的 /callback 终端节点,而不是客户端的重定向URI。会话ID被用作Cognito的状态参数。

步骤4:在Cognito进行用户身份验证

User → Cognito Hosted UI
  ↓
Enters username/password
  ↓
Completes MFA (if enabled)
  ↓
Grants consent
  ↓
Cognito validates credentials

这一步完全在Cognito中进行。用户看到的是Cognito的登录页面,并在那里进行身份验证。

步骤5:Cognito回调

成功认证后,Cognito 会重定向回 MCP 服务器:

GET /callback?
  code=COGNITO_AUTH_CODE_abc123def456
  &state=7f8e9d0c-1234-5678-90ab-cdef12345678
Host: mcp-server.example.com

服务器操作:

  1. 检索会话 使用状态参数(会话ID):
   session = await tokenStore.getSession("7f8e9d0c-1234-5678-90ab-cdef12345678")

   // Returns:
   {
     client_id: "550e8400-e29b-41d4-a716-446655440000",
     redirect_uri: "cursor://callback",     // Original client callback
     state: "client_state_xyz123",          // Original client state
     code_challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
     scope: "openid email profile"
   }
  1. 用Cognito代码兑换代币
   POST /oauth2/token
   Host: my-app.auth.us-west-2.amazoncognito.com
   Authorization: Basic base64(CLIENT_ID:CLIENT_SECRET)
   Content-Type: application/x-www-form-urlencoded

   grant_type=authorization_code
   &code=COGNITO_AUTH_CODE_abc123def456
   &redirect_uri=https://mcp-server.example.com/callback  ← Must match!

Cognito 响应:

   {
     "access_token": "eyJraWQiOiJ...",
     "refresh_token": "eyJjdHkiOiJ...",
     "id_token": "eyJraWQiOiJ...",
     "token_type": "Bearer",
     "expires_in": 3600
   }
  1. 生成MCP授权码
   mcpAuthCode = "mcp-789xyz-456abc-123def"
  1. 在DynamoDB中存储令牌映射
   {
     cognito_access_token: "eyJraWQiOiJ...",
     cognito_refresh_token: "eyJjdHkiOiJ...",
     cognito_id_token: "eyJraWQiOiJ...",
     client_id: "550e8400-e29b-41d4-a716-446655440000",
     scope: "openid email profile",
     code_challenge: "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM",
     code_challenge_method: "S256",
     expires_in: 3600,
     created_at: 1729526400
   }
  1. 重定向到客户端:
   302 Redirect to:
   cursor://callback?
     code=mcp-789xyz-456abc-123def      ← MCP code, not Cognito's!
     &state=client_state_xyz123         ← Original client state

关键见解Cognito授权码会立即被交换为令牌,且不会离开服务器。客户端会收到一个 新的MCP授权码 这映射到存储在DynamoDB中的Cognito令牌。

步骤6:代币兑换

客户端现在将MCP授权码兑换成令牌:

POST /token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=mcp-789xyz-456abc-123def
&client_id=550e8400-e29b-41d4-a716-446655440000
&redirect_uri=cursor://callback
&code_verifier=dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk  ← PKCE

服务器操作:

  1. 检索令牌映射 使用MCP代码从DynamoDB中获取
  1. 验证客户端 与启动流的那一个相匹配
  1. 验证PKCE(Proof Key for Code Exchange,用于代码交换的证明密钥):
   // Calculate SHA256 of code_verifier
   calculated = SHA256("dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk")

   // Compare with stored code_challenge
   if (calculated === "E9Melhoa2OwvFrEMTJguCHaoeK1t8URWbuGJSstw-cM") {
     // Valid!
   }
  1. 返回Cognito令牌 致客户:
   {
     "access_token": "eyJraWQiOiJ...",
     "refresh_token": "eyJjdHkiOiJ...",
     "id_token": "eyJraWQiOiJ...",
     "token_type": "Bearer",
     "expires_in": 3600,
     "scope": "openid email profile"
   }
  1. 删除授权码 来自 DynamoDB(一次性使用)

关键见解MCP服务器充当透明代理。客户端接收来自Cognito的实际令牌,但PKCE(Proof Key for Code Exchange)验证是在MCP服务器层面进行的。

步骤7:令牌刷新(可选)

当访问令牌过期时,客户端可以刷新它:

POST /token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=eyJjdHkiOiJ...
&client_id=550e8400-e29b-41d4-a716-446655440000

服务器操作:

  1. 将刷新请求转发给Cognito
   POST /oauth2/token
   Host: my-app.auth.us-west-2.amazoncognito.com

   grant_type=refresh_token
   &client_id=YOUR_COGNITO_CLIENT_ID
   &refresh_token=eyJjdHkiOiJ...
  1. 返回刷新后的令牌 从Cognito到客户端

视觉流程概要

┌──────────┐                    ┌────────────┐                   ┌─────────┐
│  Client  │                    │ MCP Server │                   │ Cognito │
└────┬─────┘                    └─────┬──────┘                   └────┬────┘
     │                                │                                │
     │ 1. GET /authorize              │                                │
     │ (client_id, redirect_uri,      │                                │
     │  code_challenge)               │                                │
     ├───────────────────────────────►│                                │
     │                                │                                │
     │                                │ 2. Store session in DynamoDB   │
     │                                │    (client details, challenge) │
     │                                │                                │
     │                                │ 3. Redirect to Cognito         │
     │                                │    (server callback, sessionID)│
     │                                ├───────────────────────────────►│
     │                                │                                │
     │                                │          4. User authenticates │
     │                                │             at Cognito         │
     │                                │                                │
     │                                │ 5. Callback with Cognito code  │
     │                                │◄───────────────────────────────┤
     │                                │                                │
     │                                │ 6. Get session from DynamoDB   │
     │                                │                                │
     │                                │ 7. Exchange code for tokens    │
     │                                ├───────────────────────────────►│
     │                                │◄───────────────────────────────┤
     │                                │   (access, refresh, id tokens) │
     │                                │                                │
     │                                │ 8. Generate MCP code           │
     │                                │    Store token mapping         │
     │                                │                                │
     │ 9. Redirect with MCP code      │                                │
     │◄───────────────────────────────┤                                │
     │                                │                                │
     │ 10. POST /token                │                                │
     │     (MCP code, code_verifier)  │                                │
     ├───────────────────────────────►│                                │
     │                                │                                │
     │                                │ 11. Validate PKCE              │
     │                                │     Get tokens from DynamoDB   │
     │                                │                                │
     │ 12. Return Cognito tokens      │                                │
     │◄───────────────────────────────┤                                │
     │                                │                                │

设置与配置

先决条件

  • Python 3.8+ 或 Node.js 18+
  • 带有以下内容的AWS账户:

- 配置了Cognito用户池 - DynamoDB 表 - DynamoDB、SSM、Secrets Manager 的 IAM 权限

  • 环境变量(见下文)

环境变量

# Cognito Configuration
COGNITO_DOMAIN=your-app-name          # e.g., "my-app"
COGNITO_CLIENT_ID=abc123...           # Cognito App Client ID
COGNITO_USER_POOL_ID=us-west-2_xxxxx  # Cognito User Pool ID
COGNITO_CLIENT_SECRET=secret123...     # Cognito App Client Secret
AWS_REGION=us-west-2                   # AWS Region

# DynamoDB
TOKEN_TABLE_NAME=mcp-oauth-tokens      # DynamoDB table name

# Server Configuration
MCP_SERVER_BASE_URL=https://mcp-server.example.com  # Public server URL
PORT=3000                                            # Server port

# Security (Python version)
JWT_SECRET_KEY=your-secret-key-here    # For signing JWT tokens

# Optional - SSM Parameter Store
COGNITO_SECRET_PARAM_NAME=/mcp/cognito/secret  # SSM parameter path
MCP_SERVER_BASE_URL_PARAMETER_NAME=/mcp/base-url

DynamoDB 表架构

该表使用了一个由分区键(PK)和排序键(SK)组成的复合主键:

Table: mcp-oauth-tokens
Primary Key: 
  - PK (String) - Partition key
  - SK (String) - Sort key
Attributes:
  - data (Map) - Contains the actual data
  - created_at (Number) - Unix timestamp
  - expiration (Number) - TTL for automatic cleanup

关键模式:

  • 客户: PK=CLIENT#SK=CLIENT
  • 会话: PK=SESSION#SK=SESSION
  • 代币: PK=TOKEN#SK=TOKEN
  • 刷新: PK=REFRESH#SK=REFRESH

安装

python

pip install starlette uvicorn boto3 pyjwt requests
python flask.py

TypeScript:

npm install
npm run dev

安全特性

1. PKCE(用于代码交换的证明密钥)

防止授权码拦截攻击:

  1. 客户端生成随机数 code_verifier
  2. 客户端计算 code_challenge = SHA256(code_verifier)
  3. 收到挑战 /authorize存储在会话中
  4. 验证器已发送 /token服务器验证匹配

2. 状态参数(CSRF保护)

防止跨站请求伪造:

  1. 客户端生成随机状态
  2. 服务器在会话中存储
  3. 服务器将信息回传给客户端
  4. 客户端验证匹配

3. 会话绑定

将授权请求链接到回调:

  1. 服务器生成唯一的会话ID
  2. 存储所有请求参数
  3. 用作Cognito状态参数
  4. 检索以获取原始客户详细信息

4. 授权码隔离

确保Cognito令牌安全:

  1. Cognito 代码从未到达客户端
  2. 立即兑换成代币
  3. 新生成的MCP代码
  4. 服务器端存储的令牌
  5. 一次性使用强制措施

5. 令牌映射安全

  • 授权码的较短生存时间(TTL)(10分钟)
  • 一次性代码(交换后删除)
  • 在代币兑换时进行客户验证
  • 需要进行PKCE验证

API 端点

GET /.well-known/oauth-authorization-server

OAuth 2.0 授权服务器元数据(RFC 8414)

回答: 具备服务器功能的JSON

POST /register

动态客户端注册(RFC 7591)

请求:

{
  "client_name": "My App",
  "redirect_uris": ["https://example.com/callback"]
}

回答:

{
  "client_id": "...",
  "client_id_issued_at": 1234567890,
  ...
}

GET /authorize

OAuth 2.0 授权端点

参数:

  • client_id (必需的)
  • redirect_uri (必填)
  • response_type (必填,必须为“代码”)
  • state (推荐)
  • code_challenge (PKCE 所需)
  • code_challenge_method (可选,默认值为“S256”)
  • scope (可选)

回答: 302重定向到Cognito

GET /callback

处理Cognito回调(内部端点)

参数:

  • code - 来自Cognito的授权码
  • state - 会话ID

回答: 将302重定向到客户端,并附带MCP代码

POST /token

OAuth 2.0 令牌端点

授权类型:

  • authorization_code
  • refresh_token

参数(授权码):

  • grant_type=authorization_code
  • code (必填)
  • client_id (必需)
  • redirect_uri (必填)
  • code_verifier (如使用 PKCE 则为必填项)

参数(刷新令牌):

  • grant_type=refresh_token
  • refresh_token (必需)
  • client_id (必填)

回应:

{
  "access_token": "...",
  "refresh_token": "...",
  "id_token": "...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "openid email profile"
}

数据存储

(临时)会议

目的: 将授权请求链接到回调函数 TTL:(此处“TTL”通常可翻译为“生存时间”或根据上下文具体含义翻译,但在此直接保留原英文缩写,若需具体翻译则需更多上下文) 24小时 包含: 客户端详情、PKCE(Proof Key for Code Exchange)挑战、状态

代币映射(临时)

目的: 将MCP代码映射到Cognito令牌 TTL:(在计算机网络中,TTL通常代表“Time To Live”,即生存时间) 10分钟 包含: Cognito令牌、客户端ID、PKCE挑战

客户端注册(持久性)

目的: 存储注册的客户端信息 TTL:(在计算机网络中)生存时间(Time To Live) 无(永久保存,直至删除) 包含: 客户端元数据,重定向URI

刷新令牌(长期有效)

目的: 存储刷新令牌映射 TTL:(这里“TTL”可能是一个缩写或特定术语,根据上下文可能有不同的翻译,但一般可译为)生存时间(Time To Live) 30天 包含: 令牌数据、客户端ID、作用域

故障排除

常见问题

1. 无效的redirect_uri

  • 在客户端注册时确保重定向URI已注册
  • URI 必须完全匹配(包括方案、主机、端口、路径)

2. 无效状态

  • 会话可能已过期(有效期24小时)
  • 检查DynamoDB中的会话数据

3. PKCE验证失败

  • 确保 code_verifier 与 code_challenge 匹配
  • 检查 code_challenge_method 是否为 "S256"

4. Cognito令牌交换失败

  • 验证COGNITO_CLIENT_SECRET是否正确
  • 检查回调URL是否与Cognito配置匹配
  • 确保Cognito应用程序客户端设置正确

许可证

麻省理工学院(MIT)

做出贡献

欢迎贡献!请提交问题或拉取请求。

______________________________________________________________________

注: 这是一个参考实现。对于生产环境使用,请考虑:

  • 速率限制
  • 全面的日志记录和监控
  • 令牌撤销端点
  • 内省端点
  • 额外的安全头部信息
  • 负载均衡和高可用性
  • 秘密轮换
  • 全面的错误处理

目录标签

目录标签

PythonClaude安全OAuth2.0本地部署AWSCognito认证授权动态客户端注册PKCE

支持客户端

Claude DesktopClaudeCursor

接入字段

传输方式(transport,传输协议)

stdio

鉴权方式(authType,认证方式)

oauth

工具数量(toolCount,工具数)

0

资源数量(resourceCount,资源数)

0

提示词数量(promptCount,提示词数)

0

权限和风险

stdiooauth部署方式未说明

接入前请确认传输方式、认证方式和部署位置,并根据实际工具能力限制访问范围。

安装前确认

不要直接授予不必要的文件、网络或账号权限;先核对安装命令和配置内容。

来源信息

继续浏览同类 MCP