Microsoft Entra ID · PowerShell 7.6
Application permissions granted to apps (Microsoft Graph by default)
Which apps have been granted application permissions (app roles) on Microsoft Graph, such as Mail.Read or User.Read.All, that work without a signed-in user?
Script
#Requires -Modules Microsoft.Graph.Authentication, Microsoft.Graph.Applications
# Application permissions (app roles) granted to apps on one API, Microsoft Graph by default. Read-only.
param(
[string]$ResourceAppId = '00000003-0000-0000-c000-000000000000'
)
Connect-MgGraph -Scopes 'Application.Read.All' -NoWelcome
$resource = Get-MgServicePrincipal -Filter "appId eq '$ResourceAppId'" -Property 'id', 'displayName', 'appRoles' | Select-Object -First 1
if (-not $resource) { throw "No service principal with appId $ResourceAppId in this tenant." }
$roleNames = @{}
foreach ($role in $resource.AppRoles) { $roleNames[$role.Id] = $role.Value }
Get-MgServicePrincipalAppRoleAssignedTo -ServicePrincipalId $resource.Id -All |
Where-Object { $_.PrincipalType -eq 'ServicePrincipal' } |
ForEach-Object {
[pscustomobject]@{
Application = $_.PrincipalDisplayName
Permission = $roleNames[$_.AppRoleId]
Api = $resource.DisplayName
GrantedOn = $_.CreatedDateTime
AppRoleId = $_.AppRoleId
PrincipalId = $_.PrincipalId
}
} |
Sort-Object Application, Permission
Checked automatically against Microsoft's published cmdlet reference. KBY hasn't run it in your tenant; run it in a test environment first.
Reading the output
- Lists app role assignments made to service principals on one resource API. By default that is Microsoft Graph (appId 00000003-0000-0000-c000-000000000000); pass -ResourceAppId to check another API.
- Application permissions apply tenant-wide with no user present, so entries such as Mail.Read, Files.Read.All or Directory.ReadWrite.All deserve a named owner and a reason.
- Delegated permissions (an app acting as a signed-in user) are a different object; the delegated permission grants script covers those.
- Permission is the app role's value. If an assignment refers to a role the API no longer exposes, Permission is empty and the AppRoleId tells you which one it was.
Sources
The Microsoft reference page for every cmdlet the script calls, plus the API and product pages behind each permission and caveat.
Connect-MgGraph (Microsoft.Graph.Authentication)Get-MgServicePrincipal (Microsoft.Graph.Applications)Get-MgServicePrincipalAppRoleAssignedTo (Microsoft.Graph.Applications)List appRoleAssignments granted for a service principal: permissionsappRoleAssignment resource type: principalType, appRoleId, createdDateTimeappRole resource type: id and valueGrant or revoke API permissions programmatically (Microsoft Graph appId and appRoles)Select-Object (Microsoft.PowerShell.Utility)Where-Object (Microsoft.PowerShell.Core)ForEach-Object (Microsoft.PowerShell.Core)Sort-Object (Microsoft.PowerShell.Utility)