Skip to content

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 URLhttps://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:

Terminal window
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.

MethodPathPurpose
GET/ServiceProviderConfigAdvertised capabilities and auth scheme
GET/ResourceTypesThe User and Group resource types
GET/SchemasSupported attribute schemas
GET/UsersList users (supports filter, startIndex, count)
POST/UsersProvision a new user
GET/Users/:idFetch a single user
PUT/Users/:idFull replace of the user’s mutable attributes
PATCH/Users/:idPartial update (most commonly toggling active)
DELETE/Users/:idDeprovision (soft-disable) the user
GET/GroupsList groups (roles)
GET/Groups/:idFetch a single group and its members
PATCH/Groups/:idAdd 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.

Terminal window
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/:id replaces the mutable attributes (userName, externalId, name, active) in full.
  • PATCH /Users/:id applies partial changes. It accepts both the { "path": "active", "value": false } and the { "value": { "active": false } } operation shapes, for replace and add operations. Recognized attributes are active, userName, name.givenName, name.familyName, and externalId; 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.

Terminal window
# Deprovision via PATCH
curl -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 add operation with member values assigns the role to those users.
  • A remove operation unassigns it.
Terminal window
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.