使用OAuth和Entra ID实现安全的MCP OAuth桌面客户端

本文详细介绍了如何使用 Microsoft Entra ID 构建一个安全的 MCP OAuth 桌面客户端,涵盖 ASP.NET Core MCP 服务器端实现、.NET 控制台客户端如何通过 PKCE 流程获取访问令牌,以及如何使用 Microsoft.Identity.Client 库进行安全集成。

实现一个使用 OAuth 和 Entra ID 的安全 MCP OAuth 桌面客户端

2025年10月16日 · by damienbod · in .NET, .NET Core, ASP.NET Core, Azure, Entra CIAM, MCP, Microsoft Entra External ID, Microsoft Entra ID, OAuth2, Open AI, Security · 1 Comment

本文演示了如何使用 Microsoft Entra ID 实现一个安全的 MCP OAuth 桌面客户端。MCP 服务器使用 ASP.NET Core 构建,并使用 Microsoft Entra ID 进行安全保护。MCP 客户端是一个 .NET 控制台应用程序,必须获取一个 OAuth 访问令牌才能与 MCP 服务器交互。 代码:https://github.com/damienbod/McpSecurity

设置

开发了一个客户端应用程序,用于对受 Microsoft Entra ID 保护的 MCP 服务器进行身份验证和交互。它使用 Azure OpenAI,并通过公共的 OpenID Connect 客户端获取委派的访问令牌。然后,应用程序调用 MCP 服务器公开的功能。服务器是一个实现了 MCP 服务器 API 的简单 ASP.NET Core 应用程序。

MCP 服务器

新的客户端使用了先前文章《实现一个使用 OAuth 和 Entra ID 的安全 MCP 服务器》中的 MCP 服务器。它只接受来自特定 Microsoft Entra ID 租户的委派访问令牌。

MCP 桌面 OAuth 客户端

使用 Microsoft.Identity.Client Nuget 包来实现公共的 OpenID Connect 客户端。作为桌面应用程序,或本演示中使用的控制台应用程序,无法保存密钥,因此需要使用公共客户端,并且客户端必须使用基于用户的委派访问令牌。使用带有 PKCE 的 OpenID Connect 授权码流程进行身份验证,客户端必须使用 Web 浏览器来验证用户身份。此类应用程序不能使用应用间服务,我们拥有较低的信任级别。

SignInUserAndGetTokenUsingMSAL 方法用于实现用户身份验证。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
private static async Task<string> SignInUserAndGetTokenUsingMSAL(
    PublicClientApplicationOptions configuration, string[] scopes)
{
    string authority = string.Concat(configuration.Instance, configuration.TenantId);
    
    // 通过构建公共客户端应用程序来初始化 MSAL 库
    application = PublicClientApplicationBuilder.Create(configuration.ClientId)
                    .WithAuthority(authority)
                    .WithDefaultRedirectUri()
                    .Build();
    
    AuthenticationResult result;
    try
    {
        var accounts = await application.GetAccountsAsync();
        result = await application.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
         .ExecuteAsync();
    }
    catch (MsalUiRequiredException ex)
    {
        result = await application.AcquireTokenInteractive(scopes)
         .WithClaims(ex.Claims)
         .ExecuteAsync();
    }
    
    return result.AccessToken;
}

CreateMcpTransportAsync 方法使用 Microsoft Entra ID 客户端获取访问令牌,并在 HttpClient 的 Authorization 头中设置 Bearer 令牌。此令牌在 MCP 服务器上进行验证。服务器期望一个包含“mcp:tools”作用域声明的委派访问令牌。不接受应用程序访问令牌。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
private static PublicClientApplicationOptions? appConfiguration = null;
// MSAL 公共客户端应用
private static IPublicClientApplication? application;

public static async Task<IClientTransport> CreateMcpTransportAsync(HttpClient httpClient, IConfigurationRoot configuration)
{
    appConfiguration = configuration.Get<PublicClientApplicationOptions>();
    string[] scopes = ["api://96b0f495-3b65-4c8f-a0c6-c3767c3365ed/mcp:tools"];
    
    // 使用 MSAL 登录用户并获取访问令牌
    var accessToken = await SignInUserAndGetTokenUsingMSAL(appConfiguration!, scopes);
    
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
    
    var httpMcpServer = configuration["HttpMcpServerUrl"];
    var transport = new SseClientTransport(new()
    {
        Endpoint = new Uri(httpMcpServer!),
        Name = "MCP 桌面客户端",
    }, httpClient);
    
    return transport;
}

当应用程序启动时,控制台应用程序会打开浏览器进行身份验证。

注意事项

在此设置中,全程强制使用用户委派的访问令牌。无法实现应用间的安全性。MCP 服务器被用作客户端应用程序中的远程服务器集成。此设置中未使用 DCR,也不应使用。信任是支持 DCR 的主要问题。安全性仍有改进空间,并且存在一些与此相关的有趣的 OAuth 待解决问题。

链接

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计