Guide · SCIM 2.0 · Open identity

Migrate SCIM to 0Trust

Leave paid directory brokers behind. 0Trust is an open control plane with bidirectional SCIM 2.0 for Users and Groups, plus a built-in application gallery comparable to Entra and Okta.

On this page

  1. Why leave paid SCIM providers
  2. How 0Trust SCIM works
  3. Attribute map
  4. Migration paths by provider
  5. Application gallery
  6. Stand up 0Trust SCIM
  7. Dual-run and cutover
  8. Cutover checklist
  9. Scope and limits
  10. API quick reference

Why leave paid SCIM providers

Commercial IdPs sell you the same RFC 7643/7644 protocol wrapped in seat licenses, app catalog surcharges, and outbound connectors you cannot audit. 0Trust implements SCIM as open infrastructure on your plane:

Bidirectional by default

Inbound /scim/v2 for Users and Groups (Bearer) plus outbound push to each gallery/catalog app when access is assigned.

No per-app tax

Bind any SCIM 2.0 endpoint and token on a catalog app. Provisioning is part of the control plane, not a SKU.

Same plane as OIDC

Passkeys, OIDC clients, ZTNA, and directory live together — one operator surface at 0trust.cloud.

Self-host optional

Hosted issuer for most teams; container self-host via tunneltug.com/hub when you need the stack on your metal.

Typical outcome: HR or legacy IdP remains a temporary source of truth (inbound SCIM into 0Trust), while 0Trust becomes the identity provider for SSO and the provisioner for apps (outbound SCIM). After cutover, the paid broker is decommissioned.

How 0Trust SCIM works

Inbound (you are the SCIM server)

Upstream systems — Okta, Entra ID, Google, Auth0, Ping, OneLogin, JumpCloud, Workday connectors, or a temporary dual-run from another IdP — push Users and Groups to:

https://0trust.cloud/scim/v2
Content-Type: application/scim+json
Authorization: Bearer 

Supported resources: User and Group (create, read, replace, patch, delete, filtered list, member ops). Auth scheme: OAuth Bearer token generated and rotated in the SCIM console.

Outbound (you are the SCIM client)

When an operator assigns a user to a catalog app (or queues a manual provision), 0Trust POSTs a SCIM User to that app's endpoint:

POST {scim_endpoint}/Users
Authorization: Bearer {app scim_token}
Content-Type: application/scim+json

{
  \"schemas\": [\"urn:ietf:params:scim:schemas:core:2.0:User\"],
  \"userName\": \"\",
  \"active\": true,
  \"name\": { \"givenName\": \"...\", \"familyName\": \"...\" }
}

Configure per app in SCIM Console → Outbound Integration (scim_endpoint + scim_token).

Roles in a migration

RolePaid provider todayAfter 0Trust
SSO / OIDC issuerOkta / Entra / Auth00trust.cloud
Inbound directoryHR → paid IdPHR or paid IdP → 0Trust /scim/v2
Outbound app SCIMPaid IdP connectors0Trust catalog apps
Access policyIdP groups / rulesIAM assignments + RBAC/ABAC

Attribute map

Keep mappings simple so dual-run stays deterministic. Required outbound identity attribute: email (maps to userName).

SCIM (RFC)0Trust identityNotes
userNameUsername / emailRequired; uniqueness enforced inbound
emails[primary].valueEmailPrimary email preferred
name.givenNamegiven_nameOutbound optional
name.familyNamefamily_nameOutbound optional
displayNameDisplay nameInbound; falls back to given+family
activeEnabled / statusfalse deprovisions access path
externalIdSCIM external linkPreserve during import for idempotent re-sync
Groups: SCIM Groups are supported inbound (CRUD + member patch) and outbound (queue group provision). Bulk remains limited. Use the application gallery for Entra/Okta/Google/Auth0/Ping tiles.

Migration paths by provider

Patterns below assume you want 0Trust as the long-term IdP. Adjust if you only need 0Trust as a SCIM spoke.

Okta

Microsoft Entra ID (Azure AD)

OneLogin / JumpCloud / Ping

Auth0 / other OIDC-only brokers

HR-first (Workday, BambooHR, etc.)

Stand up 0Trust SCIM

1

Register and enroll

