Skip to content

SCIM Provisioning Enterprise

SCIM (System for Cross-domain Identity Management) lets your IdP push users and groups into Controlinfra automatically — no manual invitation flow, and groups in your IdP can map directly to roles in your Controlinfra org.

This page assumes you already have SAML SSO working. SAML handles authentication; SCIM handles provisioning.

What SCIM does for you

Without SCIMWith SCIM
First login auto-creates the user with the SSO Default Role.The user already exists in the org before their first login.
Role changes are manual (Members tab).Group memberships in your IdP map to roles via the Group Mappings UI.
Removing a user from your IdP doesn't touch Controlinfra.Deprovisioning the user in your IdP removes their org membership.

Group routing is scoped to the org that owns the SSO config. A user authenticating through your IdP cannot be auto-added to some other tenant's org just because that other tenant happens to have a SCIM group with the same name.

How role assignment works

There are two role-related fields, and they cover different cases — they don't compete:

FieldWhere you set itWhen it applies
SSO Default RoleSSO configUser isn't in any mapped SCIM group
Group → Role mappingThis page (Group Mappings UI)User is in a pushed SCIM group with a role mapping set

On every SAML login, role assignment runs two stages:

Stage 1: SCIM group routing
  ├─ Does the SAML assertion carry a `groups` claim?
  ├─ AND does any value match a pushed ScimGroup in this org?
  │   YES → use that group's mappedRole.
  │         Reconciles role on EVERY login (source of truth).
  │   NO  → fall through.
  └─
Stage 2: SSO Default Role
  └─ Only on first login. Doesn't overwrite an existing user's role.

If a user matches multiple SCIM groups with different mapped roles (e.g. engineers → Member and eng-admins → Admin), the highest-privilege role wins. Order: viewer < member < admin < owner.

Two separate Okta configs needed

For SCIM group routing to fire on login, both must be true in Okta:

  1. Push Groups has happened — so the ScimGroup doc exists in our DB (Step 3 below).
  2. Group Attribute Statement is set on the SAML app — so the SAML assertion carries the groups claim at login time (see SSO Setup › Step 1.6).

If only #1 is done, the group appears in the Mappings UI but routing falls back to the SSO Default Role at login. This is the single most common source of "the mapping is set but the user still has the wrong role" confusion.

Worked example

You want users in the Okta viewers group to land as Viewer in Controlinfra:

  1. Create the viewers group in Okta and add members to it.
  2. Push the group via Okta's Push Groups tab — Controlinfra now has a ScimGroup for viewers (Step 3).
  3. In Controlinfra, set the viewers group's mapping dropdown to Viewer (Step 4).
  4. Make sure the SAML app's Group Attribute Statement is set to send groups (one-time setup in SSO config).
  5. A user in the viewers group logs in via SSO → routing finds the group → they're set to Viewer. The SSO Default Role is not consulted for this user.

Prerequisites

  • SAML SSO is configured and tested for the org.
  • Owner or Admin role in Controlinfra.
  • Admin access to your IdP's SCIM provisioning settings.

Step 1 — Generate a SCIM token

  1. In Controlinfra, open SettingsSecuritySCIM.
  2. Expand SCIM Provisioning.
  3. Note the SCIM Base URL at the top of the panel — it's the value to give your IdP. It looks like:
    https://api.controlinfra.com/api/scim/v2

    WARNING

    Use the API host (api.controlinfra.com), not the app host. The app host serves the SPA and doesn't speak SCIM — pointing your IdP there will return HTML and fail validation.

  4. Click Generate Token. The plaintext bearer token is shown once; copy it before navigating away. It cannot be retrieved later — only revoked and regenerated.
  5. Optional: generate multiple tokens with descriptive labels (e.g. okta-prod, okta-staging) so you can revoke one without breaking the other.

Step 2 — Configure the SCIM connector in your IdP

Okta
  1. Open the SAML application you created during SSO setupGeneral tab → App SettingsEdit.

  2. Tick Enable SCIM provisioningSave. The Provisioning tab appears.

  3. ProvisioningIntegrationEdit:

    • SCIM connector base URL: paste the SCIM Base URL from Step 1.
    • Unique identifier field for users: userName
    • Supported provisioning actions: tick Push New Users, Push Profile Updates, Push Groups.
    • Authentication Mode: HTTP Header
    • HTTP Header → Authorization: Bearer <token from Step 1>
  4. Click Test Connector Configuration. You should see "Connector configured successfully" and a list of detected features:

    FeatureExpected
    Create Users
    Update User Attributes
    Push Groups
    User Import / Import Profile Updates / Import Groups✗ (expected — Controlinfra is the consumer, not the source of truth)

    Red marks on the Import features are normal. They're only relevant if you want Okta to pull state from Controlinfra — not the typical setup.

  5. Save.

  6. ProvisioningTo AppEdit → tick Create Users, Update User Attributes, Deactivate UsersSave.

