Reading Time: 5 minutes

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.