Skip to main content

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

Application with manage_configuration scope

Phase 1: Prepare migration data

Format your data structure

Follow the Import Tenant Configuration API schema requirements.

Data typeRequired fieldsPurpose
usersid, user_pool_id, tenant_idCore user information
user_credentialsid, user_id, payloadLogin credentials
user_identifiersid, user_id, identifierEmail or phone identifiers
user_verifiable_addressesid, user_id, addressContact 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:

StrategyConfigurationUse case
Migrate passwordsLeave expires_at unset or 1900-01-01T00:00:00ZUsers keep existing passwords
Force password resetSet expires_at to past dateEnhanced 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:

ModeBehaviorWhen to Use
ignore (default)Skip conflicting recordsStandard migration
failStop on conflictsTesting/validation
updateOverwrite existing recordsData 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 fields
  • 401 Unauthorized → Verify access token and scope
  • 409 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:

  1. Use same UUIDs to retry failed imports (API is idempotent)
  2. Check error logs for specific failure reasons
  3. 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"
}
]
}