Migrate users to Identity Pools
Migrate users from external CIAM platforms into SecureAuth Identity Pools while maintaining data integrity and security at scale.
💡 Why this matters
Consolidate user data from multiple platforms into SecureAuth for better security, compliance, and operational efficiency. Supports large-scale migrations (~1.5 million users in 30 minutes).
Prerequisites:
- Identity Pool configured
- System workspace access
- Client application with
manage_configuration
scope
Phase 1: Prepare migration data
Format your data structure
Follow the Import Tenant Configuration API schema requirements.
Data type | Required fields | Purpose |
---|---|---|
users | id , user_pool_id , tenant_id | Core user information |
user_credentials | id , user_id , payload | Login credentials |
user_identifiers | id , user_id , identifier | Email or phone identifiers |
user_verifiable_addresses | id , user_id , address | Contact information |
Generate unique identifiers
Create version 4 UUIDs for all records to ensure API idempotency and avoid duplicates during retries.
Handle password migration
Choose your password migration strategy:
Strategy | Configuration | Use case |
---|---|---|
Migrate passwords | Leave expires_at unset or 1900-01-01T00:00:00Z | Users keep existing passwords |
Force password reset | Set expires_at to past date | Enhanced security, users must reset |
⚠️ Security note
Forced password reset provides better security but requires user communication plan.
Phase 2: Import users
Get system access token
curl --location --request POST 'https://example.com/tenant_id/system/oauth2/token' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=client_credentials' \
--data-urlencode 'client_id=YOUR_CLIENT_ID' \
--data-urlencode 'client_secret=YOUR_CLIENT_SECRET'
Verify: Token response includes manage_configuration
scope
Submit import batches
curl --location --request PUT 'https://example.com/api/identity/system/{tid}/configuration' \
-H 'Authorization: Bearer {ACCESS_TOKEN}' \
-d @user-batch.json
Performance guidelines:
- Batch size: Up to 100 users per request
- Parallel requests: Up to 8 simultaneous requests
- Expected throughput: ~1.5 million users in 30 minutes
Verify: 204 NO CONTENT
response confirms successful import
Phase 3: Handle import conflicts
Configure conflict resolution using the mode
parameter:
Mode | Behavior | When to Use |
---|---|---|
ignore (default) | Skip conflicting records | Standard migration |
fail | Stop on conflicts | Testing/validation |
update | Overwrite existing records | Data updates |
Example with update mode:
curl --location --request PUT 'https://example.com/api/identity/system/{tid}/configuration?mode=update'
Export users (testing only)
⚠️ Warning
Export API not production-ready for large user bases. Use only for testing or beta purposes.
Export user data
curl --location --request GET 'https://example.com/api/identity/system/{tid}/configuration' \
--header 'Authorization: Bearer {ACCESS_TOKEN}'
Result: 200 OK
response returns tenant configuration as JSON
Verification and Testing
Test these scenarios:
- Import small batch → Verify users appear in Identity Pool
- Test login with migrated user → Confirm authentication works
- Test password reset flow → Verify expired credentials behavior
Monitor these metrics:
- Import success rate: Should be >95%
- API response times: Should be <2 seconds
- Error patterns: Track and resolve common issues
Troubleshooting
Import failures:
400 Bad Request
→ Check JSON format and required fields401 Unauthorized
→ Verify access token and scope409 Conflict
→ User already exists, check import mode
Password issues:
- Users can't login → Check
expires_at
configuration - "Credential expired" error → Users need password reset via forgot password flow
Performance issues:
- Slow imports → Reduce batch size or parallel requests
- Timeouts → Check network connectivity and retry failed batches
Recovery steps:
- Use same UUIDs to retry failed imports (API is idempotent)
- Check error logs for specific failure reasons
- Test with smaller batches if bulk import fails
Sample Data Format
Minimal example for two users:
{
"users": [
{
"id": "58e6184f-8e38-4193-b889-965b34326c7f",
"user_pool_id": "caku6lrphdd3cfqro3mg",
"tenant_id": "default",
"status": "active",
"payload": {
"name": "John Doe",
"given_name": "John",
"family_name": "Doe"
}
}
],
"user_credentials": [
{
"id": "e89e254c-f538-4ae2-9150-4d4580bcf886",
"user_id": "58e6184f-8e38-4193-b889-965b34326c7f",
"type": "password",
"expires_at": "2019-08-24T14:15:22Z",
"payload": {
"hashed_password": {
"config": {
"method": "sha",
"sha": {
"function": "SHA-256",
"salt": "lJgayFHwYelZGmrBnYqt"
}
},
"value": "eUJBxl+dwVjPgwC2cm1K+hYNWFRly/RdCT/bgmIBowo="
}
}
}
],
"user_identifiers": [
{
"id": "b7108442-7f1e-40b9-a4d9-0c9ab3b0d18b",
"user_id": "58e6184f-8e38-4193-b889-965b34326c7f",
"identifier": "john.doe@example.com",
"type": "email"
}
]
}