通过使用 PowerShell 代表单个用户授予同意

本文介绍如何使用 PowerShell 代表单个用户授予同意。

当用户为自己授予同意时,以下事件会更频繁地发生:

  1. 为客户端应用程序创建一个服务主体(如果不存在)。 服务主体是 Microsoft Entra 租户中的应用程序或服务的实例。 向应用或服务授予的访问权限与此服务主体对象相关联。

  2. 对于应用程序需要访问的每个 API,将为应用程序对该 API 所需的权限创建委托的权限授予。 将代表用户授予该访问权限。 委托的权限授予将授权应用程序在用户登录时代表该用户访问 API。

  3. 为用户分配客户端应用程序。 为用户分配应用程序可确保在我的应用门户中为该用户列出此应用程序。 用户可以从“我的应用”门户查看和撤销代表其授予的访问权限。

先决条件

若要代表一个用户向应用程序授予同意,需要:

  • 具有特权角色管理员、应用程序管理员或云应用程序管理员身份的用户帐户

在开始之前,请从 Microsoft Entra 管理中心记录以下详细信息:

  • 要授予同意的应用的应用 ID。 在本文中,我们将其称为“客户端应用程序”。
  • 客户端应用程序所需的 API 权限。 找到 API 的应用 ID 以及权限 ID 或声明值。
  • 代表被授予访问权限的用户的用户名或对象 ID。

对于此示例,我们使用 Microsoft Graph PowerShell 来代表单个用户授予同意。 客户端应用程序是 Microsoft Graph 浏览器,我们授予对 Microsoft Graph API 的访问权限。

要使用 Microsoft Graph PowerShell 代表一个用户向应用程序授予同意,需要至少以云应用程序管理员身份登录。

# The app for which consent is being granted. In this example, we're granting access
# to Microsoft Graph Explorer, an application published by Microsoft.
$clientAppId = "de8bc8b5-d9f9-48b1-a8ad-b748da725064" # Microsoft Graph Explorer

# The API to which access will be granted. Microsoft Graph Explorer makes API 
# requests to the Microsoft Graph API, so we'll use that here.
$resourceAppId = "00000003-0000-0000-c000-000000000000" # Microsoft Graph API

# The permissions to grant. Here we're including "openid", "profile", "User.Read"
# and "offline_access" (for basic sign-in), as well as "User.ReadBasic.All" (for 
# reading other users' basic profile).
$permissions = @("openid", "profile", "offline_access", "User.Read", "User.ReadBasic.All")

# The user on behalf of whom access will be granted. The app will be able to access 
# the API on behalf of this user.
$userUpnOrId = "user@example.com"

# Step 0. Connect to Microsoft Graph PowerShell. We need User.ReadBasic.All to get
#    users' IDs, Application.ReadWrite.All to list and create service principals, 
#    DelegatedPermissionGrant.ReadWrite.All to create delegated permission grants, 
#    and AppRoleAssignment.ReadWrite.All to assign an app role.
#    WARNING: These are high-privilege permissions!
Connect-MgGraph -Scopes ("User.ReadBasic.All Application.ReadWrite.All " `
                        + "DelegatedPermissionGrant.ReadWrite.All " `
                        + "AppRoleAssignment.ReadWrite.All")

# Step 1. Check if a service principal exists for the client application. 
#     If one doesn't exist, create it.
$clientSp = Get-MgServicePrincipal -Filter "appId eq '$($clientAppId)'"
if (-not $clientSp) {
   $clientSp = New-MgServicePrincipal -AppId $clientAppId
}

# Step 2. Create a delegated permission that grants the client app access to the
#     API, on behalf of the user. (This example assumes that an existing delegated 
#     permission grant does not already exist, in which case it would be necessary 
#     to update the existing grant, rather than create a new one.)
$user = Get-MgUser -UserId $userUpnOrId
$resourceSp = Get-MgServicePrincipal -Filter "appId eq '$($resourceAppId)'"
$scopeToGrant = $permissions -join " "
$grant = New-MgOauth2PermissionGrant -ResourceId $resourceSp.Id `
                                     -Scope $scopeToGrant `
                                     -ClientId $clientSp.Id `
                                     -ConsentType "Principal" `
                                     -PrincipalId $user.Id

