Microsoft Azure – Find AD Graph Applications in Azure AD Tenant?
Last Updated :
31 Mar, 2023
Azure AD Graph is a compliant service that can be used to read and modify azure tenant objects such as users, groups, contacts, and other additional information. In this article, we will be using the PowerShell script to find all the azure AD Graph-related apps in Azure AD Tenant. This PowerShell script will return all the azure applications and azure service principles that currently use the Azure AD Graph.
Purpose of use:
Microsoft Azure is suggesting to Migrate the App from AD Graph API to Microsoft Graph Rest API. Microsoft Graph is very similar to Azure AD Graph but has greater security and additional properties than Azure AD Graph.
Prerequisite:
- Requires -PSEdition Desktop Version on your Windows(Any Version)
- Install PowerShell Az and AzureAD latest modules on your Windows desktop
Implementation:
Step 1: Open the PowerShell on your Windows desktop in azure administrator mode.
Step 2: Create a new file with the name MSAzure-ADGraphApplications.ps1
touch MSAzure-ADGraphApplications.ps1
Step 3: Open the get-Azure-ADGraphApplications.ps1 to code.
code MSAzure-ADGraphApplications.ps1
Step 4. Now paste the script in MSAzure-ADGraphApplications.ps1 file.
[cmdletbinding()]
param()
function Load-Module ($m) {
Write-Progress -Activity "Loading dependencies..."
# If module is imported say that and do nothing
if (Get-Module | Where-Object { $_.Name -eq $m }) {
Write-Verbose "Already imported Module $m."
}
else{
if(Get-Module -ListAvailable | Where-Object { $_.Name -eq $m }){
Import-Module $m
}
else{
if (Find-Module -Name $m | Where-Object { $_.Name -eq $m }) {
Install-Module -Name $m -Force -Scope CurrentUser
Import-Module $m
}
else{
Write-Host "Module $m not imported,
not available and not in online gallery, exiting."
EXIT 1
}
}
}
}
function Get-MSCloudIdConsentGrantList {
$script:ObjectByObjectId = @{}
$script:ObjectByObjectClassId = @{}
function CacheObject($Object) {
if ($Object) {
if (-not $script:ObjectByObjectClassId.ContainsKey($Object.ObjectType)) {
$script:ObjectByObjectClassId[$Object.ObjectType] = @{}
}
$script:ObjectByObjectClassId[$Object.ObjectType][$Object.ObjectId] = $Object
$script:ObjectByObjectId[$Object.ObjectId] = $Object
}
}
function GetObjectByObjectId($ObjectId) {
if (-not $script:ObjectByObjectId.ContainsKey($ObjectId)) {
Write-Verbose ("Querying Azure AD for object '{0}'" -f $ObjectId)
try {
$object = Get-AzureADObjectByObjectId -ObjectId $ObjectId
CacheObject -Object $object
}
catch {
Write-Verbose "Object not found."
}
}
return $script:ObjectByObjectId[$ObjectId]
}
Write-Progress -Activity "Retrieving Service Principal objects. Please wait..."
$servicePrincipals = Get-AzureADServicePrincipal -All $true
$tenantId = (Get-AzureADTenantDetail).ObjectId
$Oauth2PermGrants = @()
$count = 0
foreach ($sp in $servicePrincipals) {
CacheObject -Object $sp
$spPermGrants = Get-AzureADServicePrincipalOAuth2PermissionGrant
-ObjectId $sp.ObjectId -All $true
$Oauth2PermGrants += $spPermGrants
$count++
Write-Progress -Activity "Getting Service Principal Delegate
Permissions..." -Status "$count of $($servicePrincipals.Count)
- $($sp.DisplayName)" -percentComplete (($count / $servicePrincipals.Count) * 100)
if ($sp.AppId -eq "00000002-0000-0000-c000-000000000000") {
#Azure Active Directory Graph API app
$aadGraphSp = $sp
}
}
Write-Progress -Activity "Checking Delegated Permission Grants..."
foreach ($grant in $Oauth2PermGrants) {
if ($grant.ResourceId -eq $aadGraphSp.ObjectId -and $grant.Scope) {
$grant.Scope.Split(" ") | Where-Object { $_ } | ForEach-Object {
$scope = $_
$client = GetObjectByObjectId -ObjectId $grant.ClientId
$isAppProxyApp = $false
if ($client.Tags -contains "WindowsAzureActiveDirectoryOnPremApp") {
$isAppProxyApp = $true
}
if(-not $isAppProxyApp)
{
$ownerUPN = (Get-AzureADServicePrincipalOwner
-ObjectId $client.ObjectId -Top 1).UserPrincipalName
Write-Progress -Activity "Checking Delegate
Permissions - $($client.DisplayName)"
$MicrosoftRegisteredClientApp = @()
if ($client.AppOwnerTenantId -eq "f8cdef31-a31e-4b4a-93e4-5f571e91255a"
-or $client.AppOwnerTenantId -eq "72f988bf-86f1-41af-91ab-2d7cd011db47") {
$MicrosoftRegisteredClientApp = $true
}
else {
$MicrosoftRegisteredClientApp = $false
}
if(-not $MicrosoftRegisteredClientApp) {
$isTenantOwnedApp = $false
if ($client.AppOwnerTenantId -eq $tenantId) {
$isTenantOwnedApp = $true
}
$resource = GetObjectByObjectId -ObjectId $grant.ResourceId
if ($grant.ConsentType -eq "AllPrincipals") {
$simplifiedgranttype = "Delegated-AllPrincipals"
}
elseif ($grant.ConsentType -eq "Principal") {
$simplifiedgranttype = "Delegated-Principal"
}
$global:hasData = $true
New-Object PSObject -Property ([ordered]@{
"ObjectId" = $grant.ClientId
"DisplayName" = $client.DisplayName
"ApplicationId" = $client.AppId
"PermissionType" = $simplifiedgranttype
"Resource" = $resource.DisplayName
"Permission" = $scope
"Owner" = $ownerUPN
"TenantOwned" = $isTenantOwnedApp
})
}
}
}
}
}
Write-Progress -Activity "Fetching Permission Grants of Application..."
$script:ObjectByObjectClassId['ServicePrincipal'].GetEnumerator() | ForEach-Object {
$sp = $_.Value
Write-Progress -Activity "Checking Application Permissions - $($sp.DisplayName)"
Get-AzureADServiceAppRoleAssignedTo -ObjectId $sp.ObjectId -All $true `
| Where-Object { $_.PrincipalType -eq "ServicePrincipal" -and $_.
ResourceId -eq $aadGraphSp.ObjectId } | ForEach-Object {
$assignment = $_
$client = GetObjectByObjectId -ObjectId $assignment.PrincipalId
$isAppProxyApp = $false
if ($client.Tags -contains "WindowsAzureActiveDirectoryOnPremApp") {
$isAppProxyApp = $true
}
if(-not $isAppProxyApp)
{
$ownerUPN = (Get-AzureADServicePrincipalOwner
-ObjectId $client.ObjectId -Top 1).UserPrincipalName
$MicrosoftRegisteredClientApp = @()
if ($client.AppOwnerTenantId -eq "f8cdef31-a31e-4b4a-
93e4-5f571e91255a" -or $client.AppOwnerTenantId
-eq "72f988bf-86f1-41af-91ab-2d7cd011db47") {
$MicrosoftRegisteredClientApp = $true
}
else {
$MicrosoftRegisteredClientApp = $false
}
if(-not $MicrosoftRegisteredClientApp) {
$isTenantOwnedApp = $false
if ($client.AppOwnerTenantId -eq $tenantId) {
$isTenantOwnedApp = $true
}
$resource = GetObjectByObjectId -ObjectId $assignment.ResourceId
$appRole = $resource.AppRoles | Where-Object { $_.Id -eq $assignment.Id }
$global:hasData = $true
New-Object PSObject -Property ([ordered]@{
"ObjectId" = $assignment.PrincipalId
"DisplayName" = $client.DisplayName
"ApplicationId" = $client.AppId
"PermissionType" = "Application"
"Resource" = $resource.DisplayName
"Permission" = $appRole.Value
"Owner" = $ownerUPN
"TenantOwned" = $isTenantOwnedApp
})
}
}
}
}
}
Load-Module "AzureAD"
$global:hasData = $false
Get-MSCloudIdConsentGrantList
if($global:hasData -eq $false){
Write-Warning "There doesn't exist any apps using Azure AD Graph"
}
Note: No code changes are required to perform this activity.
Step 4. Save the get-Azure-ADGraphApplications.ps1 file and run the file using the following commands
Run this Connect-AzureAD command to connect Azure Active Directory
cmd: Connect-AzureAD
Run the below run command after the Connect-AzureAD command.
cmd: ./MSAzure-ADGraphApplications.ps1 |
Export-Csv .\ADGraphApps.csv
output returns all the list of azure applications and azure service principles that currently use Azure AD Graph in a .csv file format.
Sample CSV File Output:
Like Article
Suggest improvement
Share your thoughts in the comments
Please Login to comment...