在 API Management 中保护对 MCP 服务器的访问

借助 API 管理中的 MCP 服务器支持,你可以公开并管理对 MCP 服务器及其工具的访问权限。 本文介绍如何确保对在API Management中管理的MCP服务器的安全访问,包括通过托管的REST API暴露的MCP服务器,以及托管在API Management外部的现有MCP服务器。

可以确保 MCP 服务器的入站访问(从 MCP 客户端到 API 管理)和出站访问(从 API 管理到 MCP 服务器)的安全。

保护入站访问

基于密钥的身份验证

如果 MCP 服务器使用传入的 Ocp-Apim-Subscription-Key 标头中传递的API Management订阅密钥进行保护,MCP 客户端可以在传入请求中显示密钥,MCP 服务器可以验证密钥。 例如,在 Visual Studio Code 中,可以将 headers 节添加到 MCP 服务器配置中,以要求请求标头中的订阅密钥:

{
  "name": "My MCP Server",
  "type": "remote",
  "url": "https://my-api-management-instance.azure-api.cn/my-mcp-server",    
  "transport": "streamable-http",
  "headers": {
    "Ocp-Apim-Subscription-Key": "<subscription-key>"
  }
}

注释

使用 Visual Studio Code 工作区设置或安全输入安全地管理订阅密钥。

基于令牌的身份验证(具有Microsoft Entra ID的 OAuth 2.1)

MCP 客户端可以使用 Authorization 标头提供由Microsoft Entra ID颁发的 OAuth 令牌或 JWT,并通过API Management进行验证。

例如,使用 validate-azure-ad-token 策略验证 Microsoft Entra ID 令牌:

<validate-azure-ad-token tenant-id="your-entra-tenant-id" header-name="Authorization" failed-validation-httpcode="401" failed-validation-error-message="Unauthorized. Access token is missing or invalid.">     
    <client-application-ids>
        <application-id>your-client-application-id</application-id>
    </client-application-ids> 
</validate-azure-ad-token>

将令牌转发到后端

请求标头会自动转发(具有某些排除项)到 MCP 工具调用,从而简化与依赖标头进行路由、上下文或身份验证的下游 API 的集成。

如果需要显式转发 Authorization 标头来验证传入的请求,可以使用以下方法之一:

  • 在 API 设置中显式将 Authorization 定义为必需的标头,并在 Outbound 策略中转发该标头。

    示例策略片段:

    <!-- Forward Authorization header to backend --> 
    <set-header name="Authorization" exists-action="override"> 
        <value>@(context.Request.Headers.GetValueOrDefault("Authorization"))</value> 
    </set-header> 
    
  • 使用 API 管理中的凭据管理器和策略(get-authorization-contextset-header)安全地转发令牌。 有关详细信息,请参阅 安全的出站访问

有关更多入站授权选项和示例,请参阅:

配置 OAuth 2 的向外访问的步骤

步骤 1:在标识提供程序中注册应用程序。

Step 2:在链接到标识提供者的API Management中创建凭据提供程序。

步骤 3:在凭据管理器中配置连接。

Step 4:应用API Management策略以动态提取和附加凭据。

例如,以下策略将在传出请求的 Authorization 头部中设置从凭据管理器检索到的访问令牌。

<!-- Add to inbound policy. -->
<get-authorization-context
    provider-id="your-credential-provider-id" 
    authorization-id="auth-01" 
    context-variable-name="auth-context" 
    identity-type="managed" 
    ignore-error="false" />
<!-- Attach the token to the backend call -->
<set-header name="Authorization" exists-action="override">
    <value>@("Bearer " + ((Authorization)context.Variables.GetValueOrDefault("auth-context"))?.AccessToken)</value>
</set-header>