MCP服务器授权示例(OAuth2+Entra ID)
服务器功能
MCP服务器提供了一个名为 get_user_name 它展示了如何在MCP工具中访问经过身份验证的用户信息。此工具:
- 需要身份验证: 只有在使用Entra ID成功进行OAuth2身份验证后,才能调用该工具
- 返回用户信息: 提供从用户的Entra ID配置文件中获得的用户显示名称
- 演示授权流程: 显示MCP授权规范如何实现对用户特定数据的安全访问
这个简单的工具演示了从身份验证到使用用户上下文访问受保护资源的完整OAuth2流程。
此解决方案仅用于演示目的,不适用于生产用例。在某些情况下,代码注释会突出显示需要注意的区域。
组件
- 服务器:
azure_user_mcp_server.py
- 实现由OAuth2承载令牌(Entra ID)保护的MCP服务器。
- 客户:
simple_oauth_client_example.py
- 基于控制台的客户端,使用OAuth2授权码流(使用PKCE)与MCP服务器进行身份验证。
环境设置
创建Entra应用程序注册,并在 Authentication 选项。这确保了服务器在进行令牌交换时不需要机密。
- 集
http://localhost:8000/auth/callback作为重定向URI。
创建一个 .env 项目根目录中的文件,包含以下变量:
AUTH_TENANT_ID=your-tenant-id
AUTH_CLIENT_ID=your-client-id
# Optional:
# AUTH_AUTHORITY=login.microsoftonline.com
# AUTH_REDIRECT_URI=http://localhost:8000/auth/callbackAUTH_TENANT_ID:您的Entra ID(Azure AD)租户IDAUTH_CLIENT_ID:在Entra ID中注册的客户/应用程序IDAUTH_REDIRECT_URI:重定向MCP服务器的URI(默认值:http://localhost:8000/auth/callback)
如何运行演示
- 安装依赖项:
pip install uv
uv sync- 启动MCP服务器:
从项目根目录运行:
make start-server- 运行OAuth2控制台客户端:
在新终端中,从项目根目录运行:
make start-client客户将:
- 尝试访问受保护的资源(预期401) - 启动OAuth2授权码流 - 将授权URL打印到控制台(在浏览器中打开以进行身份验证) - 处理回调并将代码交换为令牌 - 连接到服务器,允许用户通过列出可用工具和调用工具等常见功能与MCP服务器进行交互。
Secured Auth using Console Client
使用MCP检查器访问MCP服务器
MCP Inspector是一个用于与MCP服务器交互的图形工具。
- 安装:
- 按照MCP网站上的官方安装说明进行操作: MCP检查员安装指南
- 身份验证:
1. 安装后启动MCP检查器。 1. 在适当的URL处连接到MCP服务器(例如。, http://localhost:8000/sse).
这允许您使用图形界面与安全的MCP服务器进行交互,并使用有效的OAuth2令牌进行身份验证。
Secured Auth using MCP Inspector
安全:混乱的副保护
该实施包括防止 混乱的副攻击,在MCP服务器同时充当OAuth2客户端和服务提供者的OAuth2流中可能出现的安全漏洞。
困惑的副威胁
在一个混乱的副攻击场景中:
- MCP服务器作为代理: MCP服务器充当“代理”-它可以代表经过身份验证的用户合法访问受保护的资源(如Microsoft Graph API)
- 恶意客户端利用: 恶意MCP客户端可能通过以下方式欺骗服务器进行未经授权的API调用:
- 向先前已授权并同意Azure的用户发送精心编制的请求,但使用恶意参与者的客户端id和重定向URI,可能会导致MCP服务器泄露对恶意参与者的访问权限。
攻击流程图
下图说明了恶意行为者如何利用混淆的代理漏洞:
%%{init: {'theme':'dark'}}%%
sequenceDiagram
participant U as Legitimate User
participant LC as Legitimate Client
participant MS as MCP Server
participant EA as Entra ID
participant MA as Malicious Actor
participant MC as Malicious Client
Note over U,MC: Confused Deputy Attack Scenario
%% Step 1: Legitimate user setup
rect rgb(40, 80, 40)
Note over U,EA: Phase 1: Legitimate User Setup
U->>LC: Connect MCP client to server
LC->>MS: Initiate OAuth flow
MS->>EA: Authorize with server
EA->>U: Present consent screen
U->>EA: Authenticate & consent
EA->>U: Set session cookie in browser
EA->>MS: Return authorization code
MS->>LC: Complete legitimate connection
end
%% Step 2: Malicious actor preparation
rect rgb(100, 20, 20)
Note over MA,MS: Phase 2: Malicious Client Registration
MA->>MS: Use dynamic client registration
MS->>MA: Register malicious client & return client_id
MA->>MA: Craft malicious authorization link
with own client_id & redirect_uri
end
%% Step 3: Attack execution
rect rgb(100, 20, 20)
Note over MA,EA: Phase 3: Attack Execution
MA->>U: Send crafted link (phishing/social engineering)
U->>MS: Click link - redirected to OAuth endpoint
MS->>EA: Start OAuth flow with malicious client_id
Note over EA: Existing session cookie found!
No new consent required
EA->>MS: Auto-approve & return auth code
MS->>MC: Redirect to malicious client's redirect_uri
MC->>MA: Malicious client receives tokens
MA->>EA: Use tokens to access Graph APIs
Note over MA,EA: Gains access with server's elevated permissions
end
Note over U,MC: User's existing consent bypassed additional authorization,
malicious actor gains server-level access to user data攻击向量示例
考虑以下情况:
- 合法用户将其MCP客户端连接到您的服务器,并同意Entra ID访问
- Entra ID在用户的浏览器中存储会话cookie,以便将来进行身份验证
- 恶意行为者使用服务器的动态客户端注册来注册自己的客户端
- 恶意行为者使用其注册的client_id和redirect_uri创建链接
恶意URL示例:
http://your-mcp-server.com/auth/authorize?response_type=code&client_id=malicious-client-123&redirect_uri=https://evil-actor.com/callback&scope=user.read
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Malicious Client ID Attacker's Redirect URI- 当合法用户点击恶意链接时:
- 它们通过MCP服务器的OAuth流重定向 - Entra ID找到现有会话cookie并自动批准,而不显示同意屏幕 - 授权码被发送到恶意行为者的注册重定向URI(https://evil-actor.com/callback) - 恶意行为者获得具有服务器范围和权限的访问令牌
保护机制:同意筛查
为了减轻这种威胁,该实施包括 附加同意屏幕 在初始MCP客户端授权期间:
- 明确用户同意: 在任何受保护的操作之前,用户必须审查并明确同意授权MCP客户端。
- 范围限制: 同意屏幕明确定义了可访问的资源和操作
只要存在有效的同意cookie,同一客户的后续授权就不需要同意。
基于Cookie的保护实施
同意屏幕保护是通过一个复杂的基于cookie的验证系统来执行的:
同意Cookie生成:
- 当用户同意时,服务器会生成一个加密签名的cookie,其中包含:
- application_id:请求访问的客户端ID - redirect_uri:客户端的注册重定向URI - scopes:授予的特定权限 - expires_on:Cookie过期时间戳(默认为30天) - signature:使用服务器的身份验证密钥进行HMAC签名以防止篡改
同意验证流程:
- 初始请求: 当OAuth授权请求到达时,服务器会检查有效的同意cookie
- Cookie验证: 如果cookie存在,服务器将验证:
- cookie签名与预期的哈希匹配(防止篡改) - cookie尚未过期 - 这 application_id 匹配请求客户端 - 这 redirect_uri 匹配已注册的客户端重定向URI - 这 scopes 匹配请求的权限
- 保护决定:
- 找到有效Cookie: 授权直接进入Entra ID - 无有效Cookie: 用户首先被重定向到同意屏幕
安全优势:
- 防止重放攻击: 每个同意cookie都绑定到特定的动态注册(MCP)客户端
- 防篡改: 加密签名可防止恶意修改
- 时间限制: Cookie过期,需要定期重新同意
- 具体范围: 同意是按请求的确切权限细化的
这确保了即使恶意客户端试图利用服务器的权限,用户也能明确控制代表他们实际执行的操作。
致谢: 特别感谢 德利马尔斯基 让我们注意到混乱的副威胁向量。有关在MCP和API管理背景下对此漏洞的深入分析,请参阅他的详细博客文章: MCP与API管理中的代理混淆问题.
备注
- 需要Azure应用程序注册: 在运行此演示之前,您必须在Microsoft Entra ID(Azure AD)中创建应用程序注册。此注册提供
AUTH_CLIENT_ID和AUTH_TENANT_ID你需要的价值观.env文件。
- 安装说明: 有关创建应用程序注册和配置重定向URI的详细步骤,请参阅Microsoft官方文档: 使用Microsoft身份平台注册应用程序
- 重定向URI配置: 确保您的申请注册包括
http://localhost:8000/auth/callback作为身份验证设置中的有效重定向URI。
