So, here I am looking down at a project to create a new domain and migrate users. Normally this isn’t a bad process. You clone the user on the other domain and have them sign in. Use a tool like Profwiz or ADMT (assuming it works). Then I realize, they are AD synced to Entra/Identity. Oh, this is going to be interesting. So, I pulled out my Diet Dr Pepper and got to work. It’s time to find the Entra ID source anchor attribute.
ms-DS-ConsistencyGuid is the Entra ID source anchor attribute
This little guy is the magic sauce that you are looking for. Back in the day, the syncing attribute was the object guid. This was a problem as many companies had more than one domain with the same account names. So, this little consistency guid matches the Immutable ID in entra. Lets take a look at these two.
- On-prem AD user:
- Attribute: ms-DS-ConsistencyGuid
- Type: GUID stored as binary
- Entra ID user:
- Attribute: immutableId
- Type: Base64-encoded version of that GUID
As long as these values never change, your hybrid identity stays the same. Change it the wrong way, your sync gets ugly. Here is how you can get the information from AD.
Get-ADUser some.user -Properties ms-DS-ConsistencyGuid | Select Name, ms-DS-ConsistencyGuid
If it’s $null, nothing is using it yet, it not, then something is using it.
- It’s a GUID field, perfect for unique identity.
- It doesn’t change when you move users between OUs.
- In the right design, you keep it stable even across forests and migrations.
- Microsoft now recommends it specifically as the Entra ID source anchor attribute.
This is important to understand. if these don’t match, you don’t have a sync going on. Lets write a powershell that will check both.
Confirm with powershell
This powershell grabs both and lets us know if they match, if they don’t it tells us.
<#
.SYNOPSIS
Compare on-prem ms-DS-ConsistencyGuid with Entra/Azure AD ImmutableId.
.DESCRIPTION
For each user:
- Reads ms-DS-ConsistencyGuid from AD
- Converts it to Base64 (what ImmutableId should be)
- Gets the cloud ImmutableId by UPN
- Outputs if they match
NOTE: This script is READ-ONLY. It does NOT change anything.
#>
Import-Module ActiveDirectory
Import-Module MSOnline
Write-Host "Connecting to Entra/Azure AD..."
Connect-MsolService
Write-Host "Getting AD users..."
$adUsers = Get-ADUser -Filter * -Properties userPrincipalName, ms-DS-ConsistencyGuid |
Where-Object { $_.UserPrincipalName -ne $null }
$result = @()
foreach ($user in $adUsers) {
$upn = $user.UserPrincipalName
# Get ms-DS-ConsistencyGuid from AD
$consistencyBytes = $user.'ms-DS-ConsistencyGuid'
$consistencyGuid = $null
$adAnchorBase64 = $null
if ($consistencyBytes) {
$consistencyGuid = [Guid]$consistencyBytes
$adAnchorBase64 = [Convert]::ToBase64String($consistencyBytes)
}
# Get cloud ImmutableId by UPN
$cloudUser = Get-MsolUser -UserPrincipalName $upn -ErrorAction SilentlyContinue
$immutableId = $null
$matchStatus = "Unknown"
if ($cloudUser) {
$immutableId = $cloudUser.ImmutableId
}
# Work out match status
if ($adAnchorBase64 -and $immutableId) {
if ($adAnchorBase64 -eq $immutableId) {
$matchStatus = "Match"
} else {
$matchStatus = "Mismatch"
}
}
elseif ($adAnchorBase64 -and -not $immutableId) {
$matchStatus = "No ImmutableId in Entra"
}
elseif (-not $adAnchorBase64 -and $immutableId) {
$matchStatus = "No ConsistencyGuid in AD"
}
else {
$matchStatus = "Neither Set"
}
$result += [PSCustomObject]@{
UserPrincipalName = $upn
ConsistencyGuid = $consistencyGuid
ADSourceAnchorB64 = $adAnchorBase64
EntraImmutableId = $immutableId
MatchStatus = $matchStatus
}
}
# Show on screen
$result | Sort-Object MatchStatus, UserPrincipalName | Format-Table -AutoSize
# Optional: save to CSV for review
#$result | Export-Csv .\AnchorComparison.csv -NoTypeInformation
This script will give you a list of all the users and if it matches. Here is a script that will force the user to the immutableid. The check gives you info, and if you don’t check it will set it.
function Set-MsDsConsistencyGuidFromImmutableId {
<#
.SYNOPSIS
Set ms-DS-ConsistencyGuid from Entra/Azure AD ImmutableId for one user.
.DESCRIPTION
Given a samAccountName:
- Look up the on-prem AD user
- Read ms-DS-ConsistencyGuid
- Look up the Entra/Azure AD user by UPN
- If ms-DS-ConsistencyGuid is empty and ImmutableId exists,
set ms-DS-ConsistencyGuid to the ImmutableId value (decoded from Base64)
Use -Check to only show what would happen, without making changes.
.PARAMETER SamAccountName
The on-prem AD samAccountName of the user.
.PARAMETER Check
If supplied, only checks and reports. No changes are made.
#>
[CmdletBinding()]
param(
[Parameter(Mandatory = $true)]
[string]$SamAccountName,
[switch]$Check
)
# Make sure AD module is available
if (-not (Get-Module ActiveDirectory -ListAvailable)) {
Write-Error "ActiveDirectory module not found. Install RSAT / AD tools first."
return
}
Import-Module ActiveDirectory -ErrorAction Stop
# Make sure MSOnline module is available
if (-not (Get-Module MSOnline -ListAvailable)) {
Write-Error "MSOnline module not found. Install-Module MSOnline first."
return
}
Import-Module MSOnline -ErrorAction Stop
# Get on-prem user
$adUser = Get-ADUser -Identity $SamAccountName -Properties userPrincipalName, ms-DS-ConsistencyGuid -ErrorAction SilentlyContinue
if (-not $adUser) {
Write-Error "No AD user found with samAccountName '$SamAccountName'."
return
}
$upn = $adUser.UserPrincipalName
if (-not $upn) {
Write-Error "User '$SamAccountName' does not have a UPN. Cannot match to Entra."
return
}
# Current AD ConsistencyGuid
$currentConsistencyBytes = $adUser.'ms-DS-ConsistencyGuid'
$currentConsistencyGuid = $null
$currentConsistencyB64 = $null
if ($currentConsistencyBytes) {
try {
$currentConsistencyGuid = [Guid]$currentConsistencyBytes
$currentConsistencyB64 = [Convert]::ToBase64String($currentConsistencyBytes)
}
catch {
Write-Warning "Failed to interpret existing ms-DS-ConsistencyGuid as GUID/Base64: $_"
}
}
# Get cloud user and ImmutableId
$cloudUser = Get-MsolUser -UserPrincipalName $upn -ErrorAction SilentlyContinue
if (-not $cloudUser) {
Write-Error "No Entra/Azure AD user found with UPN '$upn'."
return
}
$immutableId = $cloudUser.ImmutableId
# Decide what to do
$action = "None"
$result = "No change"
if ($currentConsistencyBytes) {
# Already has a ConsistencyGuid
$action = "None"
$result = "ms-DS-ConsistencyGuid already set. Nothing to do."
}
elseif (-not $immutableId) {
$action = "None"
$result = "Cloud user has no ImmutableId. Cannot set ms-DS-ConsistencyGuid from it."
}
else {
# We CAN set ms-DS-ConsistencyGuid from ImmutableId
$action = "Set ms-DS-ConsistencyGuid from ImmutableId"
try {
$newBytes = [Convert]::FromBase64String($immutableId)
$newGuid = [Guid]$newBytes
if ($Check) {
$result = "CHECK ONLY: Would set ms-DS-ConsistencyGuid to $newGuid from ImmutableId."
}
else {
Set-ADUser -Identity $adUser.DistinguishedName -Replace @{ 'ms-DS-ConsistencyGuid' = $newBytes }
$currentConsistencyGuid = $newGuid
$currentConsistencyB64 = [Convert]::ToBase64String($newBytes)
$result = "UPDATED: ms-DS-ConsistencyGuid set to $newGuid from ImmutableId."
}
}
catch {
$action = "Error"
$result = "Failed to convert ImmutableId '$immutableId' to GUID/bytes: $_"
}
}
# Output a simple summary object
[PSCustomObject]@{
SamAccountName = $SamAccountName
UserPrincipalName = $upn
CurrentConsistencyGuid = $currentConsistencyGuid
CurrentConsistencyGuidB64 = $currentConsistencyB64
CloudImmutableId = $immutableId
Action = $action
Result = $result
CheckMode = [bool]$Check
}
}
Notes
- if you have two domains, and the Entra ID source anchor attribute is the same in a synced area in both, you will get odd little accounts out of no where. Once you remove one of those into a unsynced ou, this will resolve the issue.
- You can force a user to become someone else using the Entra ID source anchor attribute ms-ds-consistencyguid. This isn’t a great thing, but it’s a hack around. So, if you want bob to become philip’s entra account, just change his anchor.
What can we learn as a person
In Entra, the anchor says “this is who I am, no matter where you move me.” In real life, we’ve got those too—just without the GUID. They’re the moments, labels, and stories that quietly tell us who we are: the kid who “wasn’t smart,” the one who always had to fix everything, the person who “always messes things up.” Those anchors don’t sit in a database, but they still decide what we “sync” with: what relationships we accept, what jobs we go for, what kind of treatment we think we deserve.
The tricky part is that a lot of those anchors were never chosen on purpose. They just happened, and we started believing, “This is just who I am.” But an anchor in your life is not a prison; it’s a reference point you’re allowed to outgrow. You might not be able to change what happened, but you can change what it means. “I failed” can become “I learned what I need to avoid next time.” “I grew up in chaos” can become “No wonder I get anxious when things change—and I can still learn how to calm myself and ask for what I need.” Same history, different interpretation.
So it’s worth asking yourself: What have I been using as my anchor? And if you could pick one on purpose, what would it be instead? Maybe something like “I’m learning,” or “I’m allowed to grow,” or “I deserve basic respect, even when I screw up.” In identity systems, once the anchor is stable and correct, all the sync errors start to calm down. In life, when your inner anchor shifts from shame to self-respect, a lot of emotional “sync errors” start to calm down too. The past doesn’t vanish—but it stops being the only thing that gets to name you.