PPactDocs
Security & Privacy

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

ResourceOperations
/UsersGET (list + filter), GET by id, POST, PUT, PATCH, DELETE
/GroupsGET (list + filter), GET by id, POST, PUT, PATCH, DELETE
/ServiceProviderConfigGET — capability discovery
/ResourceTypesGET — 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):

  1. Generate token → copy it once (only the SHA-256 hash is stored).
  2. 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 attributePact mapping
userNameemail (primary key for matching)
name.givenName / name.familyNamegiven / family name
displayNamedisplay name
emails[].valueemail
activetrue = active, false = deactivated
externalIdexternal id (your IdP's stable id)
localelocale
roles[0].value or urn:company-scraper:scim:User:rolePact role (owner/admin/manager/member/viewer)
...:enterprise:2.0:Userdepartmentdepartment
...:enterprise:2.0:Usermanagermanager (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, pr and and/or/not on userName, emails, externalId, displayName, name.givenName, name.familyName, active, id, and department.
  • Groups support the same operators on displayName, externalId, and id.
  • Pagination uses startIndex (1-based) and count; responses carry totalResults, itemsPerPage, and startIndex.
  • ETag / If-Match is 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 DELETE or a PATCH/PUT setting active=false soft-deactivates the user: status suspended, deactivated_at stamped, 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/Users with a minimal { "userName": "[email protected]" } → 201 with a SCIM User body.
  • GET /scim/v2/Users?filter=userName eq "[email protected]" → 1 result.
  • PATCH with active=false → user deactivates; GET shows active: false.