本演示展示了如何使用Entra ID作为第三方授权服务器,根据MCP授权规范来保护MCP服务器。此示例包括了从MCP Python SDK中实现的针对Microsoft Entra ID的OAuthAuthorizationServerProvider。
MCP服务器提供了一个名为get_user_name的演示工具,展示如何在MCP工具中访问经过身份验证的用户信息。该工具:
这个简单的工具演示了从认证到使用用户上下文访问受保护资源的完整OAuth2流程。
此解决方案仅用于演示目的,并不适合生产环境使用。某些情况下,代码注释会突出需要关注的区域。
azure_user_mcp_server.py
simple_oauth_client_example.py
创建一个Entra应用注册,并在“认证”选项中启用公共客户端流。这确保服务器在进行令牌交换时不需要密钥。

http://localhost:8000/auth/callback设置为重定向URI。

在项目根目录下创建一个.env文件,包含以下变量:
AUTH_TENANT_ID=your-tenant-id
AUTH_CLIENT_ID=your-client-id
# 可选:
# AUTH_AUTHORITY=login.microsoftonline.com
# AUTH_REDIRECT_URI=http://localhost:8000/auth/callback
AUTH_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
客户端将:

MCP Inspector是一款用于与MCP服务器交互的图形工具。
安装:
认证:
http://localhost:8000/sse)。这允许您使用图形界面与已认证的OAuth2令牌访问受保护的MCP服务器。

此实现包括对困惑副手攻击的防护,这是一种可能发生在OAuth2流程中的安全漏洞,其中MCP服务器同时充当OAuth2客户端和服务提供商。
在一个困惑副手攻击场景中:
以下图表说明了恶意行为者如何利用困惑副手漏洞:
%%{init: {'theme':'dark'}}%%
sequenceDiagram
participant U as 合法用户
participant LC as 合法客户端
participant MS as MCP服务器
participant EA as Entra ID
participant MA as 恶意行为者
participant MC as 恶意客户端
Note over U,MC: 困惑副手攻击场景
%% 第一步:合法用户设置
rect rgb(40, 80, 40)
Note over U,EA: 阶段1:合法用户设置
U->>LC: 连接MCP客户端到服务器
LC->>MS: 启动OAuth流程
MS->>EA: 与服务器授权
EA->>U: 显示同意屏幕
U->>EA: 认证并同意
EA->>U: 在浏览器中设置会话cookie
EA->>MS: 返回授权码
MS->>LC: 完成合法连接
end
%% 第二步:恶意行为者准备
rect rgb(100, 20, 20)
Note over MA,MS: 阶段2:恶意客户端注册
MA->>MS: 使用动态客户端注册
MS->>MA: 注册恶意客户端并返回client_id
MA->>MA: 制作恶意授权链接<br/>使用自己的client_id和redirect_uri
end
%% 第三步:攻击执行
rect rgb(110, 20, 20)
Note over MA,EA: 阶段3:攻击执行
MA->>U: 发送精心制作的链接(网络钓鱼/社会工程)
U->>MS: 点击链接 - 转向OAuth端点
MS->>EA: 使用恶意client_id启动OAuth流程
Note over EA: 找到现有会话cookie!<br/>无需新的同意
EA->>MS: 自动批准并返回授权码
MS->>MC: 重定向到恶意客户端的redirect_uri
MC->>MA: 恶意客户端接收令牌
MA->>EA: 使用令牌访问Graph API
Note over MA,EA: 使用服务器的提升权限获得访问
end
Note over U,MC: 用户现有的同意绕过了额外的授权,<br/>恶意行为者获得了服务器级别的用户数据访问权限
考虑以下场景:
恶意URL示例:
http://your-mcp-server.com/auth/authorize?response_type=code&client_id=恶意客户端-123&redirect_uri=https://邪恶行为者.com/callback&scope=user.read
^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
恶意客户端ID 攻击者重定向URI
https://邪恶行为者.com/callback)为了缓解这一威胁,此实现包括在初始MCP客户端授权期间的一个额外同意屏幕,该屏幕:
同一客户端的后续授权只要存在有效的同意cookie则不需要再次同意。
同意屏幕的防护是通过复杂的基于Cookie的验证系统强制执行的:
同意Cookie生成:
application_id:请求访问的客户端IDredirect_uri:客户端注册的重定向URIscopes:授予的具体权限expires_on:Cookie过期时间戳(默认30天)signature:使用服务器的认证密钥生成的HMAC签名,防止篡改同意验证流程:
application_id与请求客户端匹配redirect_uri与注册客户端重定向URI匹配scopes与请求权限匹配安全性优势:
这确保即使恶意客户端试图利用服务器的权限,用户仍然对其代表自己执行的实际操作拥有明确的控制权。

致谢: 特别感谢Den Delimarsky提醒我们注意困惑副手威胁向量。关于此漏洞在MCP和API管理背景下的深入分析,请参阅他的详细博客文章:MCP和API管理中的困惑副手问题。
需要Azure应用注册: 在运行此演示之前,您必须在Microsoft Entra ID(Azure AD)中创建一个应用注册。此注册提供了.env文件所需的AUTH_CLIENT_ID和AUTH_TENANT_ID值。
设置说明: 有关创建应用注册和配置重定向URI的详细步骤,请遵循官方Microsoft文档:将应用程序注册到Microsoft标识平台
重定向URI配置: 确保您的应用注册包括http://localhost:8000/auth/callback作为认证设置中的有效重定向URI。