使用 .NET Azure SDK 从代理调用 Azure 服务

本文介绍如何从代理调用 Azure 服务。 若要使用代理身份验证向 Azure 服务(如 Azure 存储 或 Azure 密钥保管库)进行身份验证,请使用 MicrosoftIdentityTokenCredential 类,该类来自 Microsoft.Identity.Web.Azure。 该 MicrosoftIdentityTokenCredential 类实现 Azure SDK 的 TokenCredential 接口,从而在 Microsoft.Identity.Web 和 Azure SDK 客户端之间实现无缝集成。

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

先决条件

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

实施步骤

  1. 安装 Azure 集成包和 Microsoft.Identity.Web.AgentIdentities 包,以添加对代理标识的支持。

    dotnet add package Microsoft.Identity.Web.Azure
    dotnet add package Microsoft.Identity.Web.AgentIdentities
    
  2. 安装要使用的Azure SDK包,例如Azure 存储:

    dotnet add package Azure.Storage.Blobs
    
  3. 配置服务以添加Azure令牌凭据支持:

    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();
    
    // Add Azure token credential support
    builder.Services.AddMicrosoftIdentityAzureTokenCredential();
    
    builder.Services.AddControllersWithViews();
    var app = builder.Build();
    app.UseAuthentication();
    app.UseAuthorization();
    app.MapControllers();
    app.Run();
    
  4. appsettings.json 中配置 Azure 令牌凭据选项

    Warning

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

    {
      "AzureAd": {
        "Instance": "https://login.partner.microsoftonline.cn/",
        "TenantId": "<your-tenant-id>",
        "ClientId": "<agent-blueprint-id>",
    
       // Other client creedentials available. 
        "ClientCredentials": [
          {
            "SourceType": "ClientSecret",
            "ClientSecret": "your-client-secret"
          }
        ]   
      }
    }
    
  5. 从服务提供商获取令牌凭据,并将其与 Azure SDK 客户端一起使用。

    1. 对于代理身份,可以通过使用 WithAgentIdentity 方法获取仅应用令牌(自治代理)或代表用户令牌(交互式代理)。 对于仅限应用的令牌,请将 RequestAppToken 属性设置为 true。 对于代表用户令牌进行委派,请不要设置 RequestAppToken 属性或显式将其设置为 false

      using Microsoft.Identity.Web;
      
      public class AgentService
      {
          private readonly MicrosoftIdentityTokenCredential _credential;
      
          public AgentService(MicrosoftIdentityTokenCredential credential)
          {
              _credential = credential;
          }
      
          // Call Azure service with the agent identity for app only scenario
          public async Task<List<string>> ListBlobsForAgentAppOnlyAsync(string agentIdentity)
          {
              // Configure for agent identity
              _credential.Options.WithAgentIdentity(agentIdentity);
              _credential.Options.RequestAppToken = true;
      
              var blobClient = new BlobServiceClient(
                  new Uri("https://myaccount.blob.core.chinacloudapi.cn"),
                  _credential);
      
              var container = blobClient.GetBlobContainerClient("agent-data");
              var blobs = new List<string>();
      
              await foreach (var blob in container.GetBlobsAsync())
              {
                  blobs.Add(blob.Name);
              }
      
              return blobs;
          }
      
          // Call Azure service with the agent identity for on-behalf of user scenario
          public async Task<List<string>> ListBlobsForAgentOnBehalfOfUserAsync(string agentIdentity)
          {
              // Configure for agent identity
              _credential.Options.WithAgentIdentity(agentIdentity);
              _credential.Options.RequestAppToken = false;
      
              var blobClient = new BlobServiceClient(
                  new Uri("https://myaccount.blob.core.chinacloudapi.cn"),
                  _credential);
      
              var container = blobClient.GetBlobContainerClient("agent-data");
              var blobs = new List<string>();
      
              await foreach (var blob in container.GetBlobsAsync())
              {
                  blobs.Add(blob.Name);
              }
      
              return blobs;
          }
      }
      
    2. 还可以获取代理用户帐户的令牌。 为此,可以使用用户主体名称(UPN)或对象标识(OID)来标识代理的用户帐户。

      对于对象 ID:

      using Microsoft.Identity.Web;
      
      public class AgentService
      {
          private readonly MicrosoftIdentityTokenCredential _credential;
      
          public AgentService(MicrosoftIdentityTokenCredential credential)
          {
              _credential = credential;
          }
      
          // Use object ID to identify the agent's user account
          public async Task<List<string>> ListBlobsForAgentUserByOidAsync(string agentIdentity)
          {
              // Configure for agent identity
              string userOid = "user-object-id";
              _credential.Options.WithAgentUserIdentity(agentIdentity, userOid);
      
              var blobClient = new BlobServiceClient(
                  new Uri("https://myaccount.blob.core.chinacloudapi.cn"),
                  _credential);
      
              var container = blobClient.GetBlobContainerClient("agent-data");
              var blobs = new List<string>();
      
              await foreach (var blob in container.GetBlobsAsync())
              {
                  blobs.Add(blob.Name);
              }
      
              return blobs;
          }
      
          // Use UPN to identify the agent's user account
          public async Task<List<string>> ListBlobsForAgentUserByUpnAsync(string agentIdentity)
          {
              // Configure for agent identity
              string userUpn = "user@contoso.com";
      
              _credential.Options.WithAgentUserIdentity(agentIdentity, userUpn);
      
              var blobClient = new BlobServiceClient(
                  new Uri("https://myaccount.blob.core.chinacloudapi.cn"),
                  _credential);
      
              var container = blobClient.GetBlobContainerClient("agent-data");
              var blobs = new List<string>();
      
              await foreach (var blob in container.GetBlobsAsync())
              {
                  blobs.Add(blob.Name);
              }
      
              return blobs;
          }
      }