使用 .NET 从代理调用Microsoft 图形 API

本文介绍如何使用代理身份或代理的用户账户,通过代理调用 Microsoft 图形 API。

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

先决条件

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

调用Microsoft 图形 API

  1. 安装处理 Graph SDK 的身份验证的 Microsoft.Identity.Web.GraphServiceClientMicrosoft.Identity.Web.AgentIdentities 包,以添加对代理标识的支持。

    dotnet add package Microsoft.Identity.Web.GraphServiceClient
    dotnet add package Microsoft.Identity.Web.AgentIdentities
    
  2. 在服务集合中添加对 Microsoft Graph 和代理标识的支持。

    using Microsoft.AspNetCore.Authentication.OpenIdConnect;
    using Microsoft.Identity.Web;
    
    var builder = WebApplication.CreateBuilder(args);
    
    // Add authentication (web app or web API)
    builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
        .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
        .EnableTokenAcquisitionToCallDownstreamApi()
        .AddInMemoryTokenCaches();
    
    // Add Microsoft Graph support
    builder.Services.AddMicrosoftGraph();
    
    // Add Agent Identities support
    builder.Services.AddAgentIdentities();
    
    var app = builder.Build();
    app.UseAuthentication();
    app.UseAuthorization();
    app.Run();
    
  3. appsettings.json中配置 Graph 和代理标识选项。

    Warning

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

    {
      "AzureAd": {
        "Instance": "https://login.partner.microsoftonline.cn/",
        "TenantId": "<your-tenant-id>",
        "ClientId": "<agent-blueprint-client-id>",
        "ClientCredentials": [
          {
            "SourceType": "ClientSecret",
            "ClientSecret": "your-client-secret"
          }
        ]
      },
      "DownstreamApis": {
        "MicrosoftGraph": {
          "BaseUrl": "https://microsoftgraph.chinacloudapi.cn/v1.0",
          "Scopes": ["User.Read", "User.ReadBasic.All"]
        }
      }
    }
    

    注释

    仅配置你的代理所需的 Microsoft Graph 权限,并确保你设置的 Scopes 与你的代码调用的 Graph 资源相匹配。 这些示例使用 User.Read ; User.ReadBasic.All调用其他资源需要其相应的权限。

  4. 现在,您可以通过在您的服务中注入GraphServiceClient或通过服务提供商获取它,然后调用Microsoft Graph。

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

    using Microsoft.Graph;
    using Microsoft.Identity.Web;
    
    // Get the GraphServiceClient
    GraphServiceClient graphServiceClient = serviceProvider.GetRequiredService<GraphServiceClient>();
    
    string agentIdentity = "agent-identity-guid";
    
    // Call Microsoft Graph APIs with the agent identity for app only scenario
    var usersAppOnly = await graphServiceClient.Users
        .GetAsync(r => r.Options.WithAuthenticationOptions(options =>
        {
            options.WithAgentIdentity(agentIdentity);
            options.RequestAppToken = true; // Set to true for app only
        }));
    
    // Call Microsoft Graph APIs with the agent identity for on-behalf of user scenario
    var usersOnBehalfOfUser = await graphServiceClient.Users
        .GetAsync(r => r.Options.WithAuthenticationOptions(options =>
        {
            options.WithAgentIdentity(agentIdentity);
            options.RequestAppToken = false; // False to show it's on-behalf of user
        }));
    
    • 对于代理的用户帐户标识,可以使用该方法 WithAgentUserIdentity 指定用户主体名称(UPN)或对象标识(OID)来标识代理的用户帐户。

      using Microsoft.Graph;
      using Microsoft.Identity.Web;
      
      // Get the GraphServiceClient
      GraphServiceClient graphServiceClient = serviceProvider.GetRequiredService<GraphServiceClient>();
      
      string agentIdentity = "agent-identity-guid";
      
      // Call Microsoft Graph APIs with the agent's user account identity using UPN
      string userUpn = "user-upn";
      var me = await graphServiceClient.Me
          .GetAsync(r => r.Options.WithAuthenticationOptions(options =>
              options.WithAgentUserIdentity(agentIdentity, userUpn)));
      
      // Or using OID
      string userOid = "user-object-id";
      var meByOid = await graphServiceClient.Me
          .GetAsync(r => r.Options.WithAuthenticationOptions(options =>
              options.WithAgentUserIdentity(agentIdentity, userOid)));