返回市场
快速MCP-Python-OAuth2-与-Entra-ID集成服务器

快速MCP-Python-OAuth2-与-Entra-ID集成服务器

作者:sean-tate9 星标更新:2025-06-25

项目介绍

MCP服务器授权示例(OAuth2 + Entra ID)

本演示展示了如何使用Entra ID作为第三方授权服务器,根据MCP授权规范来保护MCP服务器。此示例包括了从MCP Python SDK中实现的针对Microsoft Entra ID的OAuthAuthorizationServerProvider

服务器功能

MCP服务器提供了一个名为get_user_name的演示工具,展示如何在MCP工具中访问经过身份验证的用户信息。该工具:

  • 需要认证: 工具只能在通过Entra ID进行OAuth2认证成功后被调用。
  • 返回用户信息: 提供从用户的Entra ID个人资料中获取的显示名称。
  • 演示授权流程: 展示MCP授权规范如何使安全访问用户特定数据成为可能。

这个简单的工具演示了从认证到使用用户上下文访问受保护资源的完整OAuth2流程。

此解决方案仅用于演示目的,并不适合生产环境使用。某些情况下,代码注释会突出需要关注的区域。

组件

  • 服务器: azure_user_mcp_server.py
    • 实现了一个由OAuth2 Bearer令牌(Entra ID)保护的MCP服务器。
  • 客户端: simple_oauth_client_example.py
    • 基于控制台的客户端,使用OAuth2授权码流(带PKCE)与MCP服务器进行身份验证。

环境设置

创建一个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_T_租户ID:您的Entra ID(Azure AD)租户ID
  • AUTH_CLIENT_ID:在Entra ID中注册的客户端/应用程序ID
  • AUTH_REDIRECT_URI:MCP服务器的重定向URI(默认值:http://localhost:8000/auth/callback

如何运行演示

  1. 安装依赖项:

    pip install uv
    uv sync
    
  2. 启动MCP服务器: 在项目根目录下运行:

    make start-server
    
  3. 运行OAuth2控制台客户端: 在新的终端窗口中,从项目根目录运行:

    make start-client
    

    客户端将:

    • 尝试访问受保护的资源(预期结果为401)
    • 启动OAuth2授权码流
    • 打印授权URL到控制台(在浏览器中打开以进行身份验证)
    • 处理回调并交换代码以获取令牌
    • 连接到服务器并通过常见的函数(如列出可用工具和调用工具)让用户与MCP服务器交互。

    使用控制台客户端的安全认证

使用MCP Inspector访问MCP服务器

MCP Inspector是一款用于与MCP服务器交互的图形工具。

  • 安装:

  • 认证:

    1. 安装后启动MCP Inspector。
    2. 连接到适当的URL处的MCP服务器(例如,http://localhost:8000/sse)。

    这允许您使用图形界面与已认证的OAuth2令牌访问受保护的MCP服务器。

    使用MCP Inspector的安全认证

安全性:防范困惑副手攻击

此实现包括对困惑副手攻击的防护,这是一种可能发生在OAuth2流程中的安全漏洞,其中MCP服务器同时充当OAuth2客户端和服务提供商。

困惑副手威胁

在一个困惑副手攻击场景中:

  1. MCP服务器作为副手: MCP服务器充当“副手”——它代表经过身份验证的用户合法访问受保护资源(如Microsoft Graph API)。
  2. 恶意客户端利用: 恶意MCP客户端可能会诱使服务器执行未经授权的API调用:
    • 发送精心设计的请求给之前已经授权并同意的Azure用户,但使用恶意行为者的客户端ID和重定向URI可能导致MCP服务器泄露访问权限给恶意行为者。

攻击流程图

以下图表说明了恶意行为者如何利用困惑副手漏洞:

%%{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/>恶意行为者获得了服务器级别的用户数据访问权限

示例攻击向量

考虑以下场景:

  • 合法用户将其MCP客户端连接到您的服务器,并同意Entra ID访问
  • Entra ID在用户的浏览器中存储了一个会话cookie,以便未来的身份验证
  • 恶意行为者使用您的服务器的动态客户端注册来注册他们自己的客户端
  • 恶意行为者使用其注册的client_id和redirect_uri制作了一个链接

恶意URL示例:

http://your-mcp-server.com/auth/authorize?response_type=code&client_id=恶意客户端-123&redirect_uri=https://邪恶行为者.com/callback&scope=user.read
                                                                    ^^^^^^^^^^^^^^^^^^^               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                                                                    恶意客户端ID                       攻击者重定向URI
  • 当合法用户点击恶意链接时:
    • 他们通过您的MCP服务器的OAuth流程被重定向
    • Entra ID找到现有的会话cookie并自动批准,而无需显示同意屏幕
    • 授权码被发送到恶意行为者注册的重定向URI(https://邪恶行为者.com/callback
    • 恶意行为者获得了具有您服务器范围和权限的访问令牌

防护机制:同意屏幕

为了缓解这一威胁,此实现包括在初始MCP客户端授权期间的一个额外同意屏幕,该屏幕:

  1. 明确用户同意: 在任何受保护的操作之前,用户必须查看并明确同意授权MCP客户端。
  2. 范围限制: 同意屏幕清楚地定义了哪些资源和操作将可访问

同一客户端的后续授权只要存在有效的同意cookie则不需要再次同意。

基于Cookie的防护实现

同意屏幕的防护是通过复杂的基于Cookie的验证系统强制执行的:

同意Cookie生成:

  • 当用户授予同意时,服务器生成一个包含以下内容的加密签名Cookie:
    • application_id:请求访问的客户端ID
    • redirect_uri:客户端注册的重定向URI
    • scopes:授予的具体权限
    • expires_on:Cookie过期时间戳(默认30天)
    • signature:使用服务器的认证密钥生成的HMAC签名,防止篡改

同意验证流程:

  1. 初始请求: 当OAuth授权请求到达时,服务器检查是否存在有效的同意Cookie
  2. Cookie验证: 如果存在Cookie,服务器验证:
    • Cookie签名与预期哈希匹配(防止篡改)
    • Cookie未过期
    • application_id与请求客户端匹配
    • redirect_uri与注册客户端重定向URI匹配
    • scopes与请求权限匹配
  3. 防护决策:
    • 发现有效Cookie: 授权直接进入Entra ID
    • 无有效Cookie: 用户首先被重定向到同意屏幕

安全性优势:

  • 防止重放攻击: 每个同意Cookie都绑定到一个特定的动态注册(MCP)客户端
  • 防篡改: 加密签名防止恶意修改
  • 时效性: Cookies过期,需要定期重新同意
  • 范围具体化: 同意细化到确切请求的权限

这确保即使恶意客户端试图利用服务器的权限,用户仍然对其代表自己执行的实际操作拥有明确的控制权。

同意屏幕

致谢: 特别感谢Den Delimarsky提醒我们注意困惑副手威胁向量。关于此漏洞在MCP和API管理背景下的深入分析,请参阅他的详细博客文章:MCP和API管理中的困惑副手问题

注意事项

  • 需要Azure应用注册: 在运行此演示之前,您必须在Microsoft Entra ID(Azure AD)中创建一个应用注册。此注册提供了.env文件所需的AUTH_CLIENT_IDAUTH_TENANT_ID值。

  • 设置说明: 有关创建应用注册和配置重定向URI的详细步骤,请遵循官方Microsoft文档:将应用程序注册到Microsoft标识平台

  • 重定向URI配置: 确保您的应用注册包括http://localhost:8000/auth/callback作为认证设置中的有效重定向URI。