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

Update 9/16/19: It has come to my attention that at the time of this update (9/16/19), we have a similar problem with SharePoint 2019 as we did in early SP 2016 builds. To get the timer job to process the staged manager and group membership entries, you will likely need to set the “NoILMUsed” flag on the UPA object. More about that in the new SP 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

As of 9/16/19, to get the timer job to process the staged manager and group membership entries, you will likely need to run this PowerShell:

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

From here, the steps are the same as SP 2016. See “Post – Feb 2017 PU” section below.

SharePoint 2016

Pre – Feb 2017 PU (build < 16.0.4498.1002) = “User Profile ActiveDirectory Import Job” (UserProfileADImportJob).

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 – Feb 2017 PU (build >= 16.0.4498.1002) = “Updates Profile Memberships and Relationships Job” (ExternalIdentityManagerMembershipsAndRelationshipsJob)

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.