To find applications with privileged roles in Azure, list each subscription's role assignments, keep those made to service principals, and keep the roles that can manage everything or grant access: Owner, Contributor, User Access Administrator and Role Based Access Control Administrator. Managed identities are service principals too, so both appear. Check each row's scope, because a role at a management group reaches every subscription below it.
| Method | Best fit |
|---|---|
| PowerShell | A CSV of every privileged role held by an app or managed identity across your enabled subscriptions. |
| Admin centre | A look at 1 subscription's privileged assignments, or at 1 managed identity's roles. |
| Altivane | Recommended for regular access reviews, with apps listed beside guests, direct assignments and deleted identities. |
Before you start
Use an account that can read role assignments at the scopes you want to check, such as one with the built-in Reader role, and that can read service principals in the directory. Without directory access, PowerShell marks the principal type Unknown and the script leaves the assignment out. The script looks up each app's type through Microsoft Graph with the same Azure sign-in. Microsoft lists no separate licence for reading assignments.
The examples count the same 4 roles Altivane marks as privileged. Microsoft's list of privileged administrator roles also includes Reservations Administrator; add it to $roles if you want it. Custom roles aren't counted, and neither are Microsoft Entra roles or the Microsoft Graph permissions an app holds. The examples read and export, and change nothing. The script's finally block disconnects the account and clears its saved Azure contexts.
Option 1
Find applications with privileged roles with PowerShell
Install the modules once. The script reads every role assignment in each enabled subscription, keeps the privileged ones held by service principals, looks up each one's type once and saves 1 row for each assignment.
Install-Module -Name Az.Accounts, Az.Resources -Repository PSGallery -Scope CurrentUser$ErrorActionPreference = 'Stop'
$roles = @(
'Owner'
'Contributor'
'User Access Administrator'
'Role Based Access Control Administrator'
)
Connect-AzAccount -ErrorAction Stop
try {
$subscriptions = @(Get-AzSubscription | Where-Object State -eq 'Enabled')
if ($subscriptions.Count -eq 0) {
Write-Output 'No enabled subscriptions are available to this account.'
return
}
$found = @{}
foreach ($sub in $subscriptions) {
Set-AzContext -Subscription $sub.Id -Tenant $sub.TenantId -Scope Process | Out-Null
Get-AzRoleAssignment | Where-Object ObjectType -eq 'ServicePrincipal' |
Where-Object { $roles -contains $_.RoleDefinitionName } |
ForEach-Object { $found[$_.RoleAssignmentId] = $_ }
}
$kind = @{}
foreach ($id in @($found.Values | ForEach-Object ObjectId | Sort-Object -Unique)) {
$sp = Get-AzADServicePrincipal -ObjectId $id -Select 'ServicePrincipalType' -AppendSelected
$kind[$id] = $sp.ServicePrincipalType
}
$rows = @($found.Values | Sort-Object RoleDefinitionName, DisplayName | ForEach-Object {
[pscustomobject]@{
DisplayName = $_.DisplayName
Type = $kind[$_.ObjectId]
Role = $_.RoleDefinitionName
Scope = $_.Scope
ObjectId = $_.ObjectId
AssignmentId = $_.RoleAssignmentId
}
})
if ($rows.Count -eq 0) {
Write-Output 'No app or managed identity holds a privileged role.'
} else {
$rows | Export-Csv -Path './privileged-apps.csv' -NoTypeInformation -Encoding utf8
Write-Output "$($rows.Count) privileged app assignments saved to privileged-apps.csv."
}
} finally {
Disconnect-AzAccount | Out-Null
}The CSV holds the app's name, its type, the role, the scope, the object ID and the assignment ID. Type is Application for an app registration, ManagedIdentity for a managed identity and Legacy for an app made before app registrations. An assignment above a subscription is read from every subscription it reaches, so the script keeps each assignment ID once. To see every role apps hold, remove the second Where-Object line.
See every role 1 app holds
Reconnect, find the app's or managed identity's object ID by its name, then read its assignments in the current subscription.
# Run while connected to Azure. Replace the example name and object ID.
Get-AzADServicePrincipal -DisplayNameBeginsWith 'Contoso' | Select-Object DisplayName, Id
Get-AzRoleAssignment -ObjectId '00000000-0000-0000-0000-000000000000' |
Select-Object RoleDefinitionName, ScopeOption 2
Review privileged app roles in the Azure portal
- Sign in to the Azure portal with an account that can read the subscription's role assignments.
- Choose All services > Subscriptions, then select the subscription.
- Choose Access control (IAM) > Role assignments, then Privileged to list the privileged administrator role assignments at this scope.
- Read each row's type to pick out the apps and managed identities, and its scope: (Inherited) means the role was given at a scope above.
- To check 1 managed identity, open it and choose Azure role assignments; for a system-assigned one, open its resource and choose Identity first.
Microsoft's Privileged tab also counts Reservations Administrator. This method suits 1 subscription at a time; for every subscription in 1 file, use PowerShell or Altivane.
Option 3 ยท Recommended for regular access reviews
Find privileged applications with Altivane
- Open Altivane and choose the tenant.
- Run the Azure Access to Review report.
- Open the Excel workbook and find the Applications with privileged sheet: each service principal and managed identity holding Owner, Contributor, User Access Administrator or Role Based Access Control Administrator, with the role, the scope, what it is on and the subscription.
- Read Principal type to tell a service principal from a managed identity, and Inherited for roles given at a management group or the root.
The report covers every subscription where you gave Altivane the Reader role, widest scope first, with guests, direct assignments and deleted identities in the same workbook. A custom role isn't counted, whatever it allows. The Azure Access scorecard report counts applications with a privileged role for the tenant's Word report.
Contact usCommon questions
What's the difference between an application and a managed identity?
Both are service principals. An application's service principal stands for an app registration, possibly in another tenant, whose secrets and certificates someone has to manage. A managed identity stands for an Azure resource, has no app registration, and Azure handles its credentials.
Can an app with Contributor give itself more access?
Not through Azure roles. Contributor manages every resource but can't assign roles; Owner, User Access Administrator and Role Based Access Control Administrator can. Microsoft recommends a job function role or a narrower scope where one will do.
Does this cover the Microsoft Graph permissions an app holds?
No. Azure roles control Azure resources, while API permissions such as Directory. are granted in Microsoft Entra ID. See how to review app permissions in Microsoft Entra ID.
Microsoft references
Technical references checked on 7 November 2026. The example scripts have been reviewed and syntax checked; they have not been run against a live tenant.
- Install-Module cmdlet reference
- Connect-AzAccount cmdlet reference
- Set-AzContext cmdlet reference
- Get-AzRoleAssignment cmdlet reference
- Get-AzADServicePrincipal cmdlet reference
- Disconnect-AzAccount cmdlet reference
- List Azure role assignments using Azure PowerShell
- List Azure role assignments using the Azure portal
- Privileged administrator roles in Azure RBAC
- Best practices for Azure RBAC
- servicePrincipal properties
- Application and service principal objects in Microsoft Entra ID