SharePoint: Profile Sync with MIM – Managers and Group memberships are not updated

Update 2/22/21: The problem that early 2019 builds had with getting the timer job to process the staged manager and group membership entries, (the “NoILMUsed” issue) has been fixed. More about that in the “SharePoint 2019” section below.

I want to thank my colleague Dhiren for doing most of the leg work to figure this one out.

Spoiler alert: Turns out it has the same root cause as this issue: https://joshroark.com/sharepoint-2016-active-directory-import-timer-job-does-not-run-allowservicejobs/

Consider the following scenario:

In the User Profile Service Application (UPA), you configure SharePoint 2013, 2016, or 2019 to use an “External Identity Manager”.

You use Microsoft Identity Manager (MIM) to synchronize user profiles from Active Directory (AD) into SharePoint (SP).

You configure your AD and SP management agents and run a Full Sync.

You see that user profiles are successfully imported, but you also notice some of the following problems:

  • Manager to direct report relationships are not updated. They may remain stale (show the “old” manager), or not show a manager at all.
  • Audiences that utilize a “member of” rule become stale (new users added to the group are not reflected in the audience).
  • When trying to create a new “member of” audience, the Active Directory group cannot be found.
  • OAuth / Server-to-Server (S2S) authentication and claims augmentation scenarios like Workflows utilizing Workflow Manager and Office Web Apps may fail with 401 – Unauthorized (Access Denied) when you depend on AD groups to provide access to SharePoint content.

So… users were imported, why not groups?

Group memberships and manager references are a little trickier because they are not really imported objects. Instead, they are relationships between two objects. Both managers and groups are imported during the initial Sync. However, the relationships between them are built during the post-import processing task. This post-import processing is done by a timer job. In this scenario, the timer job has never run because none of the servers in the farm have the AllowServiceJobs flag set. Therefore, there are no servers in the farm that can run the job. Exactly which timer job is used for the post-import processing depends on your build number, as detailed below.

SharePoint 2019

Pre-August 2020 PU (farm build < 16.0.10364.20001)

In these earlier builds of SharePoint 2019, to get the timer job to process the staged manager and group membership entries, you will need to run this PowerShell:

$upa = Get-SPServiceApplication | ?{$_.typename -match "user profile"}
$upa.NoILMUsed = $true
$upa.update()

Post-August 2020 PU (farm build >= 16.0.10364.20001)

If your farm is at the August 2020 update or higher, the steps are the same as SharePoint 2016, Post-February 2017 PU. See that section below.

SharePoint 2016

Pre-February 2017 PU (farm build < 16.0.4498.1002). In these earlier builds of SharePoint 2016, we used the “User Profile ActiveDirectory Import Job” (UserProfileADImportJob) timer job for this work, which was not ideal.

You’ll need to use the NoILMUsed workaround to get this to work. Reference: https://thesharepointfarm.com/2016/04/sharepoint-server-2016-audiences-mim/

Run this PowerShell to check on the timer job:

Get-SPTimerJob | ? {$_.displayname -match "ActiveDirectory"}

If the “NoILMUsed” flag is set, but it looks like the timer job has never ran, move on to the “Solution” section below.

Post-February 2017 PU (farm build >= 16.0.4498.1002). After the February 2017 update, we use a new timer job called “Updates Profile Memberships and Relationships Job” for this work.

Run this PowerShell to check on the timer job:

Get-SPTimerJob | ? {$_.displayname -match "memberships"} | fl

If it doesn’t return any timer job at all, it may not have been created yet. Reference: https://thesharepointfarm.com/2017/02/microsoft-identity-manager-noilmused-bug-fixed/

You can provision the timer job like this:

$sa = Get-SPServiceApplication | ?{$_.TypeName -match "Profile"}
$sa.Provision()

If your farm shows the “Updates Profile Memberships and Relationships Job” timer job exists, but has never ran, move on to the “Solution” section below.

Solution:

Run the following PowerShell script to make sure all timer instances are online, and that at least one of your User Profile servers is set to “AllowServiceJobs”:

#This will check to make sure there is at least one User Profile Service instance in the farm,
#and that the AllowServiceJobs property is set to true for the timer instance on those server(s)
Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue
#Check the timer instances.  They should all be online:
$Farm = Get-SPFarm
$FarmTimers = $Farm.TimerService.Instances
foreach ($FT in $FarmTimers){write-host “Server: ” $FT.Server.Name.ToString(); write-host “Status: ” $FT.status; write-host “Allow Service Jobs: ” $FT.AllowServiceJobs; write-host “Allow Content DB Jobs: ” $FT.AllowContentDatabaseJobs;”`n”}
$disabledTimers = $farm.TimerService.Instances | where {$_.Status -ne “Online”}
if ($disabledTimers -ne $null)
{foreach ($timer in $disabledTimers)
{Write-Host -ForegroundColor Red “Timer service instance on server ” $timer.Server.Name ” is NOT Online. Current status:” $timer.Status
Write-Host -ForegroundColor Green “Attempting to set the status of the service instance to online…”
$timer.Status = [Microsoft.SharePoint.Administration.SPObjectStatus]::Online
$timer.Update()
write-host -ForegroundColor Red “You MUST now go restart the SharePoint timer service on server ” $timer.Server.Name}}
else{Write-Host -ForegroundColor Green  “All Timer Service Instances in the farm are online. Moving on to checking AllowServiceJobs...”}   
#Make sure AllowServiceJobs is set on servers running the User Profile Service:
$SIs = Get-SPServiceInstance | ?{$_.typename -match “profile service”}
$1onLine = $false
foreach ($SI in $SIs)
{If($SI.Status -eq “Online”)
{$1onLine = $true
foreach ($FT in $FarmTimers)
{if($SI.Server.Address.ToString() -eq $FT.Server.Name.ToString())
{if($FT.AllowServiceJobs -eq $false)
{write-host -ForegroundColor Red “Service jobs are NOT enabled on User Profile server” $FT.Server.Name.ToString()
write-host -ForegroundColor green “Enabling service jobs on server: ” $FT.Server.Name.ToString()
$FT.AllowServiceJobs = $true
$FT.Update()}
else{write-host -ForegroundColor green “Service Jobs already enabled on server: ” $FT.Server.Name.ToString()}
}}}}
If($1onLine -eq $false ){write-host -ForegroundColor red “No instances of User Profile Service online in this farm!”}
#End Script

Note: The above script is a combination of scripts from two of my other blog posts:

That didn’t do it?

There are a number of reasons why group memberships and manager relationships might not be updated. You should go back and doublecheck for the common issues. Ideally, you would do that first, but I didn’t want that to get in the way of explaining the specific issue noted above.

Make sure that the AD containers that store the users, their managers, and any group that you want to use for audiences are selected within the Sync connection (or AD Management Agent in this case). If you make any changes to container selection, you’ll need to run a Full Sync for it to take effect.

I also wrote an entire troubleshooter on manager and group membership updates with MIM.

Add a Comment