Azure AD (Entra ID)
  1. Enterprise Applications → your Controlinfra app → ProvisioningGet startedProvisioning Mode: Automatic.
  2. Admin Credentials:
    • Tenant URL: paste the SCIM Base URL from Step 1.
    • Secret Token: paste the bearer token from Step 1.
  3. Click Test Connection — Azure should return "Successfully verified".
  4. Mappings → keep the default user/group attribute mappings (Azure's defaults match SCIM 2.0 standards we expect).
  5. Save and turn Provisioning Status to On.
Other IdPs

The SCIM endpoint is standard SCIM 2.0 with bearer-token auth. Any compliant IdP works. The two values you'll need from Controlinfra:

  • Base URL: https://api.controlinfra.com/api/scim/v2
  • Bearer token: from Step 1.

Step 3 — Push a group

Assigning a group to your IdP app gives its members access. Pushing the group via SCIM is a separate, explicit action — without it, the group itself never lands in Controlinfra.

Okta — Push Groups
  1. Push Groups tab on the application → + Push GroupsFind groups by name.
  2. Search for the group, select it, and choose Push group memberships immediatelySave.
  3. Okta posts the group to POST /api/scim/v2/Groups, including its members.
  4. Back in Controlinfra, SettingsSecuritySCIM → expand Group Mappings — the group now appears.
Azure AD — Group provisioning
  1. Assign the group to the Enterprise app under Users and groups if you haven't already.
  2. With provisioning on, Azure posts the group on its next sync cycle (usually within 40 minutes; you can also click Provision on demand for a single user/group to test).

Step 4 — Map groups to roles

In Controlinfra, SettingsSecuritySCIM → expand Group Mappings. You'll see one row per pushed IdP group, each with:

  • Group name + member count badge.
  • The IdP's group ID as a small mono-font string.
  • A role dropdown — Admin / Member / Viewer.

Pick the role that everyone in this IdP group should have in your org. Click any row to expand and see the actual users in the group (with Pending login badges for users who've been pushed via SCIM but haven't yet logged in via SAML).

Group mapping is the source of truth

If you change a group's mapping from Member to Admin, all users in that group are reconciled to Admin on their next login — automatically. Editing a user's role manually on the Members tab works, but it gets reconciled back to whatever the group mapping says on the next login. See How role assignment works for the full precedence model.

Step 5 — Verify

  1. Group Mappings → click the group row → confirm the user list matches what's in your IdP.
  2. Have one of those users log out and log back in via SSO.
  3. SettingsAudit Log → look for an auth.login entry with routing metadata. The source field tells you whether they were routed via scim-group:<groupName> or fell back to sso-config-default.

Removing a user

Deprovisioning in the IdP cascades:

IdP actionControlinfra effect
Unassign user from appOkta sends PATCH /Users/:id with active: false → user is removed from the org's members list.
Delete user in IdPOkta sends DELETE /Users/:id → same effect.
Remove user from a pushed groupOkta sends PATCH /Groups/:id to drop the membership. On the user's next SAML login, group routing re-evaluates and may demote them.

Troubleshooting

SymptomLikely cause
Okta "Test Connector Configuration" fails immediatelyWrong base URL (often pointing at the app host instead of the API host) or wrong bearer token. The IdP usually surfaces the HTTP status — 401 is a token problem, 404 is a wrong URL.
Connector test passes, but Test Connection returns "Invalid JSON"Most often: deployment hasn't picked up your latest backend changes. Force a redeploy and retry.
Users push successfully, groups don'tYou have to push groups (Push Groups tab), not just assign them. Assignment grants access; push syncs the group itself.
Group appears with 0 members after pushThe IdP's group has no members assigned, or the assignment hasn't synced yet. Re-trigger sync from the IdP.
User logs in but lands in the SSO default role, not the group's roleEither the group hasn't been mapped to a role yet (dropdown is still on default), or the IdP's group attribute statement isn't being delivered in the SAML assertion (different from the SCIM push — see SSO setup Step 1.6).

Next steps