SCIM Provisioning
Gatewyse implements the SCIM 2.0 protocol so your identity provider (IdP) can automatically create, update, deactivate, and role-map users without any manual admin work. SCIM complements SSO: SSO authenticates users at login, while SCIM provisions and lifecycle-manages their accounts and roles out-of-band — an IdP administrator can add a user to a group and have them provisioned into the gateway before they ever sign in.
The SCIM API is mounted at /scim/v2 and every operation is scoped to a single tenant by the bearer token presented on the request.
What SCIM Is For
- Automated onboarding — new users in your IdP are pushed to the gateway on a schedule or in real time, no per-user setup in the admin dashboard.
- Automated offboarding — when a user is removed from the IdP, they are deprovisioned (soft-disabled) in the gateway.
- Role synchronization — IdP group membership maps to gateway roles (see Groups → Roles).
Enabling SCIM
SCIM is authenticated with a per-tenant bearer token. The token is SHA-256 hashed with the same scheme as API keys and only the hash is stored (tenant.scim.tokenHash); the plaintext is shown once at issuance and never persisted. Enabling SCIM (tenant.scim.enabled) and issuing the token are tenant-level operations performed by an administrator.
Configure your IdP’s SCIM integration with:
- Base URL —
https://gateway.example.com/scim/v2 - Authentication — OAuth Bearer Token
- Token — the per-tenant SCIM token issued for the tenant
Every request must carry the token:
curl https://gateway.example.com/scim/v2/Users \ -H "Authorization: Bearer <scim-token>"A request with a missing, malformed, or unrecognized token is rejected with a SCIM 401 error body. Because the token resolves to exactly one tenant, no SCIM operation can ever reach another tenant’s users.
Endpoints
Responses use the application/scim+json media type. The ServiceProviderConfig advertises support for PATCH and filtering, and no support for bulk operations, sort, etag, or changePassword.
| Method | Path | Purpose |
|---|---|---|
GET | /ServiceProviderConfig | Advertised capabilities and auth scheme |
GET | /ResourceTypes | The User and Group resource types |
GET | /Schemas | Supported attribute schemas |
GET | /Users | List users (supports filter, startIndex, count) |
POST | /Users | Provision a new user |
GET | /Users/:id | Fetch a single user |
PUT | /Users/:id | Full replace of the user’s mutable attributes |
PATCH | /Users/:id | Partial update (most commonly toggling active) |
DELETE | /Users/:id | Deprovision (soft-disable) the user |
GET | /Groups | List groups (roles) |
GET | /Groups/:id | Fetch a single group and its members |
PATCH | /Groups/:id | Add or remove group members (assign/unassign a role) |
User Lifecycle
Provisioning
POST /Users creates a user in the calling tenant. The email is taken from userName (or the primary emails entry), name.givenName/name.familyName populate the user’s name, and externalId is stored for future matching. Newly provisioned users receive the tenant’s base user role — role elevation is never driven from the User resource, only through Group membership.
Provisioning is idempotent-safe: if a user with the same email or externalId already exists, the request returns SCIM 409 uniqueness rather than creating a duplicate.
curl -X POST https://gateway.example.com/scim/v2/Users \ -H "Authorization: Bearer <scim-token>" \ -H "Content-Type: application/scim+json" \ -d '{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "userName": "jane@example.com", "externalId": "idp-user-123", "name": { "givenName": "Jane", "familyName": "Doe" }, "active": true }'Updates
PUT /Users/:idreplaces the mutable attributes (userName,externalId,name,active) in full.PATCH /Users/:idapplies partial changes. It accepts both the{ "path": "active", "value": false }and the{ "value": { "active": false } }operation shapes, forreplaceandaddoperations. Recognized attributes areactive,userName,name.givenName,name.familyName, andexternalId; unknown attributes are ignored rather than failing the whole request.
Deprovisioning
Deprovisioning is a soft disable, never a hard delete. Setting active: false (via PATCH or PUT) or calling DELETE /Users/:id moves the user to the DEACTIVATED status. The user record — and with it all audit history and request-log attribution — is preserved. Re-activating the user (active: true) restores access.
# Deprovision via PATCHcurl -X PATCH https://gateway.example.com/scim/v2/Users/<id> \ -H "Authorization: Bearer <scim-token>" \ -H "Content-Type: application/scim+json" \ -d '{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:PatchOp"], "Operations": [{ "op": "replace", "path": "active", "value": false }] }'Groups → Roles
A SCIM Group maps one-to-one to a gateway role; the group’s members are the users holding that role. Listing groups (GET /Groups) returns the tenant’s roles — the seeded system roles plus the tenant’s own custom roles — with displayName set to the role name.
Membership is synchronized with PATCH /Groups/:id:
- An
addoperation with member values assigns the role to those users. - A
removeoperation unassigns it.
curl -X PATCH https://gateway.example.com/scim/v2/Groups/<roleId> \ -H "Authorization: Bearer <scim-token>" \ -H "Content-Type: application/scim+json" \ -d '{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:PatchOp"], "Operations": [ { "op": "add", "value": [{ "value": "<userId>" }] } ] }'Escalation Guard
The super-admin role is never exposed or assignable through SCIM. It is excluded from the GET /Groups listing, and any attempt to PATCH a group that resolves to super-admin is rejected with SCIM 403 mutability. This means a tenant’s IdP — whether misconfigured or compromised — can grant tenant-scoped roles (tenant-admin, org-admin, and so on) through group membership, but can never escalate a user to platform super-admin.
Relationship to SSO
SCIM and SSO are independent and complementary:
- SSO handles authentication — verifying a user’s identity at login and (optionally) re-syncing their roles from IdP group claims on each sign-in.
- SCIM handles provisioning — creating, updating, deprovisioning, and role-mapping accounts out-of-band, independent of whether the user has ever logged in.
Both enforce the same escalation guard: neither path can assign super-admin. Most enterprise deployments run both — SSO for login, SCIM for lifecycle management.