关于 🤫 Authenticated Remote MCP Server
Authenticated Remote MCP Server 是一个示例项目,演示如何在 Azure 上部署受 Entra ID 保护的远程 MCP 服务。项目通过 Azure API Management 进行鉴权,并使用 OAuth 2.0 与 PKCE 流程。README 明确标注为实验性实现,不应用于生产环境。
主要功能
- 01基于 Entra ID 的远程 MCP 服务保护
- 02客户端先获取 MCP 服务令牌,再通过 OAuth on-behalf-of 流程访问 Microsoft Graph
- 03动态客户端注册与 PKCE 流程
- 04使用 __Host- 前缀的安全 Cookie 与 CSRF 防护
- 05通过 azd up 部署到 Azure
适用场景
- 01学习在 Azure 上部署受保护的远程 MCP 服务
- 02使用 MCP Inspector 测试 Entra ID 认证流程
- 03验证 Microsoft Graph 用户信息的获取方式
MCP 相关
该示例将远程 MCP 服务部署在 Azure 上,并通过 SSE 端点供 MCP Inspector 等 MCP 客户端连接,工具 get_graph_user_details 用于获取当前用户数据。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
🤫 经过身份验证的远程 MCP 服务
此示例演示如何在 Azure 上部署受 Entra ID 保护的 MCP 服务。
此示例还采用了一种授权模式:客户端首先获取一个_用于 MCP 服务_的令牌,然后通过代表流将其兑换为可用于Microsoft Graph的令牌。整个过程也完全无需使用机密。
⚠️ 重要:实验性实现
重要
这是一个实验性实现,不应在生产场景中使用。
此示例演示如何通过实现 OAuth 2.0 动态客户端注册和 PKCE 流模式,在 Entra ID 的原生标准支持尚有不足的情况下,构建受 Entra ID 保护的 MCP 服务。此示例展示了技术上的可行性,但仅用于教育和概念验证。
对于生产场景,请考虑使用已注册应用和标准 OAuth 流的成熟身份验证模式。
使用的技术
说明
你可以使用 Model Context Protocol Inspector 或 Visual Studio Code 测试此 MCP 服务。
授权流的工作方式
此实现使用带有 PKCE(代码交换证明)的高级 OAuth 2.0 流,对 MCP 客户端进行安全身份验证。以下是整个流程的运作方式:
sequenceDiagram
participant Client as MCP Client
participant Browser as User's Browser
participant APIM as API Management
participant Entra as Entra ID
participant Function as Azure Function
participant Graph as Microsoft Graph
Note over Client,Graph: 1. Discovery & Registration
Client->>APIM: GET /.well-known/oauth-authorization-server
APIM->>Client: OAuth metadata (authorization_endpoint, token_endpoint, etc.)
Client->>APIM: POST /register (Dynamic Client Registration)
Note over APIM: Store client info in CosmosDB<br/>Generate unique client_id
APIM->>Client: Client credentials (client_id, no secret)
Note over Client,Graph: 2. Authorization with PKCE
Note over Client: Generate code_verifier & code_challenge
Client->>Browser: Open authorization URL with PKCE params
Browser->>APIM: GET /authorize?client_id=...&code_challenge=...
Note over APIM: Check for existing consent cookie<br/>🍪 __Host-MCP_APPROVED_CLIENTS
alt No previous consent
APIM->>Browser: Redirect to /consent page
Note over Browser: User reviews permissions and clicks "Allow"
Browser->>APIM: POST /consent (with CSRF protection)
Note over APIM: Set consent cookie<br/>🍪 __Host-MCP_APPROVED_CLIENTS<br/>🍪 __Host-MCP_CONSENT_STATE
end
APIM->>Browser: Redirect to Entra ID with state correlation
Note over APIM: Set Entra state cookie<br/>🍪 __Host-MCP_ENTRA_STATE<br/>(contains sessionId|entraidState|clientState)
Browser->>Entra: Authorize with Entra ID
Note over Browser: User authenticates with Entra ID
Entra->>APIM: Callback with authorization code
Note over APIM: Validate state correlation<br/>Exchange code for Entra access token<br/>Generate encrypted session token
APIM->>Browser: Redirect with MCP authorization code
Note over Client,Graph: 3. Token Exchange
Browser->>APIM: POST /token (code + code_verifier)
Note over APIM: Validate PKCE challenge<br/>Return encrypted session token
APIM->>Browser: Access token (encrypted session key)
Browser->>Client: Token for MCP communication
Note over Client,Graph: 4. Authenticated MCP Communication
Client->>APIM: GET /mcp/sse (with Bearer token)
Note over APIM: Decrypt session token<br/>Lookup cached Entra token<br/>Add to request for downstream
APIM->>Function: Forward with Entra access token
Function->>Graph: API calls using on-behalf-of flow
Graph->>Function: User data
Function->>APIM: MCP response
APIM->>Client: Authenticated MCP response
安全功能与使用的 Cookie
此实现使用多种安全机制和 Cookie,确保流程安全:
| Cookie | 用途 |
|---|---|
__Host-MCP_APPROVED_CLIENTS | 记住用户对特定客户端的授权 |
__Host-MCP_DENIED_CLIENTS | 记住被拒绝的授权,避免再次提示 |
__Host-MCP_CONSENT_STATE | 验证授权表单提交 |
__Host-MCP_ENTRA_STATE | 将 Entra ID 回调与原始请求关联起来 |
__Host-MCP_CSRF_TOKEN | 防止授权表单遭受 CSRF 攻击 |
说明
所有 Cookie 均使用
__Host-前缀,并设置 Secure、HttpOnly 和 SameSite=Lax,以实现最高安全性(但__Host-MCP_ENTRA_STATE除外,它使用 SameSite=None 进行跨站重定向)。
主要安全功能:
- 🔐 PKCE(代码交换证明) - 防止授权码被截获
- 🍪 安全 Cookie - 所有 Cookie 均使用
__Host-前缀,以实现最高安全性 - 🛡️ CSRF 防护 - 使用双重提交 Cookie 模式和恒定时间验证
- 🔄 状态关联 - 多层状态验证可防止会话固定
- 🔒 加密的会话令牌 - 会话标识符经过 AES 加密
- ⏰ 令牌缓存 - 缓存 Entra 令牌,并使用加密的会话密钥提升性能
开始使用
按照以下步骤开始使用。
-
在本地克隆仓库:
git clone https://github.com/localden/remote-auth-mcp-apim-py -
在终端中进入仓库目录:
cd remote-auth-mcp-apim-py -
确保已在订阅中注册
Microsoft.App资源提供程序,可通过 Azure 门户完成注册,也可运行以下 Azure CLI 命令:az login az provider register --namespace Microsoft.App --wait -
登录 Azure Developer CLI:
azd auth login -
将项目部署到 Azure:
azd up
重要
部署此项目会产生 Azure 费用。如果部署用于测试和实验,请务必在测试后删除创建的资源组。
部署和测试项目
运行 azd up 时,infra 目录中声明的资源将在你的 Azure 帐户中预配。你可以查看现有的 Bicep 文件,了解将自动部署哪些基础设施。

