SCIM Provisioning Integration
This guide walks you through implementing automated user provisioning using SCIM 2.0 (System for Cross-domain Identity Management). SCIM enables your identity provider to automatically manage users and groups in AuthOS.
What is SCIM?
SCIM (System for Cross-domain Identity Management) is an industry-standard protocol for automating user lifecycle management. With SCIM, your identity provider (IdP) can:
- Automatic Provisioning: Create users when added to the directory
- Profile Sync: Update user information when changed in the IdP
- Deprovisioning: Deactivate or remove users when they leave
- Group Management: Synchronize group memberships across systems
Prerequisites
Before setting up SCIM provisioning:
- Organization Admin Access: You need admin access to your AuthOS organization
- IdP Administrator Role: Admin access to your identity provider (Okta, Azure AD, OneLogin, etc.)
- HTTPS Endpoint: AuthOS must be accessible via HTTPS
- SDK Installed (optional):
npm install @drmhse/sso-sdkfor programmatic token management
Step 1: Generate a SCIM Token
SCIM tokens authenticate requests from your identity provider to AuthOS.
Using the SDK
import { SsoClient } from '@drmhse/sso-sdk';
const sso = new SsoClient({
baseURL: 'https://sso.example.com',
token: 'your-org-admin-jwt'
});
// Create a SCIM token
const scimToken = await sso.organizations.createScimToken('acme-corp', {
name: 'Okta SCIM Integration',
expires_at: '2026-12-31T23:59:59Z' // Optional expiration
});
console.log('SCIM Base URL:', 'https://sso.example.com/scim/v2');
console.log('Bearer Token:', scimToken.token);
console.log('Token Prefix:', scimToken.prefix);
// IMPORTANT: Save this token securely - it's only shown once
Using the API Directly
curl -X POST https://sso.example.com/api/organizations/acme-corp/scim-tokens \
-H "Authorization: Bearer your-org-admin-jwt" \
-H "Content-Type: application/json" \
-d '{
"name": "Okta SCIM Integration",
"expires_at": "2026-12-31T23:59:59Z"
}'
Response:
{
"id": "scim-token-123",
"name": "Okta SCIM Integration",
"token": "scim_live_abc123def456...",
"prefix": "scim_live_abc1",
"created_at": "2025-01-15T10:00:00Z",
"expires_at": "2026-12-31T23:59:59Z"
}
Critical: The full token is only shown once. Store it securely in your identity provider.
Step 2: Configure Your Identity Provider
Choose your identity provider from the options below:
Option A: Okta Integration
1. Create SCIM Token
Follow Step 1 above to generate a SCIM token.
2. Configure Okta Application
- Log into Okta Admin Console
- Navigate to Applications → Select your application
- Click the Provisioning tab
- Click Configure API Integration
3. SCIM Connection Settings
Configure the following settings:
| Field | Value |
|---|---|
| SCIM Base URL | https://your-sso-platform.com/scim/v2 |
| Unique Identifier | userName |
| Authentication Mode | HTTP Header |
| Authorization Header | Bearer scim_live_your_token |
4. Test Connection
Click Test API Credentials to verify the connection.
Expected Result: “Credentials verified successfully”
If the test fails:
- Verify the SCIM base URL is correct and accessible
- Check that the token was copied completely (no extra spaces)
- Ensure the token hasn’t expired
- Confirm HTTPS is used (HTTP will fail)
5. Enable Provisioning Features
In Provisioning → To App, enable:
- Create Users: Automatically create users in SSO platform
- Update User Attributes: Sync profile changes
- Deactivate Users: Deactivate users when suspended in Okta
6. Configure Attribute Mappings
Navigate to Provisioning → To App → Attribute Mappings
Recommended mappings:
| Okta Attribute | AuthOS Attribute |
|---|---|
email |
userName |
email |
emails[0].value |
displayName |
displayName |
firstName |
name.givenName |
lastName |
name.familyName |
7. Assign Users and Groups
- Go to Assignments tab
- Click Assign → Assign to People or Assign to Groups
- Select users/groups to provision
- Click Assign
Okta will immediately start provisioning the assigned users to the SSO platform.
8. Verify Provisioning
Check the SSO platform to confirm users were created:
// List users in the organization
const users = await sso.organizations.listUsers('acme-corp');
console.log('Provisioned users:', users);
Option B: Azure AD Integration
1. Create SCIM Token
Follow Step 1 above to generate a SCIM token.
2. Configure Azure AD Provisioning
- Log into Azure Portal
- Navigate to Azure Active Directory → Enterprise Applications
- Select your application
- Click Provisioning in the left sidebar
- Click Get started
3. Provisioning Configuration
Set the following:
| Field | Value |
|---|---|
| Provisioning Mode | Automatic |
| Tenant URL | https://your-sso-platform.com/scim/v2 |
| Secret Token | scim_live_your_token |
4. Test Connection
Click Test Connection to validate the configuration.
Expected Result: “The supplied credentials are authorized to enable provisioning”
Troubleshooting Connection Failures:
- Verify the tenant URL ends with
/scim/v2(no trailing slash) - Ensure the secret token is the full token including the
scim_live_prefix - Check that the SSO platform is accessible from Azure’s IP ranges
- Confirm the token has not expired
5. Configure Mappings
Click Mappings to configure attribute synchronization:
User Mappings
Navigate to Provision Azure Active Directory Users:
| Azure AD Attribute | AuthOS Attribute | Notes |
|---|---|---|
userPrincipalName |
userName |
Required |
mail |
emails[type eq "work"].value |
Primary email |
Switch([IsSoftDeleted], , "False", "True", "True", "False") |
active |
Handles soft delete |
displayName |
displayName |
Optional |
givenName |
name.givenName |
Optional |
surname |
name.familyName |
Optional |
Group Mappings
Navigate to Provision Azure Active Directory Groups (if using group sync):
| Azure AD Attribute | AuthOS Attribute |
|---|---|
displayName |
displayName |
members |
members |
6. Configure Scoping
Under Settings → Scope, choose:
- Sync only assigned users and groups (recommended for initial setup)
- Sync all users and groups (for full directory sync)
7. Save and Start Provisioning
- Click Save to save the configuration
- Set Provisioning Status to On
- Click Save again
Azure AD will begin an initial synchronization cycle.
8. Monitor Provisioning
- Navigate to Provisioning → Provisioning logs
- Monitor for successful user creation events
- Check for any errors or warnings
Typical Initial Cycle Duration: 20-40 minutes
Option C: OneLogin Integration
1. Create SCIM Token
Follow Step 1 above to generate a SCIM token.
2. Configure OneLogin Application
- Log into OneLogin Admin Portal
- Navigate to Applications → Select your application
- Click the Provisioning tab
- Click Enable provisioning
3. SCIM Configuration
Configure the following:
| Field | Value |
|---|---|
| SCIM Base URL | https://your-sso-platform.com/scim/v2 |
| SCIM Bearer Token | scim_live_your_token |
| API Connection | SCIM 2.0 |
4. Enable Operations
Select the provisioning operations to enable:
- Create user: Provision new users
- Update user: Sync profile changes
- Delete user: Remove users (soft delete)
5. Configure Entitlements
Map OneLogin fields to SCIM attributes:
| OneLogin Field | SCIM Attribute |
|---|---|
| userName | |
| emails[0].value | |
| First Name | name.givenName |
| Last Name | name.familyName |
6. Apply Provisioning Rules
- Navigate to Rules tab
- Create rules for automatic user provisioning
- Define conditions for when users should be provisioned
7. Test and Enable
- Click Save
- Assign test users to the application
- Verify provisioning in SSO platform
- Roll out to all users
Step 3: Verify Provisioning
After configuring your identity provider, verify that provisioning works correctly.
Manual Verification
Check User Creation
// List all users in the organization
const users = await sso.organizations.listUsers('acme-corp');
// Check if a specific user exists
const specificUser = users.find(u => u.email === 'newuser@example.com');
console.log('User provisioned:', specificUser ? 'Yes' : 'No');
Monitor SCIM Token Usage
// List SCIM tokens to check last usage
const tokens = await sso.organizations.listScimTokens('acme-corp');
tokens.forEach(token => {
console.log(`Token: ${token.prefix}`);
console.log(`Last used: ${token.last_used_at || 'Never'}`);
console.log(`Expires: ${token.expires_at || 'Never'}`);
});
Testing Scenarios
Test 1: User Creation
- Add a new user to your IdP
- Assign them to the SSO application
- Wait for sync cycle (1-40 minutes depending on IdP)
- Verify user exists in SSO platform
Test 2: User Update
- Change a user’s email or name in IdP
- Wait for sync
- Verify the change reflects in SSO platform
Test 3: User Deactivation
- Suspend or remove a user from the application in IdP
- Wait for sync
- Verify user is deactivated (not deleted) in SSO platform
// Check user's active status
const user = await sso.organizations.getUser('acme-corp', 'user-id');
console.log('User active:', user.deleted_at === null);
Test 4: Group Membership
- Create a group in IdP and assign users
- Assign the group to the SSO application
- Verify all group members are provisioned
Advanced Configuration
Automatic Token Rotation
Implement automatic token rotation for security:
async function rotateScimToken(orgSlug: string, oldTokenId: string) {
// Create new token
const newToken = await sso.organizations.createScimToken(orgSlug, {
name: 'Okta SCIM Integration - Rotated',
expires_at: new Date(Date.now() + 365 * 24 * 60 * 60 * 1000).toISOString()
});
console.log('New SCIM token created:', newToken.prefix);
console.log('Update your IdP with this token:', newToken.token);
// After updating IdP configuration, revoke old token
// await sso.organizations.deleteScimToken(orgSlug, oldTokenId);
return newToken;
}
// Schedule token rotation every 6 months
Custom Attribute Mapping
Some organizations need custom attribute mappings:
// Example: Azure AD custom security attributes
// In Azure AD provisioning mappings, add:
// extensionAttribute1 -> emails[type eq "work"].value
// customAttribute -> name.formatted
Handling Provisioning Conflicts
When a user already exists (e.g., manually created before SCIM):
// The IdP will receive a 409 Conflict error
// Options:
// 1. Delete the manual user first
// 2. Configure IdP to update instead of create
// 3. Use matching rules in IdP to link existing users
For Azure AD, configure Accidental Deletions Threshold to prevent mass deprovisioning:
- Navigate to Provisioning → Settings
- Set Accidental deletions threshold to 5-10 users
- Azure AD will pause and alert if deletions exceed threshold
Filtering Users for Provisioning
Control which users get provisioned using IdP filters:
Okta: Use group assignments to scope users
Azure AD: Use scoping filters in provisioning settings:
department Equals "Engineering"
city Equals "San Francisco"
OneLogin: Use provisioning rules with conditions
Monitoring and Troubleshooting
Common Issues
Issue: “Invalid SCIM token” Error
Symptoms: IdP reports authentication failure
Solutions:
- Verify token was copied completely (including
scim_live_prefix) - Check token hasn’t expired
- Ensure token belongs to the correct organization
- Verify HTTPS is used (HTTP will fail authentication)
Issue: Users Not Provisioning
Symptoms: Users assigned in IdP but not appearing in SSO platform
Solutions:
- Check IdP provisioning logs for errors
- Verify users are assigned to the application
- Confirm SCIM base URL is correct
- Check network connectivity from IdP to SSO platform
- Review firewall rules allowing IdP IP ranges
Issue: “User already exists” (409 Conflict)
Symptoms: IdP reports conflict when creating users
Solutions:
- User exists in SSO platform (possibly manually created)
- Delete existing user or configure IdP to update instead of create
- Use IdP’s user matching features to link existing accounts
Issue: Slow Synchronization
Symptoms: Changes take hours to sync
Understanding Sync Cycles:
- Okta: Real-time for explicit provisioning, 40 minutes for automatic sync
- Azure AD: Initial sync 20-40 minutes, incremental every 40 minutes
- OneLogin: Configurable, default 1 hour
Workarounds:
- Force manual sync in IdP admin console
- Reduce sync interval if supported by IdP
- Use webhooks for real-time updates (if available)
Monitoring Best Practices
Track Token Usage
// Monitor SCIM token usage weekly
async function auditScimTokens(orgSlug: string) {
const tokens = await sso.organizations.listScimTokens(orgSlug);
for (const token of tokens) {
const daysSinceUsed = token.last_used_at
? Math.floor((Date.now() - new Date(token.last_used_at).getTime()) / (1000 * 60 * 60 * 24))
: Infinity;
if (daysSinceUsed > 7) {
console.warn(`Token ${token.prefix} not used in ${daysSinceUsed} days`);
}
if (token.expires_at) {
const daysUntilExpiry = Math.floor((new Date(token.expires_at).getTime() - Date.now()) / (1000 * 60 * 60 * 24));
if (daysUntilExpiry < 30) {
console.warn(`Token ${token.prefix} expires in ${daysUntilExpiry} days`);
}
}
}
}
Monitor Provisioning Events
Review organization audit logs for SCIM activity:
// Get recent user provisioning events
const auditLogs = await sso.organizations.getAuditLog('acme-corp', {
action: 'user.joined',
limit: 50
});
// Filter for SCIM-provisioned users (check details for SCIM source)
const scimProvisionedUsers = auditLogs.filter(log =>
log.details?.source === 'scim'
);
console.log(`${scimProvisionedUsers.length} users provisioned via SCIM`);
Debugging Tips
Enable Verbose Logging in IdP
- Okta: Navigate to Reports → System Log and filter by application
- Azure AD: Use Provisioning logs under the application’s Provisioning section
- OneLogin: Check Activity → Events for provisioning events
Test SCIM Endpoints Directly
Use curl to test SCIM endpoints directly:
# List users
curl -X GET "https://sso.example.com/scim/v2/Users?count=10" \
-H "Authorization: Bearer scim_live_your_token"
# Get specific user
curl -X GET "https://sso.example.com/scim/v2/Users/user-id" \
-H "Authorization: Bearer scim_live_your_token"
# Test token authentication
curl -X GET "https://sso.example.com/scim/v2/Users?count=1" \
-H "Authorization: Bearer scim_live_your_token" \
-v
Validate SCIM Compliance
Test your SCIM implementation against the spec:
# Verify SCIM endpoints return correct schemas
curl -X GET "https://sso.example.com/scim/v2/Users/user-id" \
-H "Authorization: Bearer scim_live_your_token" | \
jq '.schemas'
# Should return: ["urn:ietf:params:scim:schemas:core:2.0:User"]
Security Best Practices
Token Management
- Rotate Tokens Regularly: Rotate SCIM tokens every 6-12 months
- Use Expiration Dates: Set expiration dates on tokens to force rotation
- Limit Token Scope: Each IdP integration should have its own token
- Monitor Token Usage: Alert on unused or suspicious token activity
- Revoke Unused Tokens: Remove tokens that haven’t been used in 90+ days
Access Control
- Least Privilege: Only grant SCIM provisioning to necessary IdP administrators
- Audit Logging: Review SCIM provisioning logs regularly
- IP Allowlisting (if supported): Restrict SCIM endpoint access to IdP IP ranges
- HTTPS Only: Never use HTTP for SCIM endpoints
Data Protection
- Soft Deletion: Use
active: falseinstead of hard deletion for compliance - PII Handling: Ensure IdP-to-SSO data transfer complies with regulations (GDPR, CCPA)
- Backup Before Bulk Operations: Back up user data before enabling provisioning
- Test in Staging: Test SCIM configuration in a non-production environment first
Related Documentation
- SCIM 2.0 API Reference - Complete SCIM endpoint documentation
- Organizations SDK Reference - SCIM token management
- Authentication Flows Guide - Understanding user authentication
- Access Control Concepts - ReBAC permissions