Prerequisites
SCIM is tied to single sign-on: every SCIM connection is bound to one of the workspace’s SSO providers, and every user it pushes is keyed to that provider’s identities. That keying is what makes provisioning and sign-in resolve to the same person — and what prevents one provider from claiming users that belong to another. Configure an SSO provider for the workspace first. In single-workspace deployments the instance’s sign-in providers can be used directly. A token bound to an instance sign-in provider only works while the deployment runs in single-workspace mode and the workspace is the instance’s original one — switching to multi-workspace mode stops it, as does a deployment that still holds workspaces from an earlier multi-workspace configuration. In those cases the workspace needs a token bound to its own SSO provider instead.Connecting your IdP
In Settings → SCIM (workspace admins):- Generate a token, choosing the SSO provider the IdP will push identities for. The secret is shown exactly once — copy it immediately.
- In your IdP’s SCIM (provisioning) settings, set the connector’s base URL to
the SCIM base URL shown on the page (
https://<your-instance>/scim/v2) and authenticate with the token as an OAuth Bearer token. - Enable provisioning in the IdP and assign the users and groups to push.
Usernames and email addresses
Conduit reads two attributes of a pushed user differently:userNameis your IdP’s identifier for the person — Okta’s application username, Entra’suserPrincipalName. It doesn’t have to be an email address. Conduit returns it exactly as your IdP sent it, matches it without regard to case, and requires it to be unique within the workspace.emailscarries the person’s address: the entry marked primary, else theworkone, else the first. This is the address their single sign-on asserts, so it is what joins a provisioned person to their sign-ins. When a push carries noemails, auserNamethat is an email address stands in for it; a push with neither is refused.
emails that your SSO provider sends as the person’s
email claim — Okta and Entra both do by default. If your IdP also sends its
own user id as externalId and as the sign-in subject (Okta does), a
provisioned person’s first sign-in finds their account by that id even when
the addresses differ.
Attributes Conduit keeps
Conduit keeps a user’suserName, name (formatted, givenName,
familyName), displayName, active, emails and externalId, and a
group’s displayName, members and externalId. A user’s name comes back
as your IdP last sent it: a PUT replaces it whole, and a PATCH replaces
the parts it names. The name Conduit displays, which it returns as
displayName, is set by each write that names one — its name.formatted,
else its givenName and familyName together, else its displayName, else
the one half it sends. A PATCH that changes only givenName or only
familyName keeps the other half; a PUT with only one half has only that
half as the name.
A user has one email address, chosen from emails as described above. A
group’s members are users; Conduit returns each with its $ref, and with the
member’s email address as its display.
Anything else your IdP pushes — phone numbers, addresses, a title,
enterprise-extension attributes such as department or manager — is
accepted and ignored, so there’s no need to remove those from your IdP’s
attribute mapping. So are id and meta, which Conduit assigns. Conduit’s
/scim/v2/Schemas endpoint describes the attributes it keeps.
What provisioning does
-
Users pushed by the IdP become members of the workspace. A person who
already signed in through the same SSO provider is recognized, not
duplicated — and someone provisioned before their first sign-in lands on the
same account when they do sign in. Display-name and email changes pushed by
the IdP update the person’s profile, and sign-in follows the new email. An
email that was recycled to a different person in the directory is refused
(it surfaces as a sync error in the IdP and in the audit log) rather than
handing over the previous holder’s account — and for the same reason, an
update that tries to move a provisioned user’s directory identifier
(
externalId) to a different identity is refused; remove and re-provision the user instead. Removing the previous holder in the IdP does not clear this by itself — not even deleting their SCIM resource, after which the record still blocks the address while reading as404to your IdP. The deprovisioned person is still on record in the workspace, so a new hire on their old address keeps being refused. An instance admin resolves it by deleting the previous holder’s account outright (Settings → Instance → Users), after which the next sync provisions the new person cleanly; the sync error and the audit record both say so. This is the one case where a recycled address needs a human — the alternative is quietly giving one person’s history and access to another. - Deactivating or removing a user in the IdP removes them from the workspace, revokes their active sessions, and ends the group memberships and policy grants they held there. Their memberships in other workspaces are untouched, though the session revocation is instance-wide (a session spans workspaces) — they sign in again to keep using the others. If the departing member was the workspace’s last owner, the longest-standing admin is promoted to owner automatically. Reactivating them later restores the group memberships your IdP still asserts, without waiting for a group sync — an IdP pushes group changes as deltas, so it never re-sends a membership its own directory didn’t change. Grants that came from somewhere else do not come back: a group membership an admin added by hand was that admin’s decision to re-make, and a returning member gets it again the same way they got it the first time. A deprovision that would leave the workspace’s remaining members with no owner or admin is refused instead, and surfaces as a sync error in the IdP. The departing person’s sessions are still revoked — their live access ends the moment the directory says they’re gone — so they cannot resolve this themselves, and their IdP has stopped signing them in anyway. An instance admin clears it by promoting another member of that workspace to admin (Settings → Members), after which the IdP’s next sync completes the removal. Give a workspace a second administrator before its first one leaves and the situation never arises. Deprovisioning the workspace’s only member is not refused — there is nobody left to be locked out — and leaves the workspace itself in place for an instance admin to keep or delete.
- Removing a member in Conduit (admin UI or API) also marks them inactive for the IdP, so a later group sync alone doesn’t quietly re-add them — the IdP re-provisions the person only by pushing them as active again, which restores their IdP-pushed group memberships along with the membership itself.
- Groups pushed by the IdP become Conduit groups, usable in access policies like any other group. SCIM manages only the memberships it created: members added manually in the admin UI are never removed by an IdP sync. A pushed group whose name collides with an existing group is rejected rather than adopted — including a group an admin created by hand, so if a sync reports a name conflict, rename or remove one of the two and the next sync succeeds. Names are compared without regard to case, so “Engineering” and “engineering” are the same group name. The audit log records every rejection with the reason, so a wedged group sync is diagnosable from Conduit without reading the IdP’s logs. A pushed group can also set its members’ workspace role: give it a role in Settings → Groups & Policies (see Roles from groups), and the people your directory adds to it hold that role as soon as the push lands, without waiting for them to sign in; removing them from the group takes it away. A push that would leave the workspace with no owner or admin is refused whole, and surfaces as a sync error in the IdP and in the audit log. Provisioned groups are marked SCIM in Settings → Policies. Renaming one there, or changing the members the IdP pushed, lasts only until the next sync reconciles it back — the directory is the source of truth for what it asserts.
What provisioning cannot do
A SCIM token is generated by a workspace admin, so it carries a workspace admin’s authority and no more. The limits that follow from that all surface to the IdP as a sync error rather than silently doing less than was asked:- It cannot deprovision the workspace’s owner. An admin cannot remove the owner by hand either, and removing them would pass ownership to another admin automatically — so a provisioning token must not be a way around that. Transfer ownership to another member first (Settings → Members), and the next sync completes the removal. Unlike the last-administrator refusal above, nothing at all is applied here: the owner’s sessions stay live.
- It cannot change the name or email of someone another provider established. A workspace with several SSO providers shares one SCIM surface — any of its tokens can read the workspace’s resources, manage groups, and deprovision members whichever provider pushed them — but a person’s profile is owned by the provider their identity came from. Those two fields are instance-wide, so a token that could move them would reach into workspaces it has nothing to do with.
- It cannot rename or deprovision an instance administrator. Instance admins operate the whole deployment and pass every workspace check by that role, so nothing scoped to a workspace — an owner acting by hand, or a token one of them generated — may move their profile or end their access. This matters most in single-workspace deployments, where a token can be bound to the instance’s own sign-in provider: the one the operators themselves sign in through. Pushing an instance admin as a new user is still fine (they become a member like anyone else); only the pushes that would change them are refused. If your directory legitimately needs to offboard someone who administers the instance, drop their instance admin role first (Settings → Instance → Users) and the next sync completes.
userName. An
address can legitimately belong to more than one federated identity, but SCIM
requires userName to identify exactly one user, so the second push is refused
rather than leaving your IdP’s match-before-provision lookup with two answers.
Every provisioning change — users provisioned or deprovisioned, groups
created, renamed, or deleted, memberships changed — is recorded in the
workspace audit log, attributed to the SCIM connection’s SSO provider. So is
every push Conduit refuses, with the reason: a refusal repeats on every sync
until someone resolves it, so it belongs where the workspace’s admins will see
it rather than only in the IdP’s own error log.
Troubleshooting a sync
Every SCIM request is described on its trace span, which a workspace’s own OpenTelemetry exporter receives (see Telemetry): the token (scim_token.id) and SSO provider (idp.id) that sent it, its
scim.operation and scim.resource_type, what it changed (scim.changes, the
audit records it wrote, which share its trace), and, when it was refused, the
scim.reason — the same one its audit record carries, such as
email_conflict — and the SCIM error type (scim.error_type). A push your
IdP’s attribute mapping got wrong also says which part of it:
scim.attribute names the attribute a create or replace was refused for,
scim.patch_operations lists each PATCH operation and the attribute it
targets, scim.ignored_attributes the ones Conduit doesn’t keep and skipped,
and a lookup carries its scim.filter and how many scim.results it matched.
Each provisioning event names the token and provider too. Values your
directory sends — addresses, names, what a filter compares against — never
appear in any of them.
The instance logs the same facts as one scim request line per request,
under the same names without the scim. prefix (scim.error_type is
error_type, scim_token.id is scim_token_id): at debug when it serves
one (set CONDUIT_LOG_LEVEL=debug to see a whole sync), at info when it
refuses one your IdP can correct, at warn when it refuses a push someone has
to resolve in Conduit (the push’s audit record says what), and at error when
it fails one. A request whose bearer token is refused never reaches a
workspace — its span and its conduit.scim.auth.failed event go to the
instance’s exporters only, with the reason (token_disabled, idp_disabled,
…).