# Step 3. Assign the app to the user. This ensures that the user can sign in if assignment
#     is required, and ensures that the app shows up under the user's My Apps portal.
if ($clientSp.AppRoles | ? { $_.AllowedMemberTypes -contains "User" }) {
    Write-Warning ("A default app role assignment cannot be created because the " `
                 + "client application exposes user-assignable app roles. You must " `
                 + "assign the user a specific app role for the app to be listed " `
                 + "in the user's My Apps portal.")
} else {
    # The app role ID 00000000-0000-0000-0000-000000000000 is the default app role
    # indicating that the app is assigned to the user, but not for any specific 
    # app role.
    $assignment = New-MgServicePrincipalAppRoleAssignedTo `
          -ServicePrincipalId $clientSp.Id `
          -ResourceId $clientSp.Id `
          -PrincipalId $user.Id `
          -AppRoleId "00000000-0000-0000-0000-000000000000"
}

要使用 Microsoft Graph API 代表一个用户向应用程序授予同意,至少需要以云应用程序管理员身份登录 Graph 浏览器

你需要同意以下权限:

Application.ReadWrite.AllDirectory.ReadWrite.AllDelegatedPermissionGrant.ReadWrite.All

在以下示例中,你代表单一用户向客户端企业应用程序授予由某个资源 API 定义的委托的权限。

在此示例中,资源企业应用程序是对象 ID aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb 的 Microsoft Graph。 Microsoft Graph 定义委托的权限、User.Read.AllGroup.Read.All。 consentType 为 Principal,表示你代表租户中的单一用户表明同意。 客户端企业应用程序的对象 ID 为 aaaaaaaa-0000-1111-2222-bbbbbbbbbbbb。 用户的 principalId 为 aaaaaaaa-bbbb-cccc-1111-222222222222

注意

请注意! 以编程方式授予的权限不需要评审或确认。 它们会立即生效。

  1. 检索由你的租户应用程序中的 Microsoft Graph(资源应用程序)定义的所有委托权限。 确定想要授予客户端应用程序的委托的权限。 在此示例中,委托的权限为 User.Read.AllGroup.Read.All

    GET https://graph.microsoft.com/v1.0/servicePrincipals?$filter=displayName eq 'Microsoft Graph'&$select=id,displayName,appId,oauth2PermissionScopes
    
  2. 通过运行以下请求以代表用户向客户端企业应用程序授予委托的权限。

    POST https://graph.microsoft.com/v1.0/oauth2PermissionGrants
    
    Request body
    {
       "clientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
       "consentType": "Principal",
       "resourceId": "a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1",
       "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
       "scope": "User.Read.All Group.Read.All"
    }
    
  3. 通过运行以下请求确认你已授予用户同意。

    GET https://graph.microsoft.com/v1.0/oauth2PermissionGrants?$filter=clientId eq '00001111-aaaa-2222-bbbb-3333cccc4444' and consentType eq 'Principal'
    
  4. 将应用分配给用户。 此分配可确保用户能够登录(如果需要分配),并确保可通过用户的“我的应用”门户来使用该应用。 在以下示例中,resourceId 表示要将用户分配到的客户端应用。 为用户分配的默认应用角色为 00000000-0000-0000-0000-000000000000

        POST /servicePrincipals/resource-servicePrincipal-id/appRoleAssignedTo
    
        {
        "principalId": "aaaaaaaa-bbbb-cccc-1111-222222222222",
        "resourceId": "a0a0a0a0-bbbb-cccc-dddd-e1e1e1e1e1e1",
        "appRoleId": "00000000-0000-0000-0000-000000000000"
        }
    

后续步骤