PowerShell☁️ Microsoft 365IntermediateRun as Admin

PowerShell Script to Update Immutable ID for Microsoft 365 Users

This PowerShell script updates the Immutable ID (onPremisesImmutableId) for Microsoft 365 users based on their Active Directory objectGUID. It enables proper hard-matching between on-premises AD and Entra ID, resolving common sync errors during Entra Connect deployments.

2views

When synchronizing Active Directory with Microsoft 365 using Entra Connect, users may encounter sync errors related to attribute conflicts or soft-match failures. These issues typically occur when cloud-only users were created before directory synchronization was enabled.

This Anavem PowerShell script automates the conversion of an AD user's objectGUID to a Base64-encoded Immutable ID and applies it to the corresponding Microsoft 365 account, enabling proper hard-matching on the next sync cycle.

Requirements

PowerShell Modules

# Install Microsoft Graph module
Install-Module Microsoft.Graph.Users -Scope CurrentUser

# Install RSAT for ActiveDirectory module (Windows 10/11)
Add-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools~~~~0.0.1.0

# Install RSAT for ActiveDirectory module (Windows Server)
Install-WindowsFeature RSAT-AD-PowerShell

Permissions

  • User Administrator or Global Administrator role in Microsoft Entra ID
  • Read access to Active Directory
  • Must be run from a machine with AD connectivity

Post-Execution Steps

After updating the Immutable ID, trigger a sync cycle in Entra Connect:

# Delta Sync (recommended)
Start-ADSyncSyncCycle -PolicyType Delta

# Full Sync (if delta fails)
Start-ADSyncSyncCycle -PolicyType Initial

Manual GUID Conversion

To manually convert an objectGUID to Immutable ID:

$guid = (Get-ADUser -Identity "username").ObjectGUID
$immutableId = [System.Convert]::ToBase64String($guid.ToByteArray())
Write-Host $immutableId

What This Script Does

The script performs the following operations:

  • Retrieves the objectGUID from on-premises Active Directory
  • Converts the GUID to Base64 format (Immutable ID)
  • Updates the onPremisesImmutableId attribute in Microsoft Entra ID
  • Verifies the update was successful
  • Optionally clears the Immutable ID for soft-match scenarios

Common Sync Errors This Script Fixes

Unable to update this object because the following attributes associated 
with this object have values that may already be associated with another 
object in your local directory services: [ShadowAccountUpn user@domain.com;]
InvalidSoftMatch - ObjectId conflict detected
AttributeConflictName: SipProxyAddress

How to Run the Script

Manual Execution

.\Anavem-UpdateImmutableId.ps1 -UPN "user@domain.com"

Without Parameters (Interactive)

.\Anavem-UpdateImmutableId.ps1

The script will prompt for the User Principal Name and Microsoft 365 credentials.

Skip Connection (Already Connected)

.\Anavem-UpdateImmutableId.ps1 -UPN "user@domain.com" -SkipConnection $true

Clear Immutable ID

.\Anavem-UpdateImmutableId.ps1 -UPN "user@domain.com" -Clear $true

Output Example

Connecting to Microsoft Graph...
Generated ImmutableId: 1MPSofa1kE+rze8SNFZ4kA==
ImmutableId written to Microsoft 365 User. Please confirm it matches generated ImmutableId

UserPrincipalName    ImmutableId                   SyncEnabled
-----------------    -----------                   -----------
user@domain.com      1MPSofa1kE+rze8SNFZ4kA==      False

Conclusion

Anavem Update Immutable ID is a straightforward PowerShell utility for Microsoft 365 administrators dealing with Entra Connect sync issues. It uses the modern Microsoft Graph PowerShell SDK (replacing the deprecated MSOnline and AzureAD modules) and can be run from any domain-joined machine with AD access.

Script Code

<# 
================================================================================
 Anavem.com - PowerShell Script
================================================================================
 Script Name : Anavem-UpdateImmutableId.ps1
 Description : Updates the Immutable ID (onPremisesImmutableId) for a Microsoft
               365 user based on their Active Directory objectGUID. Enables 
               hard-matching between AD and Entra ID for directory sync.
 Author      : Anavem.com
 Version     : 1.0.0
 Website     : https://www.anavem.com

 Use Case    :
 - Fix Entra Connect sync errors (InvalidSoftMatch, attribute conflicts)
 - Enable hard-matching for cloud-only users before sync
 - Recover from AD forest migrations
 - Restore deleted users with correct sync identity

 Run as Admin: No (but requires User Administrator role in Entra ID)
