对已配置权限的限制进行故障排除

应用程序对象上的 RequiredResourceAccess 集合 (RRA) 包含应用为其默认同意请求所需的所有已配置 API 权限。 此集合具有各种限制,具体取决于应用支持的标识类型。 有关支持的帐户类型限制的详细信息,请参阅支持的帐户类型的验证差异

最大权限限制已于 2022 年 5 月更新,因此某些应用在其 RRA 中拥有的权限可能比现在允许的更多。 此外,在配置权限后更改其支持的帐户类型的应用可能会超出新设置的限制。 当应用超过配置的权限限制时,在 RequiredResourceAccess 集合中的权限数量恢复到限制以下之前,不能添加新的权限。

本文档提供了解决此问题的其他信息和故障排除步骤。

确定应用何时超出 RequiredResourceAccess 限制

通常,权限超过 400 个的所有应用程序都超过了配置限制。 尝试在 Azure 门户中添加更多权限时,超出权限限制的应用将收到以下错误:

Failed to save permissions for <AppName>. This configuration exceeds the global application object limit. Remove some items and retry your request.

解决步骤

如果不再需要应用程序,则应考虑的第一个选项是完全删除应用注册。 (可以还原最近删除的应用程序,以防不久后发现仍需要使用。)

如果仍需要该应用程序或不确定,以下步骤将帮助你解决此问题:

  1. 删除重复的权限。 在某些情况下,同一权限会多次列出。 查看所需的权限,并删除列出两次或更多次的权限。 请参阅本文其他资源部分中的相关 PowerShell 脚本。
  2. 删除未使用的权限。 查看应用程序所需的权限,将其与应用程序或服务执行的操作进行比较。 删除在应用注册中配置但应用程序或服务不需要的权限。 有关如何查看权限的详细信息,请参阅查看应用程序权限
  3. 删除冗余权限。 在许多 API(包括 Microsoft Graph)中,当包含其他更高特权的权限时,便不再需要某些权限。 例如,当应用程序具有 User.ReadWrite.All(读取、创建和更新所有用户)时,就不需要 Microsoft Graph 权限 User.Read.All(读取所有用户)。 若要详细了解 Microsoft Graph 权限,请参阅 Microsoft Graph 权限参考

常见问题解答 (FAQ)

为什么 Microsoft 修改了总权限限制?

此限制很重要,原因有以下两点:

  • 帮助防止为应用配置的所需权限超过同意期间授予的权限数量。
  • 将应用注册的总大小保持在基础存储平台的稳定性和性能所需的限制范围内。

如果我不执行任何操作,会发生什么情况?

如果应用超出总权限限制,你将无法再增加应用程序所需权限的总数。

限制是否会更改可以向应用程序授予的权限数量?

否。 此限制仅影响在应用注册时配置的请求 API 权限列表。 这与已授予应用程序的权限列表不同。

即使未列在所需 API 权限列表中,应用程序仍可以动态请求委托的权限。 还可以使用 Microsoft Graph API 或 Microsoft Graph PowerShell 直接授予委托的权限和应用角色(应用程序权限)。

是否可以提高应用程序的限制?

不,不能针对单个应用程序或组织提高限制。

所需 API 权限列表是否有其他限制?

是的。 限制可能因应用支持的帐户类型而异。 请参阅按支持的帐户类型列出的验证差异了解详细信息。

其他资源

使用以下 PowerShell 脚本从应用注册中删除任何重复的权限。

<#
.SYNOPSIS
    Remove duplicate required API permissions from an app registration's required API permission list.
.DESCRIPTION
    This script ensures all API permissions listed in a Microsoft identity platform's app registration are only listed once,
    removing any duplicates it finds. This script requires the Microsoft.Graph.Applications PowerShell module.
.EXAMPLE
     Get-MgApplication -Filter "appId eq '00001111-aaaa-2222-bbbb-3333cccc4444'" | .\Deduplicate_RequiredResourceAccess.ps1"
.EXAMPLE
     $apps = Get-MgApplication -Filter "startswith(displayName,'Test_app')"
     $apps | .\Deduplicate_RequiredResourceAccess.ps1
#>

#Requires -Modules Microsoft.Graph.Applications

[CmdletBinding()]
param(
    [Parameter(ValueFromPipeline = $true)]
    $App
)

begin {
    $context = Get-MgContext
    if (-not $context) {
        throw ("You must connect to Microsoft Graph PowerShell first, with sufficient permissions " +
               "to manage Application objects. For example: Connect-MgGraph -Environment China -ClientId 'YOUR_CLIENT_ID' -TenantId 'YOUR_TENANT_ID' -Scopes ""Application.ReadWrite.All""")
    }
}

process {
    
    # Build the unique list of required API permissions for each required API
    $originalCount = 0
    $tempRras = @{}
    foreach ($rra in $App.RequiredResourceAccess) {
        if (-not $tempRras.ContainsKey($rra.ResourceAppId)) {
            $tempRras[$rra.ResourceAppId] = @{"Scope" = @{}; "Role" = @{}};
        }
        foreach ($ra in $rra.ResourceAccess) {
            if ($tempRras[$rra.ResourceAppId][$ra.Type].ContainsKey($ra.Id)) {
                # Skip duplicate required API permission
            } else {
                $tempRras[$rra.ResourceAppId][$ra.Type][$ra.Id] = $true
            }
            $originalCount++
        }
    }
    
    # Now that we have the unique set of required API permissions, iterate over all the keys to build the final requiredResourceAccess structure
    $deduplicatedCount = 0
    $finalRras = @($tempRras.Keys) | ForEach-Object {
        $resourceAppId = $_
        @{
            "resourceAppId" = $resourceAppId
            "resourceAccess" = @(@("Scope", "Role") | ForEach-Object { 
                $type = $_
                $tempRras[$resourceAppId][$type].Keys | ForEach-Object { 
                    $deduplicatedCount++;
                    @{"type" = $type; "id" = $_}
                }
            })
        }
    }
    
    $countDifference = $originalCount - $deduplicatedCount
    if ($countDifference) {
        Write-Host "Removing $($countDifference) duplicate entries in RequiredResourceAccess for '$($App.DisplayName)' (AppId: $($App.AppId))"
        Update-MgApplication -ApplicationId $App.Id -RequiredResourceAccess $finalRras
    } else {
        Write-Host "No updates necessary for '$($App.DisplayName)' (AppId: $($App.AppId))"
    }
}

了解详细信息