Okta provisions a new user, the user can log in, but the assignment groups in ServiceNow are wrong, the manager is empty, and three months later there is a duplicate sys_user record from a slight email format mismatch. SCIM gets users into ServiceNow; getting them in correctly and out cleanly when they leave is the work the default mappings skip.
Match on a stable key, not email
Email is the most common SCIM matching attribute and the worst. Email changes on marriage, on M&A, on rebrand. Use externalId (Okta’s unique user ID) mapped to employee_number or a custom okta_user_id field on sys_user. The match attribute should be immutable for the user’s entire tenure. Otherwise, the second time their email changes, SCIM creates a duplicate.
SCIM mapping:
externalId -> sys_user.okta_user_id (unique, indexed)
userName -> sys_user.user_name
emails[primary] -> sys_user.email (for display, not matching)
Group membership through SCIM, not push
Okta has two ways to manage group membership in ServiceNow: SCIM groups and group push. SCIM groups are part of the standard provisioning flow and version cleanly. Group push is a separate mechanism that can race with SCIM and produce inconsistent state. Pick one — SCIM groups for new implementations — and disable the other. Mixing them is the most common source of “user added to group then immediately removed” cycles.
Authoritative sources differ by attribute
SCIM provisions identity. HR (Workday, BambooHR, etc.) provisions employment data. Both want to write to sys_user. Without a clear matrix, the last writer wins and the manager field flips between systems daily. Document per-field authority, configure SCIM to skip non-authoritative fields, and use the HR feed for those. The SCIM logs should show “skipped (not authoritative)” not “wrote (overrode).”
Deactivation vs deletion
When a user leaves Okta, SCIM sends a deprovisioning request. Deleting the sys_user record breaks every historical reference (assigned tasks, work notes, audit logs). Deactivate instead: set active=false, preserve all history, transfer open work, retain the record for audit. Configure the SCIM endpoint to translate DELETE to deactivate, not to actual deletion.
// SCIM DELETE handler
function handleScimDelete(externalId) {
var user = findUserByOktaId(externalId);
if (!user) return 404;
user.active = false;
user.locked_out = true;
user.deactivated_at = gs.nowDateTime();
user.update();
reassignOpenWork(user.sys_id);
return 204;
}
Reactivation needs explicit handling
A boomerang employee reactivated in Okta should reuse the existing sys_user record, not create a new one. The match-by-externalId pattern handles this if the external ID is preserved across the off-boarding. Some Okta configurations rotate external ID on reactivation, breaking the match. Verify the rotation behavior in your tenant before relying on it.
Audit the drift
A weekly job pulls Okta’s user list via the standard API, compares against sys_user records with non-null okta_user_id, and reports discrepancies: users in Okta but not in SN, users in SN with stale Okta data, deactivated-in-Okta but active-in-SN, group memberships out of sync. The discrepancies are the diff your SCIM provisioning is missing.
Common failure modes
SCIM endpoint authentication using a personal user’s API token — rotate to a dedicated integration user with bare-minimum roles. Bulk operation timeouts on large tenants — Okta defaults to small batches; tune via pageSize and let SCIM retry on 429. Custom SN business rules that reject SCIM updates because of business logic written for human submitters — exclude the SCIM integration user from those rules.
What changed in 2026
Okta has expanded SCIM 2.0 schema extensions, including richer group hierarchy and conditional attribute provisioning. ServiceNow’s SCIM endpoint accepts the extensions but ignores unknown ones silently — verify expected attributes are actually being written by checking sys_user_audit after a test provision.
What to do this week: query sys_user for active records with no okta_user_id and no other authoritative external ID — those are the users SCIM cannot match cleanly.