FastMCP Keycloak OAuth代理演示
FastMCP服务器示例演示 OAuth代理模式 用于使用Keycloak进行身份验证,Keycloak是一个不支持动态客户端注册(DCR)的传统OAuth提供程序。
为什么选择OAuth代理?
MCP客户端希望使用动态客户端注册(DCR)-他们希望自动注册并动态获取凭据。然而,Keycloak(与GitHub、Google和Azure等大多数传统OAuth提供商一样)需要通过管理控制台手动注册应用程序。
这 OAuth代理 通过以下方式弥合这一差距:
- 向MCP客户端展示符合DCR的接口
- 在幕后使用预先注册的Keycloak凭据
- 处理动态客户端重定向URI的回调转发
- 发行FastMCP JWT令牌,而不是直接转发上游令牌
这保持了适当的OAuth 2.0安全边界,同时提供了无缝的MCP客户端集成。
演示的主要功能
- OAuth代理模式:将DCR不兼容的OAuth提供程序与MCP客户端连接起来
- 动态客户端注册仿真:接受客户端注册请求并返回预先配置的凭据
- 双PKCE安全:客户端到代理和代理到上游层的端到端PKCE
- 令牌工厂模式:发行FastMCP JWT令牌,而不是转发上游令牌
- 回拨转发:支持动态客户端重定向URI(随机本地主机端口、固定URL)
- JWT令牌验证:使用Keycloak的JWKS端点验证令牌
- 同意屏幕:防止混淆的副手攻击
- FastMCP功能:工具、资源和提示示例
建筑
sequenceDiagram
participant Client as MCP Client
participant Proxy as FastMCP OAuthProxy
participant Keycloak as Keycloak OAuth Provider
participant User
Note over Client,Keycloak: Phase 1: Discovery & Registration
Client->>Proxy: 1. POST /mcp (initialize)
Proxy-->>Client: 401 Unauthorized + metadata URL
Client->>Proxy: 2. GET /.well-known/oauth-protected-resource/mcp
Proxy-->>Client: OAuth server metadata
Client->>Proxy: 3. POST /register (DCR with redirect_uri)
Note over Proxy: Records client redirect_uri
Returns pre-configured credentials
Proxy-->>Client: client_id (fixed upstream credentials)
Note over Client,Keycloak: Phase 2: Authorization with Dual-PKCE
Client->>Proxy: 4. GET /authorize?code_challenge=...
Note over Proxy: Stores client PKCE challenge
Generates own PKCE for upstream
Proxy-->>User: Show consent page
User->>Proxy: Approve client
Proxy->>Keycloak: Redirect to /authorize (proxy PKCE)
Keycloak-->>User: Login page
User->>Keycloak: Authenticate
Keycloak-->>Proxy: Authorization code
Note over Client,Keycloak: Phase 3: Token Exchange
Proxy->>Keycloak: POST /token (code + proxy verifier)
Keycloak-->>Proxy: Upstream access_token
Note over Proxy: Encrypts & stores upstream token
Issues new FastMCP JWT
Proxy-->>Client: Redirect to client redirect_uri + code
Client->>Proxy: 5. POST /token (code + client verifier)
Note over Proxy: Validates client PKCE
Returns FastMCP JWT
Proxy-->>Client: FastMCP JWT token
Note over Client,Keycloak: Phase 4: Authenticated Requests
Client->>Proxy: 6. POST /mcp (with FastMCP JWT)
Note over Proxy: Validates FastMCP JWT
Verifies upstream token
Proxy-->>Client: Protected MCP resources运作原理
- 问题:MCP客户端期望动态客户端注册(DCR)-他们希望自动注册并即时获得凭据。Keycloak需要通过其管理控制台手动注册应用程序。
- 解决方案:OAuthProxy在幕后使用预先注册的Keycloak凭据时,向MCP客户端提供符合DCR的接口。
- 流量:
- 当客户端注册时,代理返回您的固定Keycloak凭据并存储客户端的回调URL - 当客户端授权时,代理使用Keycloak的固定回调URL,然后转发回客户端的动态回调 - 代理发出自己的FastMCP JWT令牌(用HS256签名),而不是直接转发Keycloak令牌 - 这保持了适当的OAuth 2.0受众边界,并实现了更好的安全控制
先决条件
- Python 3.12+:FastMCP需要
- 码头工人:用于在本地运行Keycloak
- 紫外线:Python包管理器
- 安装紫外线: curl -LsSf https://astral.sh/uv/install.sh | sh - 或者看看 紫外线安装文档
安装
1.克隆存储库
git clone https://github.com/vikrantjain/mcp-oauth-proxy-demo.git
cd mcp-oauth-proxy-demo2.安装依赖项
uv sync配置
1.使用Docker启动Keycloak
docker run -d \
--name keycloak \
-p 8080:8080 \
-e KEYCLOAK_ADMIN=admin \
-e KEYCLOAK_ADMIN_PASSWORD=admin \
quay.io/keycloak/keycloak:latest \
start-dev访问Keycloak管理控制台http://localhost:8080(凭据:admin/admin)
2.在Keycloak中创建客户端
- 导航到 客户 在左侧边栏中
- 点击 创建客户端
- 配置客户端:
- 客户端ID: mcp_server - 客户端认证:ON(机密客户) - 有效的重定向URI: http://localhost:8000/auth/callback - 有效的注销后重定向URI: http://localhost:8000
- 保存客户端
- 去 凭证 选项卡并复制 客户端密钥
3.配置环境变量
cp .env.example .env
# Edit .env and add your Keycloak client secret更新 .env 根据您的实际值:
KEYCLOAK_CLIENT_ID=mcp_server
KEYCLOAK_CLIENT_SECRET=
KEYCLOAK_BASE_URL=http://localhost:8080
KEYCLOAK_REALM=master
MCP_SERVER_BASE_URL=http://localhost:8000运行服务器
uv run fastmcp run mcp-server.py --transport streamable-http --host 0.0.0.0 --port 8000服务器将于启动http://localhost:8000
使用示例
1.Python客户端(FastMCP客户端)
uv run python mcp-client.py此客户端演示:
- 呼叫
greet工具 - 阅读
resource://server/config资源(OAuth配置) - 获取
explain_oauth_flow提示
2.REST客户端(VS代码REST客户端扩展)
安装 REST客户端扩展 对于VS代码。
使用 client-proxy.rest 要使用动态客户端注册测试完整的OAuth代理流,请执行以下操作:
- 打开
client-proxy.rest - 遵循OAuth的分步流程:
- 发现和元数据检索 - 动态客户端注册 - 使用PKCE进行授权 - 代币兑换 - 经过身份验证的MCP请求
备注: client.rest 包含未经身份验证的引用请求,但由于服务器需要OAuth身份验证,因此将失败。
项目结构
.
├── mcp-server.py # FastMCP server with OAuthProxy configuration
├── mcp-client.py # Python client example using FastMCP Client
├── client.rest # Simple MCP API tests (REST Client)
├── client-proxy.rest # Complete OAuth flow demonstration
├── pyproject.toml # Python project dependencies
├── uv.lock # Dependency lock file
├── .env.example # Environment variables template
├── .env # Your actual environment variables (gitignored)
├── .gitignore # Git ignore patterns
├── .python-version # Python version specification (3.12)
└── README.md # This file安全特性
- 双PKCE:客户端到代理和代理到上游层的端到端PKCE
- 使用者同意:客户授权前需要明确批准
- 加密令牌存储:用于存储令牌的AES-128-CBC+HMAC-SHA256加密
- JWT签名验证:FastMCP令牌的HS256签名验证
- 受众验证:防止不同服务之间的令牌滥用
- 困惑的副保护:同意屏幕可防止恶意客户端模拟
了解更多
许可证
MIT许可证-有关详细信息,请参阅许可证文件
贡献
欢迎投稿!请随时提交拉取请求。
