使用 .NET 从代理调用自定义 API

可通过多种方式从代理调用自定义 API。 根据你的方案,可以使用IDownstreamApi、MicrosoftIdentityMessageHandler或IAuthorizationHeaderProvider中的任意一个。 本指南解释了三种不同方法来调用您自己的受保护 API。

若要从代理调用 API,需要获取代理可用于向 API 进行身份验证的访问令牌。 建议使用适用于 .NET 的 Microsoft.Identity.Web SDK 调用 Web API。 此 SDK 简化了获取和验证令牌的过程。 对于其他语言,请使用 Microsoft Entra ID 身份验证 SDK (sidecar)。

先决条件

  • 具有调用目标 API 的适当权限的代理标识。 你需要一个代表流的用户。
  • 具有调用目标 API 的适当权限的代理用户帐户。

根据方案确定使用哪种方法

下表可帮助你确定使用哪种方法。 对于大多数方案,我们建议使用 IDownstreamApi。

Approach 复杂性 灵活性 用例
IDownstreamApi 低 Medium 带有配置选项的标准 REST API
MicrosoftIdentityMessageHandler Medium 高 具有直接注入(DI)和可组合管道的 HttpClient
IAuthorizationHeaderProvider 高 非常高 完全控制 HTTP 请求

IDownstreamApi 是三个选项中调用受保护 API 的首选方法。 它高度可配置,需要最少的代码更改。 它还提供自动令牌获取。

需要以下列出的项时使用 IDownstreamApi :

  • 正在调用标准 REST API
  • 需要配置驱动的方法
  • 需要自动序列化/反序列化
  • 你想要编写最少的代码

调用 API

确定适合自己的内容后,继续调用自定义 Web API。

Warning

由于安全风险,客户端机密不应在生产环境中用作代理标识蓝图的客户端凭据。 而是使用更安全的身份验证方法 ,例如将联合标识凭据(FIC)与托管标识 或客户端证书配合使用。 这些方法通过消除直接在应用程序配置中存储敏感机密的需要,从而提供增强的安全性。

  1. 安装所需的 NuGet 包:

    dotnet add package Microsoft.Identity.Web.DownstreamApi
    dotnet add package Microsoft.Identity.Web.AgentIdentities
    
  2. 在 appsettings.json中配置令牌凭据选项和 API。

    {
      "AzureAd": {
        "Instance": "https://login.partner.microsoftonline.cn/",
        "TenantId": "your-tenant-id",
        "ClientId": "your-blueprint-id",
        "ClientCredentials": [
          {
            "SourceType": "ClientSecret",
            "ClientSecret": "your-client-secret"
          }
        ]
      },
      "DownstreamApis": {
        "MyApi": {
          "BaseUrl": "https://api.example.com",
          "Scopes": ["api://my-api-client-id/read", "api://my-api-client-id/write"],
          "RelativePath": "/api/v1",
          "RequestAppToken": false
        }
      }
    }
    
  3. 配置服务以添加下游 API 支持:

    using Microsoft.AspNetCore.Authentication.OpenIdConnect;
    using Microsoft.Identity.Web;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add authentication
    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
        .EnableTokenAcquisitionToCallDownstreamApi()
        .AddInMemoryTokenCaches();
    
    // Register downstream APIs
    builder.Services.AddDownstreamApis(
        builder.Configuration.GetSection("DownstreamApis"));
    
    // Add Agent Identities support
    builder.Services.AddAgentIdentities();
    
    builder.Services.AddControllersWithViews();
    
    var app = builder.Build();
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();
    app.Run();
    
  4. 使用 IDownstreamApi.. 调用受保护的 API。 调用 API 时,可以使用 WithAgentIdentity 方法或 WithAgentUserIdentity 方法指定代理标识或代理的用户帐户标识。 IDownstreamApi 自动处理令牌获取并将访问令牌附加到请求。

    • 对于 WithAgentIdentity,您可以使用仅限应用程序的令牌(自治代理)或代表用户的令牌(交互式代理)来调用 API。

      using Microsoft.Identity.Abstractions;
      using Microsoft.AspNetCore.Authorization;
      using Microsoft.AspNetCore.Mvc;
      
      [Authorize]
      public class ProductsController : Controller
      {
          private readonly IDownstreamApi _api;
      
          public ProductsController(IDownstreamApi api)
          {
              _api = api;
          }
      
          // GET request for app only token scenario for agent identity
          public async Task<IActionResult> Index()
          {
      
              string agentIdentity = "<your-agent-identity>";
              var products = await _api.GetForAppAsync<List<Product>>(
                  "MyApi",
                  "products",
                  options => options.WithAgentIdentity(agentIdentity));
      
              return View(products);
          }
      
          // GET request for on-behalf of user token scenario for agent identity
          public async Task<IActionResult> UserProducts()
          {
      
              string agentIdentity = "<your-agent-identity>";
              var products = await _api.GetForUserAsync<List<Product>>(
                  "MyApi",
                  "products",
                  options => options.WithAgentIdentity(agentIdentity));
      
              return View(products);
          }
      }
      
    • 对于 WithAgentUserIdentity,可以指定用户主体名称(UPN)或对象标识(OID)来标识代理的用户帐户。

      using Microsoft.Identity.Abstractions;
      using Microsoft.AspNetCore.Authorization;
      using Microsoft.AspNetCore.Mvc;
      
      [Authorize]
      public class ProductsController : Controller
      {
          private readonly IDownstreamApi _api;
      
          public ProductsController(IDownstreamApi api)
          {
              _api = api;
          }
      
          // GET request for agent's user account identity using UPN
          public async Task<IActionResult> Index()
          {
      
              string agentIdentity = "<your-agent-identity>";
              string userUpn = "user@contoso.com";
      
              var products = await _api.GetForUserAsync<List<Product>>(
                  "MyApi",
                  "products",
                  options => options.WithAgentUserIdentity(agentIdentity, userUpn));
              return View(products);
          }
      
          // GET request for agent's user account identity using OID
          public async Task<IActionResult> UserProducts()
          {
      
              string agentIdentity = "<your-agent-identity>";
              string userOid = "user-object-id";
      
              var products = await _api.GetForUserAsync<List<Product>>(
                  "MyApi",
                  "products",
                  options => options.WithAgentUserIdentity(agentIdentity, userOid));
      
              return View(products);
          }
      
      }