Get-MgAllAppsByPermission.ps1
<#PSScriptInfo
.VERSION 0.4 .GUID 84a7dc33-b92a-4911-a0a3-f319bb65a059 .AUTHOR Daniel Bradley .TAGS Microsoft Graph PowerShell Application Permissions .RELEASENOTES [Version 0.0.2] - Initial Release. [Version 0.0.3] - Fixed dependant module install. [Version 0.0.4] - Add ScopeType and orderd results. #> <# .DESCRIPTION Finds all delegated and application permissions for applications in Entra by permission scope. .SYNOPSIS Loops through all applications and filters for the defined permissions. .EXAMPLE Get-MgAllAppsByPermission -Scope Mail.Send #> [CmdletBinding()] param ( [switch]$Version, [string]$Scope ) # Script information $CurrentVersion = '0.4' if ($Version.IsPresent) { $CurrentVersion exit 0 } #-------------Dependencies-------------# $module = Import-Module microsoft.graph.authentication -PassThru -ErrorAction Ignore if (-not $module) { Write-Host "Installing module microsoft.graph.authentication" -ForegroundColor Yellow Install-Module microsoft.graph.authentication -Scope CurrentUser -Force } Import-Module microsoft.graph.authentication $module = Import-Module microsoft.graph.applications -PassThru -ErrorAction Ignore if (-not $module) { Write-Host "Installing module microsoft.graph.applications" -ForegroundColor Yellow Install-Module microsoft.graph.applications -Scope CurrentUser -Force } Import-Module microsoft.graph.applications $module = Import-Module Microsoft.Graph.Identity.SignIns -PassThru -ErrorAction Ignore if (-not $module) { Write-Host "Installing module microsoft.graph.Identity.SignIns" -ForegroundColor Yellow Install-Module Microsoft.Graph.Identity.SignIns -Scope CurrentUser -Force } Import-Module Microsoft.Graph.Identity.SignIns #-------------End Dependencies-------------# #----------------Functions----------------# function Get-AllAppsByPermission { <# .SYNOPSIS Retrieves all apps in Microsoft Entra by defined permission. .DESCRIPTION This function queries both delegated permissions and application (app roles) permissions on applications in Microsoft Entra. Then filters locally for only those with the defined permission. .EXAMPLE Get-AllAppsByPermission -Scope Mail.Send This example will find all applications with Mail.Send permission consented. .NOTES Credit to Luca Spolidoro @ Microsoft for sharing some core functionality of this script #> [CmdletBinding()] Param( [String]$Permission = "Mail.Send" ) #Check current context If((Get-MgContext).Scopes -notcontains "Application.Read.All"){ Write-host "Connecting to Microsoft Graph..." Connect-MgGraph -Scopes Application.Read.All, DelegatedPermissionGrant.Read.All } #The the Graph Service Principal ID $graphSp = Get-MgServicePrincipalByAppId -AppId "00000003-0000-0000-c000-000000000000" -Property "id,appRoles" #Get all OAuth2 delegated Graph permissions for all apps $delegatedPermissions = Get-MgOauth2PermissionGrant -All -Top 999 -CountVariable CountVar -Property "clientId,scope" -Filter "ConsentType eq 'AllPrincipals' and resourceId eq '$($graphSp.Id)'" -Headers @{ 'ConsistencyLevel' = 'Eventual' } | Select-Object @{Name='ServicePrincipalId';Expression={$_.ClientId}}, @{Name='ScopeType';Expression={"Delegated"}}, @{Name='Scope'; Expression={$_.Scope -split ' ' -ne '' }} #Get all possible available app roles $graphAppRoles = $graphSp | Select-Object -ExpandProperty AppRoles | Select-Object Id, Value | Group-Object -Property Id -AsHashTable #Get all app role assignments for all apps $spRoleAssignments = Get-MgServicePrincipal -All -PageSize 999 -ExpandProperty "appRoleAssignments" -Property "id,appId,displayName" | Where-Object { ($_.AppRoleAssignments | Where-Object { $_.ResourceId -eq $graphSp.Id }).Count -gt 0 } | Select-Object Id, AppId, DisplayName, @{Name="AppRoleId"; Expression={ ($_.AppRoleAssignments).AppRoleId }} #Expand permissions for all app role assignments $appPermissions = $spRoleAssignments | ForEach-Object { [PSCustomObject]@{ ServicePrincipalId = $_.Id; ScopeType="Application"; Scope = @($graphAppRoles[$_.AppRoleId].Value)}} #Filter all permissions by selected permission $filteredPermissions = $delegatedPermissions + $appPermissions | Where-Object Scope -CEQ $Permission #Build a filter collection of AppIds from the above $filterString = "id in('" + (($filteredPermissions | Select-Object -ExpandProperty ServicePrincipalId) -join "','") + "')" #Work backwards and find all apps by app ID from the permissions list above. $filteredAppsWithName = Get-MgServicePrincipal -Filter $filterString -Select "id,appId,displayName" | Select-Object Id, AppId, DisplayName -ErrorAction SilentlyContinue $Report = [System.Collections.Generic.List[Object]]::new() ForEach ($app in $filteredAppsWithName){ $obj = [PSCustomObject][ordered]@{ "DisplayName" = $app.DisplayName "AppId" = $app.AppId "ID" = $app.Id "ScopeType" = $filteredPermissions | Where {$_.ServicePrincipalId -eq $app.Id} | Select -ExpandProperty ScopeType } $report.Add($obj) } $Report | Sort -Descending ScopeType Write-Host "Found $($Report.count) apps with permission: $Permission `n" -ForegroundColor Cyan $return } #----------------End Functions----------------# Get-AllAppsByPermission -Permission $Scope |