# SCIM provisioning from Entra ID or Okta into a SaaS app: attribute mapping and testing deprovisioning

Source: https://startwithidentity.com/recipes/scim-provisioning-entra-okta-saas/
Last updated: 2026-11-05
License: content by Start with Identity. Cite the source URL.

---

SCIM provisioning from [Microsoft Entra ID](https://startwithidentity.com/vendors/iam/microsoft-entra/) or [Okta](https://startwithidentity.com/vendors/iam/okta/) means the IdP calls the SaaS app's SCIM 2.0 API to create users when they are assigned, update them when attributes change and disable them when they leave. As the admin you supply the app's SCIM base URL and a bearer token, confirm which attribute matches existing accounts, limit scope to assigned groups, and then prove deprovisioning end to end. The finish line is a tested leaver: the user is disabled in the app within one sync cycle and their live sessions stop working. This recipe is the IdP side; for building the endpoint see [Set up SCIM provisioning](https://startwithidentity.com/recipes/set-up-scim-provisioning/).

## Before you start

Decide the matching attribute before anything syncs. It must be unique, present on every user and filterable in the app's API (usually `userName` mapped from UPN or email). A wrong choice creates duplicate accounts or silently links the wrong person. If the app already has users, align their `userName` values with the IdP first.

| Behaviour | Entra ID | Okta |
|---|---|---|
| Sync cadence | Every 40 minutes after the initial cycle | Event-driven on assignment and profile change |
| Unassign or disable | Update with `active=false` | `active=false` (PATCH for OIN apps, PUT for custom apps) |
| Hard delete | DELETE after hard delete (30 days after soft delete) | Never sends DELETE for users |
| Single-user test | Provision on demand | Assign one user |

Sources: Microsoft's [how provisioning works](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/how-provisioning-works) and [provisioning management](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/configure-automatic-user-provisioning-portal), and Okta's [SCIM 2.0 guide](https://developer.okta.com/docs/api/openapi/okta-scim/guides/scim-20).

## 1. Connect the IdP to the app's SCIM endpoint

- **Entra ID:** **Entra ID > Enterprise apps >** your app **> Provisioning**. Set mode to **Automatic** (newer tenants show **+ New configuration**). Under **Admin Credentials** enter **Tenant URL** (the SCIM base URL) and **Secret Token**, select **Test Connection**, then save. Set a **Notification Email** so you hear about quarantine.
- **Okta:** For a catalog app, **Applications and Resources > Applications >** app **> Provisioning > Configure API Integration > Enable API integration**, enter the token, **Test API Credentials**, **Save** ([Okta provisioning](https://help.okta.com/en-us/content/topics/provisioning/lcm/lcm-provision-application.htm)). For a custom SAML app, set **Provisioning** to **SCIM** on the **General** tab, then under **Provisioning > Integration** enter the **SCIM connector base URL**, the **Unique identifier field for users**, the supported provisioning actions and **HTTP Header** authentication with the bearer token ([Okta SCIM wizard](https://help.okta.com/oie/en-us/content/topics/apps/apps_app_integration_wizard_scim.htm)).

**Check:** The connection test succeeds.
**Common failure:** A 401 from an expired or wrong token, or a 404 because the base URL is missing the `/scim/v2` path.
**Rollback:** Clear the credentials or disable API integration; nothing has been pushed yet.

## 2. Review attribute mappings and the matching attribute

- **Entra ID:** **Provisioning > Mappings**, then open the users mapping. Confirm the attribute flagged **Match objects using this attribute**, remove mappings the app rejects, and confirm `active` is mapped (Microsoft documents that `IsSoftDeleted` in the mappings drives the `active = false` update). Uncheck any **Target object actions** (Create, Update, Delete) you do not want.
- **Okta:** In **Provisioning > To App > Attribute Mappings**, choose **Go to Profile Editor**, edit the **Okta User to app** mappings, **Save Mappings**, then **Apply updates now**.

**Check:** Every mapped source attribute is populated for your test users.
**Common failure:** Entra cannot provision null attributes, and multi-valued attributes (two phone numbers mapped to one target) fail at the app with a schema error.
**Rollback:** Restore default mappings. In Entra ID, changing mappings triggers a new initial cycle.

## 3. Scope who is provisioned

- **Entra ID:** Under **Settings**, set **Scope** to **Sync only assigned users and groups**, then assign groups under **Users and groups**. Add attribute [scoping filters](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/define-conditional-rules-for-provisioning-user-accounts) if needed. Entra provisions only direct members of assigned groups, not nested groups.
- **Okta:** Assign groups on **Assignments**. To create the same groups in the app, use **Push Groups > Push Groups > By name** and choose **Create Group** or **Link Group** ([Group Linking](https://help.okta.com/oie/en-us/content/topics/users-groups-profiles/usgp-configure-enhanced-group-push.htm)).

**Check:** Only the test groups are assigned.
**Common failure:** Selecting sync all users and groups provisions the entire tenant.
**Rollback:** Remove the assignment. Expect this to disable the users it had created.

## 4. Turn on the To App actions or start provisioning

- **Okta:** **Provisioning > To App > Edit**, enable **Create Users**, **Update User Attributes** and **Deactivate Users**, then **Save**. Per Okta, Deactivate Users disables the app account when the user is unassigned or deactivated, and reassigning reactivates it.
- **Entra ID:** Validate one user with **Provision on demand** (one user at a time, or a group with up to five members, per [Microsoft](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/provision-on-demand)), then set **Provisioning Status** to **On**.

**Check:** The on-demand result walks through import, scope, match and action with no errors.
**Common failure:** "Not assigned to the application" right after assigning; Microsoft notes a replication delay of a few minutes.
**Rollback:** Set **Provisioning Status** to **Off** (Entra resumes where it left off) or uncheck the To App actions.

## 5. Watch the logs and the quarantine state

Entra ID logs every read and write in **Provisioning logs**. If most calls fail, the job enters [quarantine](https://learn.microsoft.com/en-us/entra/identity/app-provisioning/application-provisioning-quarantine-status): cycles slow to once per day, and after four weeks the job is disabled. Fix the cause, then **Restart provisioning**. In Okta, filter the System Log on `application.provision.user.push`, `application.provision.user.deactivate` and `application.user_membership.remove` ([event types](https://developer.okta.com/docs/reference/api/event-types/)).

**Check:** No quarantine banner on the Provisioning page; no failed events.
**Common failure:** Uniqueness conflicts, where another app account already uses the same email.
**Rollback:** Not applicable; this is monitoring.

## Verify it works

Run a full joiner-mover-leaver test with one test user:

1. **Joiner:** Add the user to an assigned group. Use Provision on demand in Entra ID, or wait for Okta's push. In the app, confirm the user exists with the correct `userName`, name and email, and that sign-in through SSO works.
2. **Mover:** Change the user's department or move them to the second group. After the next cycle, confirm the attribute and group membership changed in the app and the old group's entitlements are gone.
3. **Leaver, unassign:** Remove the user from the group. Expect `active=false` in the app (Entra logs show an update, Okta logs `application.provision.user.deactivate`). SSO must now fail.
4. **Leaver, disable:** Re-add the user, then disable them in the IdP (block sign-in in Entra ID, deactivate in Okta). Expect the same disable. Note Okta sends no deprovisioning event when a user is only suspended.
5. **Sessions:** Before step 3, sign the user in to the app in a separate browser and generate an API token if the app allows it. After deprovisioning, reload the page and call the API. Both must fail. If they still work, the app ignores `active=false` for existing sessions: raise it with the vendor and add a manual session revocation step to offboarding.
6. **Reconcile:** Export the app's user list and compare it to IdP assignments. Accounts in the app with no IdP owner are [orphaned accounts](https://startwithidentity.com/glossary/orphaned-account/), the starting point for [orphaned account abuse](https://startwithidentity.com/techniques/orphaned-account-abuse/).

## Related

- [SCIM](https://startwithidentity.com/glossary/scim/), [provisioning](https://startwithidentity.com/glossary/provisioning/) and [deprovisioning](https://startwithidentity.com/glossary/deprovisioning/)
- [Joiner-mover-leaver](https://startwithidentity.com/glossary/joiner-mover-leaver/)
- [SCIM provisioning implementation guide](https://startwithidentity.com/guides/implementation/scim-provisioning-implementation-guide/)
- [Set up SCIM provisioning (server side)](https://startwithidentity.com/recipes/set-up-scim-provisioning/)
- [Federate AWS IAM Identity Center with Entra ID or Okta](https://startwithidentity.com/recipes/aws-iam-identity-center-federation/)
- [Enforce SSO and disable local logins](https://startwithidentity.com/recipes/enforce-sso-disable-local-logins/)
