When managing Microsoft Entra ID (formerly Azure AD) in hybrid environments, one of the most challenging scenarios IT administrators face is dealing with GUID/ImmutableID mismatches after Active Directory restore operations. This issue often surfaces after VM restores from snapshots or backups, leading to sync errors and user authentication problems.
Understanding the Problem
The ImmutableID is a critical identifier that links on-premises Active Directory users to their corresponding Microsoft Entra ID accounts. When Active Directory VMs are restored from backups or snapshots, the ObjectGUID values may change, causing a mismatch with the stored ImmutableID in Microsoft Entra ID.
Common Symptoms
- Users unable to sync between on-premises AD and Microsoft Entra ID
- Authentication failures for hybrid users
- Duplicate user accounts appearing in Microsoft Entra ID
- Microsoft Entra ID Connect sync errors
Case Study
During a recent engagement at torpedo.pt, we encountered this exact scenario. After a domain controller VM restore, the organization faced widespread sync issues affecting over 500 users. The restore had changed the ObjectGUID values in Active Directory, but the corresponding ImmutableID values in Microsoft Entra ID remained unchanged, creating orphaned accounts.
The client initially attempted to resolve this using the deprecated MSOnline PowerShell module, which is no longer supported and will be retired. This presented an opportunity to implement a modern solution using Microsoft Graph PowerShell.
Modern Solution: Microsoft Graph PowerShell
Prerequisites
Before beginning the remediation process, ensure you have:
- Microsoft Graph PowerShell SDK installed
- Global Administrator or User Administrator privileges
- Microsoft Entra ID Connect temporarily disabled
- Full backup of your current configuration
Step 1: Install Microsoft Graph PowerShell
# Install Microsoft Graph PowerShell SDK
Install-Module Microsoft.Graph -Force -AllowClobber
# Import required modules
Import-Module Microsoft.Graph.Authentication
Import-Module Microsoft.Graph.Users
Import-Module Microsoft.Graph.Identity.DirectoryManagement
Step 2: Connect to Microsoft Graph
# Connect with required permissions
Connect-MgGraph -Scopes "User.ReadWrite.All", "Directory.ReadWrite.All"
# Verify connection
Get-MgContext
Step 3: Identify Affected Users
Create a script to identify users with mismatched ImmutableIDs:
# Get all synchronized users from Microsoft Entra ID
$CloudUsers = Get-MgUser -All -Property Id,DisplayName,UserPrincipalName,OnPremisesImmutableId
# Get all users from on-premises AD
$OnPremUsers = Get-ADUser -Filter * -Properties ObjectGUID,UserPrincipalName
# Compare and identify mismatches
$MismatchedUsers = @()
foreach ($CloudUser in $CloudUsers | Where-Object {$_.OnPremisesImmutableId}) {
$OnPremUser = $OnPremUsers | Where-Object {$_.UserPrincipalName -eq $CloudUser.UserPrincipalName}
if ($OnPremUser) {
$OnPremImmutableId = [System.Convert]::ToBase64String($OnPremUser.ObjectGUID.ToByteArray())
if ($CloudUser.OnPremisesImmutableId -ne $OnPremImmutableId) {
$MismatchedUsers += [PSCustomObject]@{
UserPrincipalName = $CloudUser.UserPrincipalName
CloudImmutableId = $CloudUser.OnPremisesImmutableId
OnPremImmutableId = $OnPremImmutableId
UserId = $CloudUser.Id
}
}
}
}
Write-Host "Found $($MismatchedUsers.Count) users with ImmutableID mismatches"
Step 4: Fix ImmutableID Mismatches
Important: Always test this process with a small group of users first.
# Function to update ImmutableID
function Update-UserImmutableId {
param(
[string]$UserId,
[string]$NewImmutableId,
[string]$UserPrincipalName
)
try {
# Clear the ImmutableID first
Update-MgUser -UserId $UserId -OnPremisesImmutableId $null
Start-Sleep -Seconds 2
# Set the new ImmutableID
Update-MgUser -UserId $UserId -OnPremisesImmutableId $NewImmutableId
Write-Host "Successfully updated ImmutableID for $UserPrincipalName" -ForegroundColor Green
return $true
}
catch {
Write-Warning "Failed to update ImmutableID for $UserPrincipalName : $($_.Exception.Message)"
return $false
}
}
# Update ImmutableIDs for mismatched users
foreach ($User in $MismatchedUsers) {
Write-Host "Processing: $($User.UserPrincipalName)"
$Success = Update-UserImmutableId -UserId $User.UserId -NewImmutableId $User.OnPremImmutableId -UserPrincipalName $User.UserPrincipalName
if ($Success) {
# Verify the update
Start-Sleep -Seconds 1
$UpdatedUser = Get-MgUser -UserId $User.UserId -Property OnPremisesImmutableId
if ($UpdatedUser.OnPremisesImmutableId -eq $User.OnPremImmutableId) {
Write-Host "Verification successful for $($User.UserPrincipalName)" -ForegroundColor Green
}
}
}
Advanced Scenarios
Handling Soft-Deleted Users
Sometimes users may appear as soft-deleted in Microsoft Entra ID:
# Check for soft-deleted users
$DeletedUsers = Get-MgDirectoryDeletedItem -DirectoryObjectId
# Restore soft-deleted users if necessary
foreach ($DeletedUser in $DeletedUsers) {
Restore-MgDirectoryDeletedItem -DirectoryObjectId $DeletedUser.Id
Write-Host "Restored user: $($DeletedUser.DisplayName)"
}
Bulk Processing with Progress Tracking
For large environments, implement progress tracking:
$TotalUsers = $MismatchedUsers.Count
$ProcessedUsers = 0
$SuccessfulUpdates = 0
foreach ($User in $MismatchedUsers) {
$ProcessedUsers++
$PercentComplete = ($ProcessedUsers / $TotalUsers) * 100
Write-Progress -Activity "Updating ImmutableIDs" -Status "Processing $($User.UserPrincipalName)" -PercentComplete $PercentComplete
if (Update-UserImmutableId -UserId $User.UserId -NewImmutableId $User.OnPremImmutableId -UserPrincipalName $User.UserPrincipalName) {
$SuccessfulUpdates++
}
}
Write-Host "\nProcess completed: $SuccessfulUpdates out of $TotalUsers users updated successfully"
Post-Remediation Steps
1. Re-enable Microsoft Entra ID Connect
# On the Microsoft Entra ID Connect server
Start-ADSyncSyncCycle -PolicyType Initial
2. Verify Sync Status
Monitor the synchronization to ensure users are properly matched:
# Check sync status
Get-MgDirectorySynchronization
# Verify user sync status
$VerificationUsers = Get-MgUser -All -Property OnPremisesImmutableId,OnPremisesSyncEnabled | Where-Object {$_.OnPremisesSyncEnabled -eq $true}
Write-Host "Successfully synchronized users: $($VerificationUsers.Count)"
Best Practices and Recommendations
1. Prevention Strategies
- Never restore domain controllers from snapshots in production environments
- Implement proper backup and recovery procedures for domain controllers
- Use Microsoft Entra ID Connect health monitoring
- Regular sync status audits
2. Migration from MSOnline Module
The deprecated MSOnline PowerShell module should be replaced with Microsoft Graph PowerShell:
| MSOnline Command | Microsoft Graph Equivalent |
|---|---|
Get-MsolUser | Get-MgUser |
Set-MsolUser | Update-MgUser |
Connect-MsolService | Connect-MgGraph |
3. Testing and Validation
- Always test scripts in a development environment first
- Process users in small batches initially
- Implement comprehensive logging
- Maintain rollback procedures
Monitoring and Troubleshooting
Common Issues and Resolutions
Issue: “Insufficient privileges” error
Resolution: Ensure your account has the required Graph API permissions
Issue: “User not found” error
Resolution: Check if the user exists and verify the User ID format
Issue: Sync still failing after ImmutableID update
Resolution: Force a full synchronization cycle and check for duplicate accounts
Logging and Auditing
Implement comprehensive logging for audit purposes:
# Create detailed log
$LogPath = "C:\Logs\ImmutableID_Remediation_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
function Write-Log {
param([string]$Message, [string]$Level = "INFO")
$Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss"
$LogEntry = "[$Timestamp] [$Level] $Message"
Add-Content -Path $LogPath -Value $LogEntry
Write-Host $LogEntry
}
Fixing GUID/ImmutableID mismatches in Microsoft Entra ID after Active Directory restores requires a methodical approach and modern tooling. The transition from the deprecated MSOnline PowerShell module to Microsoft Graph PowerShell not only provides better functionality but also ensures long-term supportability.
The torpedo.pt case study demonstrates that with proper planning and execution, even large-scale ImmutableID remediation can be completed successfully. Key success factors include:
- Thorough testing before production implementation
- Comprehensive backup procedures
- Modern tooling (Microsoft Graph PowerShell)
- Proper monitoring and validation
By following these guidelines and using the provided PowerShell scripts, IT administrators can confidently resolve ImmutableID mismatches while maintaining security and compliance standards.
Have you encountered similar ImmutableID issues in your environment? Share your experiences and solutions in the comments below. For more Microsoft Entra ID and PowerShell content, subscribe to our newsletter and follow our latest updates.








Leave a comment