Submit a company registration at /start. After approval, complete passkey enrollment and sign in to the operator plane.

2

Enable inbound

Open /scim → Inbound Server. Enable inbound, generate a Bearer token (shown once), and store it in your secret manager. Base path: /scim/v2.

3

Smoke-test inbound

curl -sS -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/scim+json\" \\
  https://0trust.cloud/scim/v2/ServiceProviderConfig

curl -sS -X POST -H \"Authorization: Bearer $TOKEN\" -H \"Content-Type: application/scim+json\" \\
  https://0trust.cloud/scim/v2/Users \\
  -d '{\"schemas\":[\"urn:ietf:params:scim:schemas:core:2.0:User\"],\"userName\":\"pilot@example.com\",\"name\":{\"givenName\":\"Pilot\",\"familyName\":\"User\"},\"emails\":[{\"value\":\"pilot@example.com\",\"primary\":true}],\"active\":true}'
4

Register apps and outbound SCIM

In IAM, ensure each SaaS app exists in the catalog. In SCIM Console → Outbound Integration, set scim_endpoint (vendor SCIM base, no trailing /Users) and scim_token. Assign a pilot user and confirm the vendor received the User.

5

Point SSO at 0Trust

Create OIDC clients (or use existing app faces) with issuer https://0trust.cloud. Update redirect URIs on the SaaS side. Prefer passkeys for operators; keep enrollment invites for end users.

Dual-run and cutover

Do not flip every app on day one. Run paid provider and 0Trust in parallel until reconciliation is boring.

  1. Inventory: List every SCIM target and whether it is SSO-only, SCIM-only, or both.
  2. Import: Push a pilot OU/group from the paid IdP into 0Trust inbound; fix mapping errors before full org.
  3. Shadow provision: For one non-critical app, disable paid outbound and enable 0Trust outbound; compare user counts.
  4. SSO cutover: Move relying parties to 0trust.cloud issuer in batches; keep paid IdP login as break-glass if needed.
  5. Full directory: Expand inbound filter to entire workforce; freeze paid IdP user creates that are not mirrored.
  6. Decommission: Revoke paid SCIM tokens, remove app assignments there, export final audit, cancel seats.
Reconciliation tip: Use the SCIM audit trail on /scim and compare userName/externalId sets against the paid provider export. Prefer soft-deactivate (active: false) before hard DELETE until you trust reverse sync.

Cutover checklist

DoneItem
Company approved; admin passkey enrolled
Inbound SCIM enabled; token stored offline; rotate plan documented
ServiceProviderConfig / Users smoke tests green
Attribute map reviewed with HR/IT (email uniqueness)
Pilot cohort synced inbound; no unexpected duplicates
Each critical SaaS app has catalog entry + outbound SCIM
Pilot assign → vendor user created; deprovision path tested
OIDC issuer switched for pilot apps; JWKS validated
Group/role → policy grants mapped (manual or workflow)
Break-glass admin path independent of paid IdP
Paid provider provisioning jobs disabled
Tokens revoked; licenses cancelled; runbook updated

Scope and limits

API quick reference

Inbound (Bearer)

GET    /scim/v2/ServiceProviderConfig
GET    /scim/v2/ResourceTypes
GET    /scim/v2/Schemas
GET    /scim/v2/Users
POST   /scim/v2/Users
GET    /scim/v2/Users/{id}
PUT    /scim/v2/Users/{id}
PATCH  /scim/v2/Users/{id}
DELETE /scim/v2/Users/{id}
GET/POST /scim/v2/Groups
GET/PUT/PATCH/DELETE /scim/v2/Groups/{id}
GET /api/v1/scim/catalog
POST /api/v1/scim/catalog/{id}/install

Operator (session / admin)

GET  /api/v1/scim/status
GET  /api/v1/scim/config
GET  /api/v1/scim/inbound
PUT  /api/v1/scim/inbound
GET  /api/v1/scim/integrations
PUT  /api/v1/scim/integrations/{app_id}
POST /api/v1/scim/provision
GET  /api/v1/scim/audit

Operators manage tokens and integrations in the SCIM Console. Developers integrating OIDC stay on 0trust.codes docs.

Next steps

Start company registrationOpen SCIM consoleBack to marketing homeSelf-host container