Skip to content

Instantly share code, notes, and snippets.

@exactmike
Last active August 14, 2023 15:52
Show Gist options
  • Save exactmike/1ddc3d6310faec41abeeced1783c16bf to your computer and use it in GitHub Desktop.
Save exactmike/1ddc3d6310faec41abeeced1783c16bf to your computer and use it in GitHub Desktop.
Find Orphaned Azure AD Users

Requirements

Have the following powershell modules installed, functions loaded, and permissions granted to the connection you are going to make to Microsoft Graph and ActiveDirectory

Modules

Install these modules in the environment where you will run your powershell session

  • Microsoft.Graph
  • OGraph
  • ActiveDirectory
  • ImportExcel

functions

Run the following code in your powershell session to create the function

    Function Get-GUIDFromImmutableID {
        [cmdletbinding()]
        param
        (
            $ImmutableID
        )
        [GUID][convert]::frombase64string($ImmutableID)
    }

permissions

  • microsoft graph user.read.all
  • Active Directory Read
  • IF you are going to remove orphaned Azure AD Accounts
    • microsoft graph user.write.all

Steps

  • 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment