SCIM 2.0
Authrim supports SCIM 2.0 (System for Cross-domain Identity Management) for automated user and group provisioning.
Overview
Section titled “Overview”Supported Features
Section titled “Supported Features”- User CRUD operations (Create, Read, Update, Delete)
- Group CRUD operations
- Discovery endpoints:
/ServiceProviderConfig,/ResourceTypes,/Schemas - Bulk operations with
/Bulk - Filtering with SCIM query syntax
- Pagination with
startIndexandcount - Resource versioning with ETags
- Partial updates with PATCH operations
- Enterprise User extension
- Bearer token authentication
Authentication
Section titled “Authentication”SCIM provisioning requests require a Bearer token:
Authorization: Bearer YOUR_SCIM_TOKENDiscovery endpoints under /scim/v2/ServiceProviderConfig, /scim/v2/ResourceTypes, and /scim/v2/Schemas are available without a bearer token so SCIM clients can discover server capabilities.
Creating a SCIM Token
Section titled “Creating a SCIM Token”- Navigate to Admin UI > SCIM Tokens or call
POST /api/admin/scim-tokens - Enter a description (e.g., “Okta SCIM Integration”)
- Set
expiresInDays(default: 365, maximum: 3650) - Copy the token immediately (it will not be shown again)
Admin API endpoints:
| Method | Endpoint | Description |
|---|---|---|
GET | /api/admin/scim-tokens | List SCIM token metadata |
POST | /api/admin/scim-tokens | Create a SCIM token |
DELETE | /api/admin/scim-tokens/{tokenHash} | Revoke a SCIM token |
API Reference
Section titled “API Reference”List Users
Section titled “List Users”GET /scim/v2/UsersQuery Parameters:
| Parameter | Type | Description | Example |
|---|---|---|---|
filter | string | SCIM filter expression | userName eq "john@example.com" |
sortBy | string | Attribute to sort by | userName |
sortOrder | string | ascending or descending | ascending |
startIndex | integer | 1-based pagination index | 1 |
count | integer | Number of results (max 1000) | 100 |
Response:
{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"], "totalResults": 250, "startIndex": 1, "itemsPerPage": 100, "Resources": [ { "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "id": "user-123", "userName": "john@example.com", "name": { "givenName": "John", "familyName": "Doe" }, "emails": [{"value": "john@example.com", "primary": true}], "active": true, "meta": { "resourceType": "User", "created": "2024-01-01T00:00:00Z", "lastModified": "2024-01-02T00:00:00Z", "location": "https://auth.example.com/scim/v2/Users/user-123", "version": "W/\"1704153600000\"" } } ]}Get User by ID
Section titled “Get User by ID”GET /scim/v2/Users/{id}Create User
Section titled “Create User”POST /scim/v2/UsersContent-Type: application/json
{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "userName": "john@example.com", "name": { "givenName": "John", "familyName": "Doe" }, "emails": [{"value": "john@example.com", "primary": true}], "active": true}Update User (PATCH)
Section titled “Update User (PATCH)”PATCH /scim/v2/Users/{id}Content-Type: application/json
{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [ {"op": "replace", "path": "name.givenName", "value": "Jane"}, {"op": "replace", "path": "active", "value": false} ]}Supported Operations:
add- Add new attributereplace- Replace existing attributeremove- Remove attribute
Replace User (PUT)
Section titled “Replace User (PUT)”PUT /scim/v2/Users/{id}Content-Type: application/json
{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"], "userName": "john@example.com", ...}Delete User
Section titled “Delete User”DELETE /scim/v2/Users/{id}Groups
Section titled “Groups”List Groups
Section titled “List Groups”GET /scim/v2/GroupsCreate Group
Section titled “Create Group”POST /scim/v2/GroupsContent-Type: application/json
{ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:Group"], "displayName": "Engineering", "members": [ {"value": "user-123", "type": "User"} ]}Discovery
Section titled “Discovery”GET /scim/v2/ServiceProviderConfigGET /scim/v2/ResourceTypesGET /scim/v2/SchemasGET /scim/v2/Schemas/{schemaId}ServiceProviderConfig advertises support for PATCH, Bulk, filtering, sorting, ETags, and OAuth Bearer token authentication.
Bulk Operations
Section titled “Bulk Operations”POST /scim/v2/BulkContent-Type: application/scim+json
{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"], "Operations": [ { "method": "POST", "bulkId": "user1", "path": "/Users", "data": { "userName": "jane@example.com", "active": true } } ]}Bulk limits default to 100 operations and 1 MB payloads. They can be configured with SCIM_BULK_MAX_OPERATIONS and SCIM_BULK_MAX_PAYLOAD_SIZE in KV.
Filtering
Section titled “Filtering”SCIM supports complex filtering using standardized query syntax.
Filter Operators
Section titled “Filter Operators”| Operator | Description | Example |
|---|---|---|
eq | Equal | userName eq "john@example.com" |
ne | Not equal | active ne false |
co | Contains | userName co "john" |
sw | Starts with | userName sw "john" |
ew | Ends with | userName ew "example.com" |
pr | Present | phoneNumber pr |
gt | Greater than | meta.created gt "2024-01-01" |
lt | Less than | meta.created lt "2024-12-31" |
Logical Operators
Section titled “Logical Operators”| Operator | Description | Example |
|---|---|---|
and | Logical AND | userName eq "john" and active eq true |
or | Logical OR | userName eq "john" or userName eq "jane" |
not | Logical NOT | not (active eq false) |
Examples
Section titled “Examples”# Find user by emailGET /scim/v2/Users?filter=userName eq "john@example.com"
# Find active usersGET /scim/v2/Users?filter=active eq true
# Complex filterGET /scim/v2/Users?filter=(userName co "john" or userName co "jane") and active eq truePagination
Section titled “Pagination”SCIM uses 1-based pagination with startIndex and count parameters.
# First page (items 1-100)GET /scim/v2/Users?startIndex=1&count=100
# Second page (items 101-200)GET /scim/v2/Users?startIndex=101&count=100Resource Versioning (ETags)
Section titled “Resource Versioning (ETags)”SCIM supports ETags for optimistic concurrency control:
# Get user with ETagGET /scim/v2/Users/user-123Response: ETag: W/"1704153600000"
# Update with ETagPUT /scim/v2/Users/user-123If-Match: W/"1704153600000"Error Responses
Section titled “Error Responses”{ "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"], "status": "400", "scimType": "invalidValue", "detail": "userName is required"}| scimType | HTTP Status | Description |
|---|---|---|
invalidFilter | 400 | Invalid filter syntax |
invalidValue | 400 | Invalid attribute value |
uniqueness | 409 | Resource already exists |
mutability | 400 | Attempt to modify read-only attribute |
noTarget | 404 | Resource not found |
invalidVers | 412 | ETag mismatch |
Integration Guides
Section titled “Integration Guides”- Generate SCIM token in Authrim Admin UI
- Configure Okta app:
- SCIM Base URL:
https://YOUR_DOMAIN/scim/v2 - Authentication: HTTP Header
- Authorization: Bearer
YOUR_TOKEN
- SCIM Base URL:
- Enable provisioning:
- Create Users
- Update User Attributes
- Deactivate Users
Azure AD (Entra ID)
Section titled “Azure AD (Entra ID)”- Add Enterprise Application (Non-gallery)
- Configure Provisioning:
- Provisioning Mode: Automatic
- Tenant URL:
https://YOUR_DOMAIN/scim/v2 - Secret Token:
YOUR_TOKEN
- Test Connection and configure attribute mappings
OneLogin
Section titled “OneLogin”- Applications > Add App > SCIM Provisioner
- Configuration:
- SCIM Base URL:
https://YOUR_DOMAIN/scim/v2 - SCIM Bearer Token:
YOUR_TOKEN - API Connection: SCIM 2.0
- SCIM Base URL:
Attribute Mapping
Section titled “Attribute Mapping”User Attributes
Section titled “User Attributes”| SCIM Attribute | Authrim canonical storage | Type |
|---|---|---|
id | identity_accounts.legacy_user_id projection | string (read-only) |
externalId | identity_accounts.external_id | string |
userName | preferred_username sensitive attribute, falling back to primary email | string (required) |
name.givenName | profile_attribute_values + identity_sensitive_values | string |
name.familyName | profile_attribute_values + identity_sensitive_values | string |
emails[primary].value | contact_points + identity_sensitive_values | string (required) |
phoneNumbers[primary].value | contact_points + identity_sensitive_values | string |
active | identity_accounts.lifecycle_state projection | boolean |
locale | sensitive profile attribute | string |
timezone | zoneinfo sensitive profile attribute | string |
SCIM reads and writes through the canonical runtime identity projection. PII values are stored in the PII database when it is configured, while lookup hashes and lifecycle state remain in the core database.
Best Practices
Section titled “Best Practices”Security
Section titled “Security”- Rotate tokens regularly (e.g., every 90 days)
- Use separate tokens for each integration
- Monitor token usage in audit logs
- Use HTTPS for all SCIM requests
Performance
Section titled “Performance”- Use filtering to reduce response sizes
- Implement pagination for large datasets
- Use ETags to avoid unnecessary updates
Error Handling
Section titled “Error Handling”- Implement retry logic with exponential backoff
- Handle 429 (rate limit) responses
- Log all errors for troubleshooting
Rate Limits
Section titled “Rate Limits”- Standard SCIM operations use the configured moderate rate-limit profile
/scim/v2/Bulkuses the configured strict rate-limit profile429 Too Many Requestsresponses includeRetry-Afterwhen available