以应用身份从安全的应用访问 Microsoft Graph

了解如何从 Azure 应用服务上运行的 Web 应用访问 Microsoft Graph。

显示如何访问 Microsoft Graph 流的示意图。

你希望为 Web 应用调用 Microsoft Graph。 向 Web 应用授予数据访问权限的安全方法是使用系统分配的托管标识。 Microsoft Entra ID 中的托管标识允许应用服务通过基于角色的访问控制 (RBAC) 访问资源,而不要求使用应用凭据。 向 Web 应用分配托管标识之后,Azure 会负责创建和分发证书。 你无需费心管理机密或应用凭据。

在本教程中,你将了解:

  • 在 Web 应用上创建系统分配的托管标识。
  • 为托管标识添加 Microsoft Graph API 权限。
  • 使用托管标识从 Web 应用调用 Microsoft Graph。

如果没有 Azure 订阅,可在开始前创建一个 Azure 试用版

先决条件

在应用上启用托管标识

如果通过 Visual Studio 创建和发布 Web 应用,则已在应用上启用了托管标识。 在应用服务中,在左侧窗格中选择“标识”,然后选择“系统分配” 。 验证“状态”是否设置为“打开” 。 如果不是,请依次选择“保存”和“是”以启用系统分配的托管标识 。 启用托管标识后,状态将设置为“启用”并且对象 ID 可用。

记下“对象 ID”值,下一步骤需要使用此值。

显示系统分配的标识的屏幕截图。

授予对 Microsoft Graph 的访问权限

在访问 Microsoft Graph 时,对于要执行的操作,托管标识需要具有适当的权限。 目前,无法通过 Microsoft Entra 管理中心分配此类权限。 下面的脚本将向托管标识服务主体对象添加请求的 Microsoft Graph API 权限。

# Install the module.
# Install-Module Microsoft.Graph -Scope CurrentUser

# The tenant ID
$TenantId = "aaaabbbb-0000-cccc-1111-dddd2222eeee"

# The name of your web app, which has a managed identity.
$webAppName = "SecureWebApp-20201106120003" 
$resourceGroupName = "SecureWebApp-20201106120003ResourceGroup"

# The name of the app role that the managed identity should be assigned to.
$appRoleName = "User.Read.All"

# Get the web app's managed identity's object ID.
Connect-AzAccount -Environment AzureChinaCloud -Tenant $TenantId
$managedIdentityObjectId = (Get-AzWebApp -ResourceGroupName $resourceGroupName -Name $webAppName).identity.principalid

Connect-MgGraph -Environment China -ClientId 'YOUR_CLIENT_ID' -TenantId $TenantId -Scopes 'Application.Read.All','AppRoleAssignment.ReadWrite.All'

# Get Microsoft Graph app's service principal and app role.
$serverApplicationName = "Microsoft Graph"
$serverServicePrincipal = (Get-MgServicePrincipal -Filter "DisplayName eq '$serverApplicationName'")
$serverServicePrincipalObjectId = $serverServicePrincipal.Id

$appRoleId = ($serverServicePrincipal.AppRoles | Where-Object {$_.Value -eq $appRoleName }).Id

# Assign the managed identity access to the app role.
New-MgServicePrincipalAppRoleAssignment `
    -ServicePrincipalId $managedIdentityObjectId `
    -PrincipalId $managedIdentityObjectId `
    -ResourceId $serverServicePrincipalObjectId `
    -AppRoleId $appRoleId

执行该脚本后,可在 Microsoft Entra 管理中心内验证是否已将请求的 API 权限分配给托管标识。

转到“应用程序”,然后选择“企业应用程序”。 此窗格显示租户中的所有服务主体。 为“应用程序类型 == 托管标识”添加筛选器,然后选择托管标识的服务主体。

如果遵循本教程,则有两个具有相同显示名称(例如“SecureWebApp2020094113531”)的服务主体。 具有主页 URL 的服务主体表示租户中的 Web 应用。 “托管标识”中显示的服务主体不应列出“主页 URL”,并且“对象 ID”应该与上一步中的托管标识的对象 ID 值匹配。

选择托管标识的服务主体。

显示“所有应用程序”选项的屏幕截图。

在“概述”中选择“权限”,你将看到添加的 Microsoft Graph 权限 。

显示“权限”窗格的屏幕截图。

调用 Microsoft Graph

ChainedTokenCredentialManagedIdentityCredentialEnvironmentCredential 类用于为你的代码获取令牌凭据以授权对 Microsoft Graph 的请求。 创建 ChainedTokenCredential 类的实例,该类使用应用服务环境中的托管标识或开发环境变量来提取令牌并将其附加到服务客户端。 下面的代码示例获取经过身份验证的令牌凭据,并使用它创建服务客户端对象,该对象将获取组中的用户。

若要查看作为示例应用程序一部分的代码,请参阅 GitHub 上的示例

安装 Microsoft.Identity.Web.GraphServiceClient 客户端库包

使用 .NET 命令行接口 (CLI) 或 Visual Studio 中的包管理器控制台,在项目中安装 Microsoft.GraphMicrosoft.Identity.Web.GraphServiceClient NuGet 包。

.NET CLI

打开一个命令行,并切换到包含项目文件的目录。

运行安装命令。

dotnet add package Microsoft.Identity.Web.GraphServiceClient
dotnet add package Microsoft.Graph

程序包管理器控制台

在 Visual Studio 中打开项目/解决方案,并使用“工具”“NuGet 包管理器”“包管理器控制台”命令打开控制台。

运行安装命令。

Install-Package Microsoft.Identity.Web.GraphServiceClient
Install-Package Microsoft.Graph

示例

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.Extensions.Logging;
using Microsoft.Graph;
using Azure.Identity;

...

public IList<MSGraphUser> Users { get; set; }

public async Task OnGetAsync()
{
    // Create the Graph service client with a ChainedTokenCredential which gets an access
    // token using the available Managed Identity or environment variables if running
    // in development.
    var credential = new ChainedTokenCredential(
        new ManagedIdentityCredential(),
        new EnvironmentCredential());

    string[] scopes = new[] { "https://microsoftgraph.chinacloudapi.cn/.default" };

    var graphServiceClient = new GraphServiceClient(
        credential, scopes);

    List<MSGraphUser> msGraphUsers = new List<MSGraphUser>();
    try
    {
        //var users = await graphServiceClient.Users.Request().GetAsync();
        var users = await graphServiceClient.Users.GetAsync();
        foreach (var u in users.Value)
        {
            MSGraphUser user = new MSGraphUser();
            user.userPrincipalName = u.UserPrincipalName;
            user.displayName = u.DisplayName;
            user.mail = u.Mail;
            user.jobTitle = u.JobTitle;

            msGraphUsers.Add(user);
        }
    }
    catch (Exception ex)
    {
        string msg = ex.Message;
    }

    Users = msGraphUsers;
}

清理资源

如果已完成本教程,并且不再需要 Web 应用或相关资源,请清理创建的资源

后续步骤