Have the following powershell modules installed, functions loaded, and permissions granted to the connection you are going to make to Microsoft Graph and ActiveDirectory
Install these modules in the environment where you will run your powershell session
- Microsoft.Graph
- OGraph
- ActiveDirectory
- ImportExcel
Run the following code in your powershell session to create the function
Function Get-GUIDFromImmutableID {
[cmdletbinding()]
param
(
$ImmutableID
)
[GUID][convert]::frombase64string($ImmutableID)
}
- microsoft graph user.read.all
- Active Directory Read
- IF you are going to remove orphaned Azure AD Accounts
- microsoft graph user.write.all
-
Connect to Active Directory
Import-Module ActiveDirectory
-
Connect to Microsoft Graph
Connect-Graph #actual syntax will depend on your intended connection type / credential
-
Get all the Azure AD Users:
$AzureADUsers = Get-OGUser -All -Property OnPremisesLastSyncDateTime,OnPremisesSyncEnabled,OnPremisesImmutableID
-
Filter for the possibly "orphaned" Azure AD Users:
$Date = (Get-Date).AddDays(-180) #change the -180 to how far back you want to allow for the last sync to have been for the user object # following code filters out users that are not enabled for sync, which have synced recently, and which have an invalid immutableID $PossiblyOrphaned = $AzureADUsers.where({$true -eq $_.OnPremisesSyncEnabled}).where({$_.OnPremisesLastSyncDateTime -lt $Date}).where({-not [string]::isnullorempty($_.OnPremisesImmutableID)})
-
Attempt to Get the AD Users that match these possibly orphaned Azure AD Users
$AdMatches = @( $PossiblyOrphaned.foreach({ $IID = $_.OnPremisesImmutableID $OnPremGuid = $(Get-GUIDFromImmutableID -ImmutableID $IID).guid Get-ADUser -Identity $OnPremGuid -Property Mail -ErrorAction SilentlyContinue | Select-Object -Property SamAccountName,DistinguishedName,UserPrincipalName,Mail,ObjectGUID,Enabled,@{n='ImmutableID';e={$IID}} }) )
-
To make identifying the actual orphaned accounts much faster, build a hashtable of the found AD Users
$FoundADUserHash = @{} #we are just building a hashtable of the found immutableIDs $ADMatches.foreach({$FoundADUserHash.$($_.ImmutableID)=$null})
-
Get the Actual Orphaned AD Users (the ones not found in AD)
$Orphaned = @($PossiblyOrphaned.where({-not $FoundADUserHash.containskey($_.OnPremisesImmutableID)}))
-
Export the list to Excel for review and further action
$Orphaned | Select-Object -property DisplayName,id,UserPrincipalName,Mail,JobTitle,onPremisesImmutableID,onPremisesLastSyncDateTime,onPremisessyncEnabled,@{n='onPremisesObjectGUID';e={Get-GUIDFromImmutableID -ImmutableID $_.onPremisesImmutableID}} | export-excel -Path F:\Reports\LikelyOrphanedAzureADUsers.xlsx -TableName LikelyOrphanedAzureADUsers -TableStyle Medium10 -WorksheetName LikelyOrphanedAADUsers
-
After review and approval, delete the orphaned user objects from AzureAD
- Re-import your list if you removed some user objects after investigation
$Orphaned = Import-Excel -Path [Path to your modified list which still has the id column containing the Azure AD id for the orphaned accounts]
- Delete the User objects from Azure AD
$Orphaned.forEach({Remove-MgUser -UserId $_.id -Confirm:$false -WhatIf}) #take the -WhatIf off when you are ready to actually delete the objects