Skip to main content

Rolter speaks SCIM 2.0, so your identity provider can create, update, and deactivate Rolter accounts — and push its groups — without anyone touching the dashboard. You issue a provisioning token for the org, paste it into the IdP’s SCIM connector, and the IdP does the rest on its own schedule.

The direction of control matters: the identity provider drives provisioning, Rolter receives it. The dashboard never calls the SCIM endpoints. What you manage in Governance → User Provisioning is the credential the IdP authenticates with — issuing one, seeing when it last synced, and revoking it — and the address it connects to, which the screen shows so you never assemble it by hand.

What a provisioning token is#

A provisioning token is an opaque bearer credential scoped to exactly one org.

Info

The token carries the tenant. There is no org id anywhere in the SCIM URL, which means a token issued for one org physically cannot address another org’s users — even if the IdP is misconfigured.

Issuing, listing, and revoking tokens all require the admin role on the org (see RBAC). A member or viewer sees an explanation instead of the token list.

Wire up an identity provider#

Issue a token

Open Governance → User Provisioning and choose Issue token. Name it after the connector it will live in — Okta production, Entra staging — because that name is the only thing that identifies it afterwards.

Copy the token and the base URL

The plaintext value is displayed exactly once, in the panel that opens right after creation. Rolter stores only a peppered SHA-256 digest of it, so the value cannot be displayed or recovered later — not by you, not by support, not from a database dump. If you lose it, issue a new token and revoke the old one.

Closing the panel before you have copied the token asks “Close without copying?”, since the token cannot be shown again; Cancel keeps it open. If the browser will not let the page use the clipboard, which is common on a dashboard served over plain http, the panel says the copy failed in a message that stays, and the token stays on screen, selected, so you can copy it by hand with Ctrl+C or Cmd+C.

The same panel shows the SCIM base URL under the token, with its own copy button, so the two values the connector needs are in one place. The URL stays on the screen above the token list afterwards, and is the same for every token in the org.

Configure the connector

In your identity provider, set the SCIM base URL to the value you copied, which looks like https://rolter.example.com/scim/v2, and the authentication mode to HTTP header / bearer token, using the token. Enable create users, update user attributes, and deactivate users — and push groups if you plan to drive roles from group membership.

The host part is the control plane’s public URL, ROLTER_PUBLIC_URL, as the server reports it through GET /api/v1/public-url. It is not the address your browser happens to be using: the identity provider calls Rolter from outside, often under a different name than the one you open the dashboard at, and a wrong base URL fails in the provider’s own test console without any hint from Rolter.

Warning

If ROLTER_PUBLIC_URL is not set, the control plane falls back to http://localhost:4001, which an identity provider can reach only if it runs on the control plane’s own host. The screen shows that default with a warning under the URL and under the URL in the token panel. Set ROLTER_PUBLIC_URL to an address your identity provider can call and restart the control plane before you paste the URL into the connector.

Push a test user

Assign one person to the Rolter application in the IdP and run a sync. They appear under Governance → Users, and the token’s Last sync column changes from never used to today’s date on the next request. The token list shows dates only; hover one for the exact time.

What provisioning does and does not grant#

A provisioned account is deliberately minimal:

  • It joins the org with the viewer role, merely for existing. SCIM decides who exists; anything beyond a read comes from a group mapping you wrote (see Map groups to teams).

  • It has no local password. A password attribute sent by the IdP is ignored rather than stored — provisioned accounts are SSO-shaped by construction.

  • Deactivating a user through SCIM also drops their live sessions, so a leaver disabled in the IdP is logged out of Rolter rather than merely blocked from signing in again.

  • A SCIM DELETE deactivates the account and removes the org’s identity mapping, but keeps the underlying user row: its memberships and audit trail have to outlive any one IdP. Re-provisioning the same person adopts the existing account instead of creating a duplicate. When that create carries active: false and the deactivation is refused (see below), nothing is linked, so the IdP’s retry gets the same 409 rather than a userName conflict.

  • Deactivating or deprovisioning the deployment’s last active superadmin is refused with 409, the same as from the dashboard, so an IdP sync cannot leave nobody able to administer the deployment. Make another account superadmin first.

  • Deactivating or deprovisioning an account that holds an organization’s last active admin grant is refused with a SCIM 409 too, for every organization the account administers, not only the one the token belongs to. The provisioning token cannot repair an organization afterwards the way a superadmin can, so the IdP is told and retries. Grant admin to another person first.

  • Its display name comes from the IdP. SCIM displayName is copied onto the account on every create and replace, and the account cannot change it from the dashboard or PATCH /api/v1/me/profile (the API answers 409); GET /api/v1/auth/me reports display_name_managed: true. An IdP that sends no displayName leaves the stored name as it was. The account’s bio stays its own. A PUT with active: false that is refused because the account is the last active superadmin (409) applies none of its other changes, so the account keeps its userName, externalId and display name. The account stores the name with surrounding whitespace and control characters removed and cut to 80 characters, while the SCIM resource returns displayName exactly as your IdP sent it, so the IdP’s reconciliation sees its own value and does not push it again on every sync.

  • A PATCH carrying displayName renames the account the same way, and if two organizations provision the same account the most recent sync from either decides the name.

