ChainLaunch

Pro Feature

SCIM 2.0 Provisioning

SCIM 2.0 user and group provisioning requires ChainLaunch Pro. Learn more about Pro features.

ChainLaunch Pro Feature

SCIM 2.0 user and group provisioning requires ChainLaunch Pro. Learn more about Pro features.

ChainLaunch Pro implements RFC 7643 (SCIM Schema) and RFC 7644 (SCIM Protocol) so your identity provider can create, update, and deprovision ChainLaunch users automatically. Pair SCIM with SAML SSO or OIDC SSO for full identity lifecycle: SSO authenticates active users, SCIM ensures the user list stays in sync.

Why SCIM (and when you need it)

SSO alone provisions a user on first login. That's fine for small teams, but in regulated environments you usually need:

  • Pre-provisioning — users exist in ChainLaunch before their first login (so role mappings are predictable).
  • Deprovisioning — when an employee leaves, their ChainLaunch account is disabled the moment HR removes them from the IdP. No leftover access.
  • Group sync — moving someone from "Operators" to "Admins" in your IdP automatically updates their ChainLaunch role.
  • Audit clarity — every change has an IdP-attributed bearer token tied to it.

If those matter, you want SCIM. If you're a 5-person startup just trying SSO, you can skip this.

What ChainLaunch supports

ChainLaunch advertises its capabilities at GET /scim/v2/ServiceProviderConfig — the same document IdPs read to figure out which patterns to use:

Capability Supported
Patch operations (RFC 7644 §3.5.2) ✅ Yes
Bulk operations ❌ No
Filtering ✅ Yes (limited — see below)
Sorting ❌ No
Change password ❌ No (passwords are SSO-only)
ETag concurrency ❌ No
Authentication OAuth Bearer Token (long-lived)

Resources: User and Group (urn:ietf:params:scim:schemas:core:2.0:User, urn:ietf:params:scim:schemas:core:2.0:Group).

Filters supported on /Users: userName eq "...", externalId eq "...", emails.value eq "...". Filters supported on /Groups: displayName eq "...", externalId eq "...".

Both Okta's nested-object PATCH and Azure AD's path+primitive PATCH shapes are accepted. You don't need to do anything special — ChainLaunch detects the shape per request.

Step 1 — Mint a bearer token

SCIM uses long-lived bearer tokens. You can only see the plaintext once — store it in your IdP immediately.

From the admin UI

Settings → SSO → SCIM Tokens → Mint Token.

Give it a descriptive name (okta-prod, azure-staging) so audit logs are easy to read. Optionally scope the token to a specific SSO provider — that links every SCIM event to that provider's audit trail.

From the API

curl -X POST https://chainlaunch.example.com/api/v1/scim/tokens \
  -H "Authorization: Bearer $ADMIN_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"okta-prod","providerId":1}'

Response:

{
  "id": 7,
  "name": "okta-prod",
  "token": "scim_a1b2c3d4e5f6..."   // store this — it will not be shown again
}

Tokens are stored hashed; revocation is instant. If you suspect a leak:

curl -X DELETE https://chainlaunch.example.com/api/v1/scim/tokens/7 \
  -H "Authorization: Bearer $ADMIN_TOKEN"

The token row stays after revocation so historical audit entries remain resolvable — only future requests are rejected with 401.

Step 2 — Tell your IdP

The SCIM Base URL is:

https://chainlaunch.example.com/scim/v2

Authentication is a single header on every request:

Authorization: Bearer scim_xxxxxxxxxxxxxxxxxxxxxxxxxxxx

Okta

  1. Okta Admin → your ChainLaunch app → Provisioning → Configure API Integration.
  2. Enable API integration.
  3. Base URL: https://chainlaunch.example.com/scim/v2
  4. API Token: the bearer token from Step 1.
  5. Test API Credentials → should succeed.
  6. Save → on the next page enable:
    • Create Users
    • Update User Attributes
    • Deactivate Users
    • Sync Password (leave OFF — ChainLaunch is SSO-only)
  7. To App → Profile mapping: confirm userName, email, givenName, familyName are mapped.
  8. Push Groups → push the groups that drive ChainLaunch role mapping (chainlaunch-admins, etc.).

Microsoft Entra ID (Azure AD)

  1. Entra Admin Center → your ChainLaunch enterprise app → Provisioning → Get started.
  2. Provisioning Mode: Automatic.
  3. Tenant URL: https://chainlaunch.example.com/scim/v2
  4. Secret Token: the bearer token from Step 1.
  5. Test Connection → should succeed.
  6. Mappings → Provision Azure Active Directory Users → review attribute mappings (Azure's defaults work for userName, emails[type eq "work"].value, name.givenName, name.familyName, active).
  7. Mappings → Provision Azure Active Directory Groups → enable.
  8. Settings → Provisioning Status: On.

Azure does an initial full sync on enable and then incremental syncs on a 40-minute cadence by default.

Other IdPs

Any IdP that speaks SCIM 2.0 with bearer-token auth will work. Point it at https://chainlaunch.example.com/scim/v2 with your token, and it'll discover the supported features via /ServiceProviderConfig and /Schemas.

How users land in ChainLaunch

When the IdP creates a user, ChainLaunch:

  1. Persists the user with the IdP-supplied userName, externalId, emails, and active state.
  2. Marks them as pending_approval=1 if a role can't be derived from groups yet (i.e. groups haven't been pushed). They're promoted automatically once a matching group sync arrives.
  3. Reuses the same role-mapping rules as your SSO providers (sso_role_mappings). A user in the chainlaunch-admins IdP group becomes an ADMIN in ChainLaunch.

