SCIM provisioning
Configure SCIM 2.0 (RFC 7644) user and group provisioning from Okta, Microsoft Entra ID, or any SCIM client — endpoints, token, attributes, group-to-role, and deprovisioning.
Pact implements SCIM 2.0 (RFC 7644) so your IdP can create, update, deactivate, and group users automatically. SAML carries the login; SCIM carries the lifecycle. SCIM is optional — JIT provisioning on SAML/OIDC login already creates users — but SCIM adds deprovisioning and group sync, which most enterprises require.
Endpoints
Base URL: https://<your-pact-host>/scim/v2
| Resource | Operations |
|---|---|
/Users | GET (list + filter), GET by id, POST, PUT, PATCH, DELETE |
/Groups | GET (list + filter), GET by id, POST, PUT, PATCH, DELETE |
/ServiceProviderConfig | GET — capability discovery |
/ResourceTypes | GET — User + Group resource types (incl. enterprise extension) |
A tenant-scoped alias is also available at https://<your-pact-host>/v1/tenants/{tenant_id}/scim/v2/Users for IdP wizards that prefer a tenant-in-path URL.
Authentication
Bearer token, one per tenant. Mint it in Pact at Admin → Identity (SCIM):
- Generate token → copy it once (only the SHA-256 hash is stored).
- In your IdP's provisioning settings, set the bearer token and the base URL above.
Rotate by generating a new token and revoking the old one in the same screen. Every issuance/revocation is audited.
Supported user attributes
| SCIM attribute | Pact mapping |
|---|---|
userName | email (primary key for matching) |
name.givenName / name.familyName | given / family name |
displayName | display name |
emails[].value | |
active | true = active, false = deactivated |
externalId | external id (your IdP's stable id) |
locale | locale |
roles[0].value or urn:company-scraper:scim:User:role | Pact role (owner/admin/manager/member/viewer) |
...:enterprise:2.0:User → department | department |
...:enterprise:2.0:User → manager | manager (resolved to a Pact user, tenant-scoped) |
department and manager are read from the standard Enterprise User extension (urn:ietf:params:scim:schemas:extension:enterprise:2.0:User) that Okta and Entra push. A manager.value is resolved to a Pact user only within the same tenant — cross-tenant references resolve to no manager.
Filtering & pagination
- Users support
eq,ne,sw,ew,co,prandand/or/notonuserName,emails,externalId,displayName,name.givenName,name.familyName,active,id, anddepartment. - Groups support the same operators on
displayName,externalId, andid. - Pagination uses
startIndex(1-based) andcount; responses carrytotalResults,itemsPerPage, andstartIndex. ETag/If-Matchis supported for optimistic concurrency on PUT/PATCH.
Groups → roles and personas
Push your IdP groups to /Groups. Map a group to a Pact role via the urn:company-scraper:scim:Group:role extension (or set it in Admin → Identity (SCIM)), and to a persona in the same admin screen. Membership changes recompute each member's effective role: the highest-precedence role across their groups, composed with the user-attribute role. Groups elevate; they never demote.
Group members are returned with absolute $ref URIs (https://<host>/scim/v2/Users/<id>) per RFC 7643.
Deprovisioning
- A SCIM
DELETEor a PATCH/PUT settingactive=falsesoft-deactivates the user: statussuspended,deactivated_atstamped, sessions revoked immediately, and the SAML/OIDC login gate refuses them even with a still-valid IdP session. - The audit trail is retained. True erasure (GDPR) is a separate, deliberate workflow — see Privacy & GDPR.
- Reactivation (
active=true) restores access.
Tenant isolation
The bearer token is the tenant scope. Every read and write is constrained to the token's tenant — a token for tenant A can never list, create, or modify resources in tenant B, including manager references and group members.
Audit
Every SCIM operation is recorded under the scim.user.* and scim.group.* action namespaces (created, updated, deactivated, deleted) and flows into the SOC 2 access-review evidence bundle via the provisioned_via signal.
Testing your connection
Use any SCIM client or a tool like Postman / scim-tester with your token and base URL:
GET /scim/v2/ServiceProviderConfig→ confirms patch/filter/etag support.POST /scim/v2/Userswith a minimal{ "userName": "[email protected]" }→ 201 with a SCIM User body.GET /scim/v2/Users?filter=userName eq "[email protected]"→ 1 result.PATCHwithactive=false→ user deactivates;GETshowsactive: false.