Every provisioning action is written to the audit log with the token id as the actor, since the change was made by a machine and not by a person. Issuing and revoking a token are operator actions and name the operator instead: the token’s created by field and the scim_token.create entry carry the account that issued it, including a superadmin who holds no role in the org. A token issued with the admin token, or in open mode, names nobody. See who an entry names as the actor.

Supported operations#

OperationEndpointNotes
List / search usersGET /scim/v2/UsersSupports the userName eq "value" filter that IdPs use for reconciliation; other filters are rejected explicitly rather than silently ignored
Create userPOST /scim/v2/UsersIdempotent — a replayed create returns a uniqueness conflict instead of a second account
Read userGET /scim/v2/Users/{id}
Replace userPUT /scim/v2/Users/{id}
Patch userPATCH /scim/v2/Users/{id}The active and displayName attributes, in both the path and bare-value shapes IdPs send; any other attribute is rejected. A patch that deactivates and renames is applied all-or-nothing
DeprovisionDELETE /scim/v2/Users/{id}Deactivates and unmaps; the account row survives, and its group-granted roles go with the identity
List / search groupsGET /scim/v2/GroupsSupports the displayName eq "value" filter
Create groupPOST /scim/v2/GroupsIdempotent — a replayed create returns a uniqueness conflict
Read groupGET /scim/v2/Groups/{id}
Replace groupPUT /scim/v2/Groups/{id}Replaces the member list wholesale
Patch groupPATCH /scim/v2/Groups/{id}Member add / remove / replace in every shape IdPs send, plus displayName and externalId
Delete groupDELETE /scim/v2/Groups/{id}Removes the group and everything it granted

Map groups to teams#

A group arriving from your identity provider grants nothing on its own. You decide what it is worth, by writing a mapping — the identity provider never gets to name a role.

Governance → User Provisioning carries a Group mappings panel under the token list. Type the group’s display name, pick where the role applies — the whole organization, a team, or a project — pick the role, and press Map group. The scope list covers the whole organization: every team, and every project in any of those teams grouped under the team it belongs to, so a mapping onto a project outside the team the scope switcher currently shows needs no detour through the switcher. An organization with no teams yet says so, and offers only itself. Role to grant starts on viewer, the least powerful role, and the scope starts on the whole organization. A mapping that grants admin, or grants at the whole organization, is confirmed before it is written: the dialog names the group, the role and the scope, says that everyone in that group at your identity provider gets the role straight away, and lists what raised it (the role, the scope, or both). A member or viewer mapping on one team or one project saves without asking. Once a mapping is written, the form goes back to viewer on the whole organization. The panel lists every mapping the org has with its scope and role, and removing one asks first, because it withdraws that role from everyone in the group. A mapping whose team or project cannot be named — the row was deleted, or the account reading the page cannot see it, or the list failed to load — is marked Unresolved scope rather than shown as a bare id, and hovering it gives the stored id to quote in a support request. Until a mapping exists the panel says so plainly: the groups your IdP pushes grant nothing, and every provisioned account stays a viewer.

The same thing over the API:

  • group_name is the group’s display name as your IdP shows it.
  • role is one of admin, member, viewer — the same three roles RBAC defines. Nothing else is mappable.
  • Name a team_id or a project_id to grant at that scope; omit both to grant at the org.
  • The scope must belong to the same org. A mapping cannot reach another tenant’s team, whatever the IdP sends.

This is the same model single sign-on uses for its group mappings, so you only learn it once.

Info

Mappings key on the group’s display name. If you rename a group in the identity provider, rewrite the mapping too — otherwise the old name simply stops matching and the roles it granted are withdrawn on the next sync.

You can write a mapping before the group has ever been pushed. Creating or deleting one takes effect immediately for whoever is already in that group, rather than waiting for the next sync.

What a sync does to roles#

Every group change recomputes the affected people’s provisioning-granted roles from scratch:

  • Running the same sync twice changes nothing.
  • Removing someone from a group revokes exactly what that group gave them, right away.
  • A role you granted by hand — in the dashboard, through the API, or through an invitation — is never touched by a sync. Manual and provisioned grants coexist.
  • Deleting a group, or deprovisioning a user, withdraws the roles involved in the same request.
  • The one exception is an organization’s last active admin grant: a sync that would withdraw it keeps it, still answers success, and records membership.last_admin_kept in the audit log. The next sync that touches that person withdraws it once someone else holds admin on the organization. Deleting a group mapping from the dashboard or the API follows the same rule for an org admin, but a superadmin deleting the mapping withdraws even the last admin grant, exactly as a superadmin revoking it directly would.
Warning

Because a mapping is a way to grant a role, creating or deleting one requires the admin role on the org — the same bar as granting a role directly.

Rotating and revoking a token#

Revocation takes effect on the very next request — the token is resolved from the database on every call, so there is no cache to wait out.

Warning

Revoking a token stops the sync. It does not touch the accounts that token already provisioned: nobody is deactivated, nobody is logged out, and no membership is removed. Those accounts simply stop receiving updates from the IdP until you point it at a new token.

To rotate without a gap in coverage:

  1. Issue a second token and copy it.
  2. Update the connector in the identity provider to use the new value.
  3. Run a sync and confirm the new token’s Last sync moves from never used to a date (hover it for the exact time).
  4. Revoke the old token.

If you need to cut off an identity provider immediately — a compromised connector, for example — revoke the token first and deactivate the affected accounts from Governance → Users separately. Revocation alone is not a way to lock people out.