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 SCIM | With 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:
| Field | Where you set it | When it applies |
|---|---|---|
| SSO Default Role | SSO config | User isn't in any mapped SCIM group |
| Group → Role mapping | This 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:
- Push Groups has happened — so the
ScimGroupdoc exists in our DB (Step 3 below). - Group Attribute Statement is set on the SAML app — so the SAML assertion carries the
groupsclaim 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:
- Create the
viewersgroup in Okta and add members to it. - Push the group via Okta's Push Groups tab — Controlinfra now has a
ScimGroupforviewers(Step 3). - In Controlinfra, set the
viewersgroup's mapping dropdown to Viewer (Step 4). - Make sure the SAML app's Group Attribute Statement is set to send
groups(one-time setup in SSO config). - A user in the
viewersgroup 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
- In Controlinfra, open Settings → Security → SCIM.
- Expand SCIM Provisioning.
- 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/v2WARNING
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. - Click Generate Token. The plaintext bearer token is shown once; copy it before navigating away. It cannot be retrieved later — only revoked and regenerated.
- 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
Open the SAML application you created during SSO setup → General tab → App Settings → Edit.
Tick Enable SCIM provisioning → Save. The Provisioning tab appears.
Provisioning → Integration → Edit:
- 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>
Click Test Connector Configuration. You should see "Connector configured successfully" and a list of detected features:
Feature Expected 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.
Save.
Provisioning → To App → Edit → tick Create Users, Update User Attributes, Deactivate Users → Save.
Azure AD (Entra ID)
- Enterprise Applications → your Controlinfra app → Provisioning → Get started → Provisioning Mode:
Automatic. - Admin Credentials:
- Tenant URL: paste the SCIM Base URL from Step 1.
- Secret Token: paste the bearer token from Step 1.
- Click Test Connection — Azure should return "Successfully verified".
- Mappings → keep the default user/group attribute mappings (Azure's defaults match SCIM 2.0 standards we expect).
- 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
- Push Groups tab on the application → + Push Groups → Find groups by name.
- Search for the group, select it, and choose Push group memberships immediately → Save.
- Okta posts the group to
POST /api/scim/v2/Groups, including its members. - Back in Controlinfra, Settings → Security → SCIM → expand Group Mappings — the group now appears.
Azure AD — Group provisioning
- Assign the group to the Enterprise app under Users and groups if you haven't already.
- 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, Settings → Security → SCIM → 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
- Group Mappings → click the group row → confirm the user list matches what's in your IdP.
- Have one of those users log out and log back in via SSO.
- Settings → Audit Log → look for an
auth.loginentry withroutingmetadata. Thesourcefield tells you whether they were routed viascim-group:<groupName>or fell back tosso-config-default.
Removing a user
Deprovisioning in the IdP cascades:
| IdP action | Controlinfra effect |
|---|---|
| Unassign user from app | Okta sends PATCH /Users/:id with active: false → user is removed from the org's members list. |
| Delete user in IdP | Okta sends DELETE /Users/:id → same effect. |
| Remove user from a pushed group | Okta sends PATCH /Groups/:id to drop the membership. On the user's next SAML login, group routing re-evaluates and may demote them. |
Troubleshooting
| Symptom | Likely cause |
|---|---|
| Okta "Test Connector Configuration" fails immediately | Wrong 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't | You 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 push | The 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 role | Either 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
- SAML SSO Setup — the auth side of the story.
- Roles & Permissions (RBAC) — what Admin / Member / Viewer can each do.
- Audit Logging — track who did what, including SCIM-driven membership changes.