SCIM Provisioning

UniAuth supports SCIM 2.0 (System for Cross-domain Identity Management) for automated user provisioning and deprovisioning. Connect your existing identity provider — such as Okta, Azure AD, or OneLogin — to automatically sync users into UniAuth when they join or leave your organization.

Note: SCIM provisioning is an enterprise feature tied to OAuth clients. Each OAuth client can have its own SCIM endpoint with an independent bearer token for authentication.

Setup

To enable SCIM provisioning for an OAuth client:

  • Navigate to Admin Panel → OAuth Clients
  • Select the client you want to enable SCIM for
  • Under the SCIM tab, click Enable SCIM
  • A bearer token is generated automatically. Copy and store it securely — it is only shown once.
  • Configure your external IdP with the SCIM base URL and bearer token

You can also generate a SCIM token programmatically:

POST /api/admin/webhooks/scim-token
Content-Type: application/json
Authorization: Bearer <admin-session-token>

{
  "client_id": "your-oauth-client-id"
}

Base URL

All SCIM endpoints are served under:

https://uniauth.id/api/scim/v2

When configuring your IdP, use this as the SCIM connector base URL.

Authentication

All SCIM requests must include a bearer token in the Authorization header:

Authorization: Bearer scim_abc123def456...

Tokens are scoped to a specific OAuth client and can be revoked or rotated from the admin panel.

Endpoints

MethodEndpointDescription
GET/api/scim/v2/UsersList users (with filter and pagination)
POST/api/scim/v2/UsersCreate a new user
GET/api/scim/v2/Users/:idGet a single user
PUT/api/scim/v2/Users/:idReplace a user (full update)
PATCH/api/scim/v2/Users/:idUpdate specific user attributes
DELETE/api/scim/v2/Users/:idDeactivate a user
GET/api/scim/v2/ServiceProviderConfigSCIM service provider capabilities
GET/api/scim/v2/SchemasSupported SCIM schema definitions
GET/api/scim/v2/ResourceTypesAvailable SCIM resource types

User Schema Mapping

SCIM attributes are mapped to UniAuth user fields as follows:

SCIM AttributeUniAuth FieldNotes
userNameemailMust be a valid email address
name.givenNamefirst_name
name.familyNamelast_name
displayNamedisplay_nameFalls back to givenName + familyName
activeemail_verifiedDeactivated users cannot log in
titlejob_title
localelocaleBCP47 language tag (e.g., en-US)
timezonetimezoneIANA timezone (e.g., America/New_York)
addresses[0]addressOIDC structured address (JSONB)

Example: Create User

POST /api/scim/v2/Users
Content-Type: application/json
Authorization: Bearer scim_abc123def456...

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "userName": "[email protected]",
  "name": {
    "givenName": "Jane",
    "familyName": "Doe"
  },
  "displayName": "Jane Doe",
  "active": true,
  "title": "Software Engineer",
  "locale": "en-US",
  "timezone": "America/New_York"
}

Example: Response

{
  "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
  "id": "550e8400-e29b-41d4-a716-446655440000",
  "userName": "[email protected]",
  "name": {
    "givenName": "Jane",
    "familyName": "Doe"
  },
  "displayName": "Jane Doe",
  "active": true,
  "title": "Software Engineer",
  "locale": "en-US",
  "timezone": "America/New_York",
  "meta": {
    "resourceType": "User",
    "created": "2026-02-26T14:30:00.000Z",
    "lastModified": "2026-02-26T14:30:00.000Z",
    "location": "https://uniauth.id/api/scim/v2/Users/550e8400-e29b-41d4-a716-446655440000"
  }
}

Filtering

The GET /api/scim/v2/Users endpoint supports SCIM filtering via the filter query parameter. Supported operators:

  • eq — Equal
  • co — Contains
  • sw — Starts with

Filter Examples

# Find user by exact email
GET /api/scim/v2/Users?filter=userName eq "[email protected]"

# Search by display name (contains)
GET /api/scim/v2/Users?filter=displayName co "Jane"

# Find users whose name starts with "J"
GET /api/scim/v2/Users?filter=name.givenName sw "J"

