Wow, long title for a post that's long overdue! I'd written about a solution to this same challenge previously, utilizing a scheduled task running from an on-premises server. The script didn't age terribly well and required a few updates, which I didn't take care of but rather let it languish. To those that reached out to me regarding this I appreciate the feedback, and this is my attempt at an updated, simpler and more robust solution to the same challenge.
The Challenge
The User Profile Sync in SharePoint Online imports a number of properties from Azure Active Directory - but we're unable to configure any additional property mappings for import. This creates a challenge where the mobilePhone Active Directory attribute does not get synchronized to the SharePoint Online User Profile CellPhone property, despite what the Azure AD Connect sync: Attributes synchronized to Azure Active Directory may lead you to believe.
A Solution
To solve this we'll take an approach that involves an Azure Automation Runbook, the MSOnline and PnP PowerShell Online cmdlets to update the SharePoint User Profiles using the Azure Active Directory data.
We'll use the PowerShell and Automation Account approach as it's generally more familiar to the IT Pros, and the support for PowerShell is still experimental in Azure Functions. However, if you'd prefer to take that approach it's equally valid but requires a little more familiarity with coding - there are examples of this online.
Additionally, since Azure Automation supports the secure use of variable and credential storage we'll gain the benefit of not having hard-coded scripts containing usernames and passwords.
Requirements
To accomplish this we'll need to have the following:
- Azure Subscription
- Office 365 Global Administrator account credentials
- Powershell script
Configuring the Azure Automation account and Runbook
Create the Automation Account
Log into the Azure Portal and create a new Automation Account:
For our purposes we don't need the 'Run As Account':
Import PowerShell Modules
Once the Automation Account is created we need to import the PowerShell Modules into the Automation Account for use by the PowerShell scripts. Open the Automation Account and click on the Modules link in the Shared Resources section:
Click the Browse gallery link:
and then search for MSOnline:
Click into the module, then on the Import link:
Click the OK button and then wait for the module to successfully import:
Repeat the above for the SharePointPnPPowerShellOnline module:
Confirm that both modules are imported by reviewing the available modules:
Automation Account Variables and Credentials
To enable some flexibility in the script we'll utilize a few Automation Account Variables and Credentials - in fact, we'll create a variable for the credential name in case this already exists in the environment.
Create the Automation Account Credential first so we can refer to it by name in a variable. The credentials should be named o365GlobalAdmin and look something like the following:
If your Office 365 Global Administrator account is MFA-enabled you'll need to have and use an App Password
The script relies on the following variables:
- o365GlobalAdminCredentialName
- overwriteExistingSPOUPAValue
- tenantName
Create the first variable o365GlobalAdminCredentialName which contains the name of the Azure Automation Credential created above (o365GlobalAdmin), as a non-encrypted string type variable similar to the following:
The second variable overwriteExistingSPOUPAValue is a boolean (True/False) type that indicates whether or not we'll overwrite existing values in the SharePoint Online User Profile store. When set to True the script will use the values in Azure AD as the source of truth which may overwrite any values that users have updated in their profiles manually:
The last variable tenantName is a string type and contains the Company name portion of the Office 365/Azure AD Tenant:
The script uses the tenantName variable to build the Url to the SharePoint Online Administration site, for example https://YOURTENANTNAMEHERE-admin.sharepoint.com/
That's all we need to setup the Automation Account for use by the Runbook.
Runbook
At this point we need to create the Runbook which will contain our PowerShell script, click on the Create a runbook link:
Give the runbook a name, select PowerShell as the type and optionally set a description - click the Create button once everything looks good:
Once created, click the Edit button:
This will open the browser-based code editor, into which we'll upload the PowerShell script:
Import-Module MSOnline
Import-Module SharePointPnPPowerShellOnline
# Automation Variables
$tenantName = Get-AutomationVariable -Name "tenantName"
$spoAdminUrl = "https://$tenantName-admin.sharepoint.com"
$overwriteExistingSPOUPAValue = Get-AutomationVariable -Name "overwriteExistingSPOUPAValue"
# Get credentials from Automation Variables
$credential = Get-AutomationPSCredential -Name (Get-AutomationVariable -Name "o365GlobalAdminCredentialName")
Try {
# Connect to AzureAD
Connect-MsolService -Credential $credential
# Connect to SPO using PnP
$spoPnPConnection = Connect-PnPOnline -Url $spoAdminUrl -Credentials $credential -ReturnConnection
# Get all AzureAD Users with a populated MobilePhone property
$AzureADUsers = Get-MsolUser -All | Where-Object {(![string]::IsNullOrWhiteSpace($_.MobilePhone))}
ForEach ($AzureADUser in $AzureADUsers) {
# Check to see if SPO UserProfileProperty CellPhone differs from AzureAD User Property MobilePhone
if((Get-PnPUserProfileProperty -Account $AzureADUser.UserPrincipalName).UserProfileProperties.CellPhone -ne $AzureADUser.MobilePhone){
# Property differs, update with AzureAD value
# Check to see if we're to overwrite existing property value
if ($overwriteExistingSPOUPAValue -eq "True") {
Write-Output "Update CellPhone for $($AzureADUser.UserPrincipalName)"
Set-PnPUserProfileProperty -Account $AzureADUser.UserPrincipalName -PropertyName CellPhone -Value $AzureADUser.MobilePhone
}
else{
# Not going to overwrite existing property value
Write-Output "Target SPO UPA CellPhone is not empty for $($AzureADUser.UserPrincipalName) and we're to preserve existing properties"
}
}
}
}
Catch {
$exception = $_.Exception.Message
Write-Output "$($exception)"
}
Click the Publish button in the Edit window and we're ready to give the script a quick test.
Back on the Runbook Overview screen click the Start link and wait a few minutes - the script will run and output any messages, Warnings or Errors as it executes.
Here's a screenshot of the Output tab showing that there are users with different values in the mobilePhone / CellPhone properties, but since overwriteExistingSPOUPAValue is currently set to False the target values will be preserved:
At this point we can modify the overwriteExistingSPOUPAValue variable to True, and set the runbook to run on a schedule by clicking Schedules and Add a schedule:
Click through the Link a schedule to your runbook and Create a new schedule. The following example shows a daily recurring schedule with no end date:
Confirm that the Runbook is schedule to execute on the schedule:
At this point the configuration is complete and scheduled to execute daily.
Verification
Following the scheduled execution, we can see that the Azure Active Directory Users that had a value in the mobilePhone attribute now have the same value in the SharePoint User Profile property CellPhone. In my test tenant we'll take a look at Binaca Pisani's account information:
And we can compare that to the SharePoint User Profile property of CellPhone:
Note that even though the value exists in the User Profile Property Store we need to wait for Search to crawl the update before it'll show in our search-based Employee Directories. Here we can see the property exists in the Delve profile card as well:
Summary
Currently the mobilePhone values from Azure Active Directory don't sync to the SharePoint Online User Profile Store - we're unable to modify the configuration of the import to make this happen.
We've worked-around the challenge with an automated approach - using Azure Automation Runbooks, PnPPowershell and a simple script that identifies users having a mobilePhone value in Azure Active Directory and sets the same value in the SharePoint User Profile CellPhone property.
I hope this helps!
Let me know what you think of this approach and I'll try to be more responsive than the three-year cycle my last post was treated to.