Have created a custom PowerShell script to export all of my azure registered apps API application permissions
and delegated permissions
. Some of my apps have either API permissions
of Type
equal to delegated
or application
. I followed the step by step guide answered in this question Similar question. It was shown for only single app, in my case its multiple apps.
What is working and not working
The script have created is able to export the application permissions assigned to any app registration
, but unable to export delegated permissions
. The script returns without errors but I don’t get the csv for delegated permissions
created and populated with apps that have delegated permissions including the permissions information.
I tried to separately export delegated permissions
only, but still the same issue, the csv is not created with the data.
My main goal is to be able to retrieve and export into a csv file all API permissions(both application permissions
and delegated permissions
) assigned to all app registrations I’m using Azure-AD
module.
Below is the script.
# Add your azure ad global administrator password here
$password_ = ""
$password = ConvertTo-SecureString $password_ -AsPlainText -Force
# Add your azure ad global administrator login UPN
$upn = ""
$export_application_permission = "C:tempapplication_perms.csv"
$export_delegated_permission = "C:tempdelegated_perms.csv"
# Automated login to azure ad
$AppCredential = New-Object System.Management.Automation.PSCredential($upn, $password)
Connect-azureAD -Credential $AppCredential
$apps = Get-AzureADApplication -All $true
foreach ($app in $apps){
$perms = $app.requiredResourceAccess
foreach($perm in $perms){
# Grab all the ResourceAppId from requiredResourceAccess array
$res_app_id = $perm.ResourceAppId
foreach($res_access in $perm.ResourceAccess){
# Check if the resourceAccess Type is Role, which means its application permissions
if($res_access.Type -eq "Role"){
# Grab the resource id
$res_ac = $res_access.Id
# Calling azure-AD module
Connect-azureAD -Credential $AppCredential
# Grab all applications assigned application permissions only
$sps = Get-AzureADServicePrincipal -All $true | Where-Object {$_.AppId -eq $res_app_id}
foreach($sp in $sps){
# Grab application permissions details now
$roles = $sp.AppRoles | Where-Object {$_.Id -eq $res_ac}
foreach($rol in $roles.value){
$record = New-Object PSObject
$record | Add-Member NoteProperty -Name "Application Display Name" -Value $app.displayName
$record | Add-Member NoteProperty -Name "Permission Type" -Value $res_access.Type
$record | Add-Member NoteProperty -Name "Permission Value" -Value $rol
$record | Export-CSV $export_application_permission -NoTypeInformation -Append
}
}
# Check if the resourceAccess Type is Scope, which means its delegated permissions
}elseif ($res_access.Type -eq "Scope") {
<# Action when this condition is true #>
$res_ac = $res_access.Id
Connect-azureAD -Credential $AppCredential
$sps = Get-AzureADServicePrincipal -All $true | Where-Object {$_.AppId -eq $res_app_id}
foreach($sp in $sps){
# Grab delegated permissions details now
$delegated_perms = $sp.oauth2PermissionScopes | Where-Object {$_.Id -eq $res_ac}
foreach($rol in $delegated_perms.value){
$record = New-Object PSObject
$record | Add-Member NoteProperty -Name "Application Display Name" -Value $app.displayName
$record | Add-Member NoteProperty -Name "Permission Type" -Value $res_access.Type
$record | Add-Member NoteProperty -Name "Permission Value" -Value $rol
$record | Export-CSV $export_delegated_permission -NoTypeInformation -Append
}
}
} else {
Write-host "Retreating........."
}
}
}
}
The csv file for application permissions
outputs well as shown below.
I’m expecting similar output for all apps with delegated permissions
What i’m i doing wrong or missing?
2
Answers
Here is how I would get all the application permissions / delegated permissions for all apps while tracking ownership context.
This will produce something like your sample CSV output.
Code
Caveat
Checking just for the permission value (eg:
User.Read.All
) can be misleading as a custom app that also expose a permission with the same name would result in a situation where you get the permissions name, but you don’t know which API is behind that permission (eg: Is it graph, a custom app, another Microsoft API that share some of the permissions name, etc…)A couple of notes regarding your original code
There is a couple of inefficiencies in your original sample.
Connect-AzureAd
. you only need to connect once before entering the loop and not at multiple points like you do.Get-AzureADServicePrincipal
can be called once before the loop at the same time you get all your azure AD apps. In the loops, you just select what you need from the initial results instead of calling the cmdlet again and again.Export-CSV -Append
. I would discourage the use of this and rather use it after the loop so instead of accessing the file dozen, hundred or thgousands times, you access it once.Add-member
Line 65 needs to say $sp.Oauth2Permissions:
You have: