Issue

There is sometimes the odd circumstances where the tenancy AAD and Microsoft backend user object attributes fail to update after a sync. Usually, a full or initial sync operation will correct this, but sometimes you have to force a refresh.

Solution

We need to purge the Azure AD object and allow the object to resynchronise through AAD Connect. This refreshes the object from Microsoft's side and synchronisation occurs without further issue.

High Level Steps
  1. Capture the MsolUser and reference the Object ID.
  2. Remove the active MsolUser .
  3. Remove the soft deleted MsolUser Object from the Recycle Bin.

IMPORTANT! Ensure you have completed full diagnostics before completing this operation. This is your fallback only when all seems normal and you just can't explain why the sync error is occuring.

Azure AD module does not yet support purging the user from the Azure Active Directory Recycle Bin. This function uses MSOnline to complete the operation. The function will be updated once support has been added to the Azure AD module.

Code:

#Requires -Module MsOnline
function Remove-xMsolUser {
    <#
.SYNOPSIS
    Deletes an MsolUser and purges the user from the Azure Active Directory (AAD) Recycle Bin.

.DESCRIPTION
    Deletes an MsolUser and purges the user from the Azure Active Directory Recycle Bin.
    Useful in the odd circumstances where the tenancy AAD and Microsoft backend object attributes fail to update after
    sync update.
    Azure AD module does not yet support purging the user from the Azure Active Directory Recycle Bin. This function
    uses MSOnline to complete the operation. Function will be updated once support has been added to the Azure AD
    module.

.EXAMPLE
    Remove-xMsolUser -UserPrincipalName [email protected]

.NOTES
    AUTHOR   : Steve Rackham
    BLOG     : https://siliconwolf.net
    GIT      : https://github.com/siliconWOLF
    TWITTER  : https://twitter.com/siliconW0LF
    LINKEDIN : https://nz.linkedin.com/in/steverackham
    TO-DO    : Add pipeline support and MsolUser object support.

    #>
    
    [CmdletBinding(
        SupportsShouldProcess,
        ConfirmImpact = 'High'
    )]
    param (
        [Parameter (
            Mandatory,
            HelpMessage = "Enter the UserPrincipalName for the MSOL user to purge."
        )]
        [MailAddress]$UserPrincipalName
    )

    # Offset for Verbose/Output stream formatting.
    $OffSet = 0 - $UserPrincipalName.Length

    # GET MSOL USER: ----------------------------------------------------------
    try {
        Write-Verbose ("{0, $OffSet} : {1}" -f "[ $UserPrincipalName) ]", "Capturing Azure AD for reference Object ID...")
        $MsolUser = Get-MsolUser -ObjectId $UserPrincipalName -ErrorAction Stop

    }
    catch {
        Write-Warning ("{0, $OffSet} : {1}" -f "[ $UserPrincipalName ]", "$($Error[0].Exception.Message)")
        Return

    } # END TRY/CATCH

    # PURGE OPERATION: --------------------------------------------------------
    if ($PSCmdlet.ShouldProcess(
            "[ $($MsolUser.ObjectID) ] Removing MsolUser : $($MsolUser.UserPrincipalName)  ",
            "[ $($MsolUser.ObjectID) ] Confirm Delete : $($MsolUser.UserPrincipalName) ",
            'WARNING!')) {
        # Remove the user: ----------------------------------------------------
        try {
            Write-Verbose ("{0,$OffSet} : {1}" -f "[ $($MsolUser.ObjectID) ]", "Deleting Azure AD Object ...")
            Remove-MsolUser -ObjectId $MsolUser.ObjectId -ErrorAction Stop

        }
        catch {
            Write-Warning ("{0, $OffSet} : {1}" -f "[ $($MsolUser.ObjectID) ]", "$($Error[0].Exception.Message)")

        } # END TRY/CATCH

        # Purge Recycle Bin: --------------------------------------------------
        try {
            Write-Verbose ("{0,$OffSet} : {1}" -f "[ $($MsolUser.ObjectID) ]", "Purging Azure AD Object from Recycle Bin...")
            Remove-MsolUser -ObjectId $MsolUser.ObjectId -RemoveFromRecycleBin -ErrorAction Stop

        }
        catch {
            Write-Warning ("{0, $OffSet} : {1}" -f "[ $($MsolUser.ObjectID) ]", "$($Error[0].Exception.Message)")

        } # END TRY/CATCH

    } # END if ($PSCmdlet.ShouldProcess())

} # END function Remove-xMsolUser #############################################


Happy Coding!