部署完成后,终端中会显示 endpoint:

例如,在上方的屏幕截图中,终结点是 https://apim-2lzunaz2nu642.azure-api.net/mcp/sse。复制它。
说明
执行下一步之前,请确保已安装 Node.js——运行 Model Context Protocol Inspector 需要它。
在终端中运行:
npx @modelcontextprotocol/[email protected]
说明
我们使用 Model Context Protocol Inspector 的
0.9.0版本,因为在测试受保护的 MCP 服务时,这是最稳定的版本。
这将提供一个终结点,你可以通过它查看本地运行的 Model Context Protocol Inspector。在浏览器中打开该 URL。
将 Transport Type 切换为 SSE,并将 URL 设置为部署运行后获得的终结点。点击 Connect。

系统会提示你使用部署基础设施所在租户中的凭据进行身份验证。Entra ID 应用程序会在部署时动态注册:一个用于服务,另一个用于执行 on-behalf-of flow,以获取 Microsoft Graph 访问权限。
同意后,你将返回 Model Context Protocol Inspector 的首页。等待几秒钟,直到建立连接;页面上会显示绿色的 Connected 标签。

连接后,点击 List Tools,并选择 get_graph_user_details。这样即可从 Microsoft Graph 获取当前已通过身份验证的用户数据。点击 Run Tool。

如果一切顺利,你会在响应区域中看到用户数据,如下所示:
{
"@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users/$entity",
"businessPhones": [],
"displayName": "YOUR_NAME",
"givenName": null,
"jobTitle": null,
"mail": "YOUR_EMAIL",
"mobilePhone": null,
"officeLocation": null,
"preferredLanguage": null,
"surname": null,
"userPrincipalName": "YOUR_UPN",
"id": "c6b77314-c0ec-44b2-b0bb-2c971a753f0c",
"success": true
}
反馈和问题报告
如果遇到任何阻碍或有意见,请务必提交问题。
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。