When the IdP deactivates a user (PUT active=false), ChainLaunch performs a soft-delete: the row stays for audit, the user can no longer log in, and any active sessions are rejected.

A SCIM DELETE (true hard delete) is also supported but most IdPs prefer soft-delete via active=false.

Endpoint reference

All endpoints below require Authorization: Bearer <scim-token>.

Discovery (unauthenticated)

Method Path Purpose
GET /scim/v2/ServiceProviderConfig Capabilities
GET /scim/v2/Schemas Schema definitions
GET /scim/v2/ResourceTypes Available resources

Users

Method Path RFC 7644
GET /scim/v2/Users?filter=userName eq "alice"&startIndex=1&count=100 §3.4.2
POST /scim/v2/Users §3.3
GET /scim/v2/Users/{id} §3.4.1
PUT /scim/v2/Users/{id} §3.5.1
PATCH /scim/v2/Users/{id} §3.5.2
DELETE /scim/v2/Users/{id} §3.6

Groups

Method Path
GET /scim/v2/Groups?filter=displayName eq "..."
POST /scim/v2/Groups
GET /scim/v2/Groups/{id}
PUT /scim/v2/Groups/{id}
PATCH /scim/v2/Groups/{id} (add/remove members supported)
DELETE /scim/v2/Groups/{id}
Method Path Purpose
POST /api/v1/scim/tokens Mint bearer token
GET /api/v1/scim/tokens List tokens (metadata only — no plaintext)
DELETE /api/v1/scim/tokens/{id} Revoke token

Manual smoke test

Once the token is minted you can drive SCIM yourself to verify it works without involving the IdP:

TOKEN="scim_xxxxxxxxxxxxxx"
BASE="https://chainlaunch.example.com/scim/v2"
 
# Discovery
curl -s "$BASE/ServiceProviderConfig" | jq '.patch.supported'
# → true
 
# Create a user
curl -s -X POST "$BASE/Users" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{
    "schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],
    "userName":"alice@example.com",
    "name":{"givenName":"Alice","familyName":"Smith"},
    "emails":[{"value":"alice@example.com","primary":true,"type":"work"}],
    "active":true
  }' | jq
 
# Search
curl -s "$BASE/Users?filter=userName%20eq%20%22alice@example.com%22" \
  -H "Authorization: Bearer $TOKEN" | jq
 
# Soft-delete
curl -s -X PATCH "$BASE/Users/{id}" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/scim+json" \
  -d '{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
       "Operations":[{"op":"replace","value":{"active":false}}]}'

SCIM ↔ SSO interplay

Want SAML/OIDC SCIM
Authenticate logins
Pre-provision before first login
Deprovision on offboarding — (only blocks future logins) ✅ (immediate soft-delete)
Role assignment First-login policy + role rules Group push + same role rules
Audit Login events Provisioning events (with token attribution)

Recommended setup for production:

  1. Configure SSO (SAML or OIDC) with FirstLoginPolicy=reject.
  2. Configure SCIM and push the groups that drive role mappings.
  3. Now ChainLaunch users only exist when the IdP says so, and roles are always in sync.

Troubleshooting

Symptom Cause Fix
401 Unauthorized from IdP test Token wrong/revoked Mint a new token, re-paste
409 uniqueness on create userName already exists This is correct SCIM behavior — Okta/Azure handle it by linking to the existing user
Users created but role is always VIEWER Groups not pushed Push groups from the IdP first; or wait for the next group sync
Azure provisioning shows "Skipped" Attribute mapping is missing required field In Azure: Provisioning → Edit attribute mappings → ensure userName and emails[type eq "work"].value are mapped
User stays pending_approval after creation No role mapping rule matched and no default Either define a * catch-all rule in SSO → Role Mappings, or set the provider's Default Role
ContentType errors in IdP logs IdP expects application/scim+json ChainLaunch always returns application/scim+json; this usually means an upstream proxy is rewriting headers
Filters returning 0 results Filter syntax not supported Only the exact filters above are supported. Other expressions return empty rather than 400.

For deep debugging, every SCIM request is logged via the audit system tagged with the token name — see Audit Logging. Use Settings → SSO → SCIM Tokens → (your token) → Activity to browse activity per token.

Security checklist

  • Tokens are stored only in your IdP's secret store. Never check them into source control or env files committed to repos.
  • Each IdP gets its own token (okta-prod, azure-staging) so audit logs attribute changes correctly.
  • Rotate tokens at least annually, immediately after any compromise of the IdP.
  • Soft-delete (PUT active=false) is preferred over DELETE so the audit trail stays resolvable.
  • Pair SCIM with SSO FirstLoginPolicy=reject for full lifecycle control.

Next steps