================================================================================
#>

param(
    [Parameter(Mandatory = $false)]
    [string]$UPN,

    [Parameter(Mandatory = $false)]
    [bool]$SkipConnection = $false,

    [Parameter(Mandatory = $false)]
    [bool]$Clear = $false
)

# Check for required modules
if (-not (Get-Module -ListAvailable -Name Microsoft.Graph.Users)) {
    Write-Host "Microsoft.Graph.Users module not found." -ForegroundColor Red
    Write-Host "Install with: Install-Module Microsoft.Graph.Users -Scope CurrentUser" -ForegroundColor Yellow
    exit 1
}

if (-not (Get-Module -ListAvailable -Name ActiveDirectory)) {
    Write-Host "ActiveDirectory module not found." -ForegroundColor Red
    Write-Host "Install RSAT tools to get this module." -ForegroundColor Yellow
    exit 1
}

Import-Module ActiveDirectory -ErrorAction Stop

# Prompt for UPN if not provided
if ([string]::IsNullOrEmpty($UPN)) {
    $UPN = Read-Host "Enter User Principal Name (UPN)"
}

# Connect to Microsoft Graph
if (-not $SkipConnection) {
    Write-Host "Connecting to Microsoft Graph..." -ForegroundColor Cyan
    Connect-MgGraph -Scopes "User.ReadWrite.All" -NoWelcome -ErrorAction Stop
}

# Get AD user and objectGUID
$adUser = Get-ADUser -Filter "UserPrincipalName -eq '$UPN'" -Properties ObjectGUID

if ($null -eq $adUser) {
    Write-Host "User not found in Active Directory: $UPN" -ForegroundColor Red
    exit 1
}

# Convert objectGUID to ImmutableId (Base64)
$immutableId = [System.Convert]::ToBase64String($adUser.ObjectGUID.ToByteArray())
Write-Host "Generated ImmutableId: $immutableId" -ForegroundColor Green

# Get Microsoft 365 user
$mgUser = Get-MgUser -Filter "userPrincipalName eq '$UPN'" -Property Id, UserPrincipalName, OnPremisesImmutableId, OnPremisesSyncEnabled

if ($null -eq $mgUser) {
    Write-Host "User not found in Microsoft 365: $UPN" -ForegroundColor Red
    exit 1
}

# Check if user is currently synced
if ($mgUser.OnPremisesSyncEnabled -eq $true) {
    Write-Host "User is currently synced. Cannot update ImmutableId while sync is active." -ForegroundColor Red
    Write-Host "Disable sync for this user or move them out of sync scope first." -ForegroundColor Yellow
    exit 1
}

# Update or clear ImmutableId
if ($Clear) {
    Update-MgUser -UserId $mgUser.Id -OnPremisesImmutableId $null
    Write-Host "ImmutableId cleared for Microsoft 365 User." -ForegroundColor Green
}
else {
    Update-MgUser -UserId $mgUser.Id -OnPremisesImmutableId $immutableId
    Write-Host "ImmutableId written to Microsoft 365 User. Please confirm it matches generated ImmutableId" -ForegroundColor Green
}

# Verify and display result
$verifyUser = Get-MgUser -UserId $mgUser.Id -Property UserPrincipalName, OnPremisesImmutableId, OnPremisesSyncEnabled

$verifyUser | Select-Object UserPrincipalName, 
    @{N='ImmutableId';E={$_.OnPremisesImmutableId}}, 
    @{N='SyncEnabled';E={$_.OnPremisesSyncEnabled}} | Format-Table -AutoSize

Security Notes

  • Read-only access to Active Directory
  • Requires explicit consent for Microsoft Graph scopes
  • No passwords or secrets are stored
  • Safe for production environments

Source Code

Comments

Want to join the discussion?

Create an account to unlock exclusive member content, save your favorite articles, and join our community of IT professionals.

Sign in