Pagination

List endpoints support pagination with startIndex and count parameters. The maximum page size is 100.

GET /api/scim/v2/Users?startIndex=1&count=25

The response includes pagination metadata:

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:ListResponse"],
  "totalResults": 142,
  "startIndex": 1,
  "itemsPerPage": 25,
  "Resources": [...]
}

Provisioning from Okta

To set up SCIM provisioning from Okta:

  • In Okta, go to Applications → Create App Integration
  • Select SCIM 2.0 as the provisioning method
  • Set the SCIM connector base URL to https://uniauth.id/api/scim/v2
  • Set the authentication mode to HTTP Header
  • Paste your UniAuth SCIM bearer token
  • Enable the desired provisioning features: Create Users, Update User Attributes, Deactivate Users
  • Assign users or groups to the application to begin provisioning

Provisioning from Azure AD

To set up SCIM provisioning from Microsoft Entra ID (Azure AD):

  • In the Azure portal, go to Enterprise Applications → New Application
  • Create a non-gallery application
  • Under Provisioning, set the mode to Automatic
  • Set the Tenant URL to https://uniauth.id/api/scim/v2
  • Set the Secret Token to your UniAuth SCIM bearer token
  • Click Test Connection to verify connectivity
  • Configure attribute mappings (the defaults generally work with UniAuth's schema)
  • Assign users or groups and start provisioning

Note: SCIM provisioning creates users without passwords. Users provisioned via SCIM can set a password through the forgot-password flow, or log in via SSO through your IdP.

Error Responses

SCIM error responses follow the standard SCIM error schema. Every error includes a schemas array, a numeric status, an optional scimType, and a human-readable detail message.

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:Error"],
  "status": "400",
  "scimType": "invalidValue",
  "detail": "Missing required attribute: userName"
}
StatusscimTypeDescription
400invalidValueInvalid or missing attribute value. Check that all required fields are present and correctly formatted.
400invalidFilterMalformed filter expression. Check the filter syntax against supported operators (eq, co, sw).
401Authentication failed. The bearer token is missing, expired, or invalid.
404User not found. The specified user ID does not exist or has been deleted.
409uniquenessA user with the same userName (email) already exists. Use the existing user or update their attributes instead.

Groups

Note: Group provisioning is not currently supported. Only User resources are available through the SCIM API. If your IdP pushes group assignments, they will be acknowledged but not processed. Role assignment for users should be managed through the UniAuth admin panel or admin API.

Deactivation vs Deletion

There are two ways to remove a user's access through SCIM, with different outcomes:

ActionMethodEffect
DeactivatePATCH /Users/:id with {"active": false}Preserves the user account and all associated data. The user cannot log in until reactivated. Existing sessions are terminated. Use this for temporary offboarding or leave of absence.
DeleteDELETE /Users/:idPermanently removes the user and all associated data including sessions, passkeys, OAuth tokens, activity logs, and 2FA configurations. This action cannot be undone.
# Deactivate a user (soft removal)
PATCH /api/scim/v2/Users/550e8400-e29b-41d4-a716-446655440000
Content-Type: application/json
Authorization: Bearer scim_abc123def456...

{
  "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
  "Operations": [
    {
      "op": "replace",
      "path": "active",
      "value": false
    }
  ]
}

Pagination Details

The list users endpoint supports pagination to handle large user directories efficiently.

  • Default page size: 20 users per page
  • Maximum page size: 100 users per page (requests exceeding this are capped)
  • startIndex: 1-based (the first user is at index 1, not 0)
  • totalResults: Reflects the total number of users matching the current filter, not just the current page
# Page through all users, 50 at a time
GET /api/scim/v2/Users?startIndex=1&count=50    # Page 1 (users 1-50)
GET /api/scim/v2/Users?startIndex=51&count=50   # Page 2 (users 51-100)
GET /api/scim/v2/Users?startIndex=101&count=50  # Page 3 (users 101-150)

Continue paginating until startIndex + itemsPerPage exceeds totalResults, or until the Resources array is empty.