SCIM 2.0 provisioning
OneAnalytics implements SCIM 2.0 for automated user and group provisioning. Pair it with SAML SSO for a complete identity story — SSO authenticates, SCIM manages lifecycle.
Endpoints
Base URL: https://api.analytics.rstglobal.in/scim/v2
| Resource | Verbs |
|---|---|
/Users | GET (list, filter), POST |
/Users/{id} | GET, PUT, PATCH, DELETE (soft) |
/Groups | GET (list, filter), POST |
/Groups/{id} | GET, PUT, PATCH, DELETE |
/ServiceProviderConfig | GET |
/Schemas | GET |
/ResourceTypes | GET |
All responses are application/scim+json and errors follow the SCIM error envelope (not RFC 7807), per the spec.
Authentication
Per-tenant bearer token. Generate in Settings → SCIM → New token. Store in your IdP's SCIM integration config. Tokens can be revoked independently of user passwords.
Provider walkthroughs
Okta: App → Provisioning → Integration → Enable API Integration → paste base URL + bearer token → map attributes → enable Create users, Update user attributes, Deactivate users.
Azure AD: Enterprise Application → Provisioning → Automatic → paste Tenant URL = <base> + Secret Token = <bearer> → Test → map attributes → enable provisioning.
JumpCloud: App → SCIM → enable → paste base + token → map.
Filter grammar
We accept the SCIM filter subset most IdPs emit:
userName eq "ada@example.com"emails.value eq "ada@example.com"displayName sw "Ada"active eq truemembers[value eq "<user_id>"](for Groups)
Compound filters (and, or) on a single attribute work. Nested filters beyond one level are rejected with 400 invalidFilter.
PATCH operations
Full SCIM PATCH path grammar:
{"op": "replace", "path": "displayName", "value": "New Name"}{"op": "add", "path": "members", "value": [{"value": "user-id"}]}{"op": "remove", "path": "members[value eq \"user-id\"]"}
Okta and Azure emit both forms; we handle both.
Soft delete
DELETE /Users/{id} marks the user inactive (active: false) and removes team memberships. The user record is retained for 30 days in case of restore, then hard-deleted. This satisfies most IdPs' "deprovisioning confirmed" check.
Attribute → RLS
Any SCIM attribute becomes available to row-level security as user.attributes.<name>. Custom enterprise attributes (urn:ietf:params:scim:schemas:extension:...) are flattened to their terminal field name.
Troubleshooting
- Okta shows "400 invalidValue" — Okta tries to send
externalIdof type bytea; we require string. Disable that attribute in the mapping. - Azure shows "410 Gone" — We return 410 for a DELETE of an already-deleted user (per the spec). Azure treats this as success; no action needed.