Open In App

Microsoft Azure – Find AD Graph Applications in Azure AD Tenant?

Last Updated : 31 Mar, 2023
Improve
Improve
Like Article
Like
Save
Share
Report

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
powershell

 

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
commands

 

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:

output

 



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads