Skip to main content

SCIM setup — Okta

Okta is a Certified vendor. The integration is listed in the Okta Integration Network (OIN) once the submission package (§8 pre-GA) is approved.

Prereqs

  • MOD tenant on a plan with scim_enabled = true (Enterprise tier).
  • Okta admin access.
  • A SCIM bearer token created in MOD Dashboard → Admin → SCIM tab (it's shown once at creation — copy it then).

Steps

1. Configure the connector

In Okta:

  1. Applications → Browse App Catalog → search "MOD" (once OIN listed) OR Applications → Create App Integration → SAML 2.0 + SCIM.
  2. Provisioning tab → Configure API Integration.
  3. Set the SCIM connector endpoint to:
    https://api.modtechlabs.com/scim/v2
  4. Bearer Token: paste the plaintext from MOD's "Create token" modal.
  5. Click Test API Credentials.
  6. Expected: "MOD SCIM provisioning was verified successfully."

2. Map attributes

Default mapping is sufficient for v1:

Okta attributeMOD attributenotes
userNameuserNameusually email
name.givenNamename.givenName
name.familyNamename.familyName
profileUrl(ignored)not stored
emailemails[type=work].valueMOD treats this as the primary email
externalIdexternalIdopaque

If using tenantRole (custom extension):

  1. Add a custom attribute under your Okta directory schema: mod_tenant_role (string).
  2. In MOD Dashboard → Admin → SCIM mapping, map your Okta group → the MOD permission template.
  3. Setting mod_tenant_role directly via PUT/PATCH is an alternative to group-driven role assignment.

3. Enable provisioning

  1. Provisioning tab → To App.
  2. Enable: Create Users, Update User Attributes, Deactivate Users.
  3. Save.

4. Assign users + groups

  1. Assignments tab → assign individual users or groups.
  2. Expected (for users): MOD receives POST /scim/v2/Users for each. New users appear in Dashboard → Users.
  3. Expected (for groups): MOD receives POST /scim/v2/Groups + PATCH .../Groups/{id} for each membership change.

5. Verify in MOD

  • Dashboard → Admin → SCIM → Activity tab.
  • Filter to "Last hour" + status_class "success" → you should see a trail of 201s and 200s matching what Okta sent.
  • Failed assignments appear in the Failed (grouped) sub-tab grouped by (external_id, error_detail).

6. Test deactivation

  1. In Okta, unassign a user from the integration.
  2. Expected in MOD: PATCH /Users/{id} with active=false then DELETE /Users/{id} within ~30 seconds.
  3. MOD soft-deletes (status = INACTIVE, deleted_at stamped).
  4. The 5-min reconcile sweep disables the Keycloak user. The next login attempt by that user returns "Account disabled."

Known Okta-specific behaviours

See the vendor compat matrix for the full list. Highlights:

  • Full-replacement PUT on Groups — Okta sends the full members[] on every push. MOD handles it by recomputing roles for the affected set (the union of the old and new members). No tuning needed.
  • 5xx retry storm — Okta retries on 5xx every 30s for 24h. MOD's idempotency cache prevents duplicate users.
  • Per-app license enforcement — Okta's "Assign" action triggers provisioning. If MOD's seat limit denies, Okta marks the assignment as "Pending push" and retries hourly until the limit is raised.

Troubleshooting

symptomlikely causefix
"Failed: 401 Unauthorized"Token revoked or rotatedGenerate a fresh token; paste into Okta
"Failed: 402 Payment Required"Plan downgraded; SCIM disabledUpgrade plan to Enterprise tier
"Failed: 429 Too Many Requests"Burst rate-limit hitWait per Retry-After; lower Okta's batch size
"Failed: 409 Conflict on POST"Email belongs to another tenant on MODContact MOD support (no leak by design)
"Failed: 400 invalidValue tenantRole"Mapping page hasn't been configured yetDashboard → Admin → SCIM Mapping; pick role

Screenshots

See CORE/docs-site/docs/assets/scim-okta-*.png (see the Phase E §7.3 CI check below).