Syncing ServiceNow User Profile Pictures from Azure using REST API
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
an hour ago - last edited an hour ago
Introduction
In many organizations, user profile pictures are stored in Microsoft Azure Active Directory (AAD). However, these profile images are not automatically synchronized with ServiceNow user records.
This article explains how to implement a custom integration that synchronizes user profile pictures from Azure to ServiceNow using the following components:
- REST Message to fetch images from Azure
- Script Include to process the response and update user avatars
- Live Profile table (live_profile) to store the avatar reference
- Scheduled Job to run the synchronization periodically
This solution ensures that ServiceNow user avatars stay consistent with Azure profile pictures.
Understanding How Avatars Work in ServiceNow
In ServiceNow, user avatars are not stored directly on the sys_user record. Instead, the avatar image is retrieved through the following structure:
sys_user
↓
live_profile (Avatar metadata)
↓
sys_attachment (Actual image file)
The live_profile.photo field stores the sys_id of the attachment containing the user's avatar.
Many interfaces such as:
- Employee Center
- Service Portal
- Workspace
retrieve avatars using the internal API:
GlideAvatarFinder.getAvatarID(user_sys_id)Therefore, updating the live_profile.photo field ensures that the avatar is displayed correctly across the platform.
Solution Architecture
The integration consists of the following components:
Scheduled Job
↓
Script Include
↓
REST Message → Azure Graph API
↓
Save Image as Attachment
↓
Update live_profile.photoThe process works as follows:
- Scheduled job queries active users.
- Script Include calls Azure API to retrieve profile pictures.
- The image response is saved as an attachment.
- The attachment sys_id is stored in the live_profile.photo field.
Step 1: Configure Azure and ServiceNow for OAuth Authentication
To fetch profile pictures from Azure, ServiceNow must authenticate with Microsoft Graph API using OAuth 2.0.
This requires configuration in both Azure and ServiceNow.
The setup consists of the following steps:
- Create an App Registration in Azure
- Assign required Microsoft Graph permissions
- Configure Application Registry in ServiceNow
- Create an OAuth Profile
- Create the REST Message
1. Create App Registration in Azure
First, create an Application Registration in Microsoft Azure that ServiceNow will use to authenticate with Microsoft Graph.
Steps
- Go to the Azure Portal: https://portal.azure.com
- Navigate to: Microsoft Entra ID → App registrations
- Click: New Registration
Provide the following details
Field | Example Value |
Name | ServiceNow Avatar Sync |
Supported account types | Accounts in this organizational directory only |
Redirect URI | Leave blank |
Example configuration:
Name: ServiceNow Avatar Sync
Supported Account Type: Single Tenant
Redirect URI: Not required
Click Register.
2. Copy Application Details
After the application is created, copy the following values:
Azure Field | Example | Used In |
Application (client) ID | 7a2d21c4-1c3f-4d01-b6f0-23dfc0d1f1e2 | ServiceNow Application Registry |
Directory (tenant) ID | 8b3f8f2a-9e1d-45c4-b3c1-3a4e6e44f222 | OAuth Endpoint |
Client Secret | Generated later | ServiceNow |
3. Create Client Secret in Azure
Navigate to: Certificates & secrets
Click: New client secret
Provide the following:
Field | Example |
Description | ServiceNow OAuth Secret |
Expiry | 24 Months |
Click Add.
Copy the generated Client Secret value.
Example:
Client Secret: x8L~kP9...abc
⚠️Important: This value is visible only once.
4. Add Microsoft Graph API Permission
Navigate to: API permissions
Click: Add permission
Select: Microsoft Graph
Choose: Application permissions
Add the following permission:
User.Read.All
Description:
Allows the application to read all user profiles without a signed-in user.
After adding the permission, click: Grant Admin Consent
5. Configure OAuth Endpoint
The OAuth Token endpoint will be:
https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token
Example:
https://login.microsoftonline.com/8b3f8f2a-9e1d-45c4-b3c1-3a4e6e44f222/oauth2/v2.0/token
6. Create Application Registry in ServiceNow
Navigate to: System OAuth → Application Registry
Click: New
Select: Connect to a third party OAuth Provider
Provide the following values
Field | Example Value |
Name | Azure OAuth Provider |
Client ID | 7a2d21c4-1c3f-4d01-b6f0-23dfc0d1f1e2 |
Client Secret | x8L~kP9...abc |
Token URL | https://login.microsoftonline.com/{tenant-id}/oauth2/v2.0/token |
Default Grant Type | Client Credentials |
Scope |
Example configuration:
Client ID: 7a2d21c4-1c3f-4d01-b6f0-23dfc0d1f1e2
Client Secret: *********
Token URL: https://login.microsoftonline.com/8b3f8f2a-9e1d-45c4-b3c1-3a4e6e44f222/oauth2/v2.0/token
Scope:https://graph.microsoft.com/.default
Save the record.
7. Create OAuth Profile
Navigate to: System OAuth → OAuth Profiles
Click New.
Provide the following values:
Field | Example |
Name | Azure OAuth Profile |
OAuth Provider | Azure OAuth Provider |
Grant Type | Client Credentials |
Save the record.
8. Create REST Message
Navigate to: System Web Services → REST Message
Create a new REST Message.
Field | Value |
Name | Get User Details |
Endpoint |
Example description:
This REST message retrieves user profile pictures from Azure using Microsoft Graph API.
9. Configure Authentication
In the REST Message: Authentication Type: OAuth 2.0
OAuth Profile: Azure OAuth Profile
10. Create REST Method
Inside the REST Message create a new method.
Field | Value |
Name | Get Profile Pic |
HTTP Method | GET |
Endpoint: https://graph.microsoft.com/v1.0/users/${email}/photo/$value
This endpoint returns the binary image of the user’s profile picture.
Example request: GET https://graph.microsoft.com/v1.0/users/john.doe@company.com/photo/$value
Response: Binary JPEG Image
11. Test the REST Message
Provide a test email: naga.b@company.com
If successful, the response will return: HTTP 200
Binary image
If the user has no profile picture:
HTTP 404
Step 2: Create Script Include for Avatar Synchronization
Create a Script Include that will:
- Query active users
- Call the REST API
- Save the image as an attachment
- Update the avatar in live_profile
var GetUserProfile = Class.create();
GetUserProfile.prototype = {
initialize: function() {},
getUserPicture: function() {
// Counters and logs for reporting
var updatedUsersLog = [];
var noPhotoUsersLog = [];
var errorUsersLog = [];
// Query all active users that have SSO source
var userRecord = new GlideRecord('sys_user');
userRecord.addEncodedQuery('active=true^sso_sourceISNOTEMPTY^emailISNOTEMPTY');
userRecord.query();
while (userRecord.next()) {
var pic = userRecord.sys_id + '_photo.jpg';
try {
// Store reference to the user's Live Profile record
var liveProfileRecord;
// REST message to fetch photo from Azure
var restMessage = new sn_ws.RESTMessageV2('Get User Details', 'Get Profile Pic');
restMessage.setStringParameterNoEscape('email', userRecord.email);
// STEP 1: Retrieve or create the live_profile record for this user
var avatarGR = new GlideRecord('live_profile');
avatarGR.addQuery('type', 'user'); // Avatar type must be 'user'
avatarGR.addQuery('document', userRecord.sys_id); // Link to sys_user record
avatarGR.query();
if (avatarGR.next()) {
liveProfileRecord = avatarGR;
} else {
// If no live_profile exists create one
avatarGR.initialize();
avatarGR.type = 'user';
avatarGR.name = userRecord.name;
avatarGR.table = 'sys_user';
avatarGR.document = userRecord.sys_id;
avatarGR.insert();
liveProfileRecord = avatarGR;
}
// STEP 2: Save Azure image response as attachment
restMessage.saveResponseBodyAsAttachment(
'live_profile',
liveProfileRecord.sys_id,
pic
);
var response = restMessage.execute();
var httpStatus = response.getStatusCode();
// STEP 3: Process REST response
if (httpStatus == 200) {
var newAttachmentSysId = response.getResponseAttachmentSysid();
// STEP 4: Delete existing avatar attachment if it exists
if (liveProfileRecord.photo) {
var oldAttachment = new GlideRecord('sys_attachment');
if (oldAttachment.get(liveProfileRecord.photo)) {
oldAttachment.deleteRecord();
}
}
// Update avatar reference
liveProfileRecord.photo = newAttachmentSysId;
liveProfileRecord.update();
// Optional: also update sys_user.photo
userRecord.photo = newAttachmentSysId;
userRecord.update();
updatedUsersLog.push("\n " + userRecord.email);
} else if (httpStatus == 404) {
noPhotoUsersLog.push("\n " + userRecord.email);
} else {
errorUsersLog.push(userRecord.email + " | Response: " + response.getBody());
}
} catch (exception) {
errorUsersLog.push(userRecord.email +
" | Error: " + exception.message);
}
}
// Final result summary
var summaryMessage =
"<b>Azure Avatar Sync Summary</b><br>" +
"<b>Users Updated:</b> " + updatedUsersLog.length + "<br>" +
updatedUsersLog.join("<br>") + "<br><br>" +
"<b>Users Without Azure Photo:</b> " + noPhotoUsersLog.length + "<br>" +
noPhotoUsersLog.join("<br>") + "<br><br>" +
"<b>Errors:</b> " + errorUsersLog.length + "<br>" +
errorUsersLog.join("<br>") + "<br>" +
"-------------------------";
gs.info(summaryMessage);
},
type: 'GetUserProfile'
};
Step 3: Create a Scheduled Job
Navigate to: System Definition → Scheduled Jobs
Create a new job.
Field | Value |
Name | Azure User Avatar Sync |
Run | Monthly |
Script:
var sync = new GetUserProfile();
var result = sync.getUserPicture();
This job will automatically synchronize user avatars.
Performance Considerations
When syncing avatars for many users:
Avoid Duplicate Attachments
Delete existing avatar attachments before saving new ones.
Skip Users Without Emails
Azure Graph requires an email identifier.
Batch Processing
For large environments process users in batches.
Handle Missing Photos
If Azure returns 404, skip the update.
Example Output
Example log output from the synchronization job:
Azure Avatar Sync Summary
nag.t@company.com - Avatar Updated
pra.now@company.com - Avatar Updated
zoho@company.com - No Azure Photo Found
Conclusion
ServiceNow can now securely fetch user profile images from Azure using OAuth 2.0 authentication and Microsoft Graph API.
