Aller au contenu

Export users from Auth0

Ce contenu n’est pas encore disponible dans votre langue.

This guide walks through exporting the users of an Auth0 tenant into the Canonical Migration Format (CMF), choosing which data to export, checking what came out, and preparing the result for import into another provider.

iamigrate export --source auth0 runs a user export job on the tenant (POST /jobs/users-exports), waits for it to finish, downloads the result, and converts each user into one CMF record. A job is used rather than paging GET /users, because the Management API’s user list stops at 1000 users.

Every user of the tenant is exported, whatever their connection, and whether or not they have a password: database users, social users, passwordless users and users from enterprise connections. Use --connection-id to export just one connection.

  • iamigrate installed (see Installation).
  • A paid Auth0 plan. Auth0 doesn’t offer user export jobs on the Free plan.
  • A Management API token, or a Machine-to-Machine application’s client ID and secret, with the read:users scope. Create one as described in the import guide. If waiting for the job fails with a 403, also grant create:users, which Auth0’s reference lists for job status requests.
Terminal window
export AUTH0_DOMAIN=your-tenant.us.auth0.com
export AUTH0_CLIENT_ID=... # the Machine-to-Machine application's Client ID
export AUTH0_CLIENT_SECRET=... # and its Client Secret

Or use a ready-made token with AUTH0_TOKEN. --domain, --client-id, --client-secret and --token do the same.

By default every attribute iamigrate can convert is exported. To export only some of them, pass --fields:

Terminal window
iamigrate export --source auth0 --fields email,email_verified,given_name,family_name --out ./export/

user_id is always exported, because it becomes the CMF source_id that import reports and diff refer to. The other attributes you can choose from are:

AttributeCMF field
email, email_verifiedemails[0], marked primary
usernameusername
phone_number, phone_verifiedphones[0], marked primary
given_name, family_name, name, nickname, pictureprofile
blockedblocked
app_metadata, user_metadataapp_metadata, user_metadata

A name that isn’t in this list is refused before anything is requested or written.

Two more options narrow down which users are exported:

FlagEffect
--connection-id con_xxxOnly the users of this connection. Find the ID in the dashboard under Authentication → Database, or with GET /api/v2/connections.
--limit 100At most that many users. Use it to try the export, and a trial import, on a small sample first.
Terminal window
iamigrate export --source auth0 --out ./export/
iamigrate: Auth0 doesn't return password hashes through its API: users are exported without a password, so they will have to reset it (see the Auth0 export guide to get the hashes from Auth0 support)
exported 1250 users -> export/users.cmf.jsonl.gz (0 skipped)

The command writes:

export/
├── users.cmf.jsonl.gz # one CMF user per exported account
├── manifest.json # record count, plus skipped accounts
└── mapping.yaml # scaffolded mapping, with no target set yet

The export job can take a while on a large tenant. iamigrate waits for it, then downloads the result right away, since Auth0’s download link is only valid for 60 seconds.

The export is a snapshot. Users created, or changed, after it aren’t in it, so plan a freeze or a final re-export before cutover.

Terminal window
cat export/manifest.json
{
"record_count": 1250
}

skipped_records lists any exported entry that had no user_id. The command exits with status 0 even then, so check it.

Because there are no passwords, there is no hash_algorithm_counts.

The password of every CMF record is null, and there is no mfa_factors.

  • Password hashes. Auth0 doesn’t return them through its API. See Keeping your users’ passwords.
  • MFA enrollments. Users will have to enroll again.
  • Linked identities. A social or enterprise user keeps their user_id (for example google-oauth2|1234), email and profile, but the link to the identity provider isn’t carried over. Reconnect that connection on the target to let them sign in the same way.
  • Roles, permissions, organizations and memberships.
  • Timestamps, such as creation and last login.

Auth0 doesn’t expose password hashes through the Management API or the dashboard. The only way to get them is to ask Auth0 support for a password hash export. It isn’t available on the Free plan, Auth0 may decline the request, and it gives no delivery date, though you can state the date you need it by.

The process, as Auth0 documents it:

  1. Generate a PGP key pair. It must be RSA with a 4096-bit key or larger, with an RSA 4096-bit encryption subkey. Elliptic-curve keys are rejected. Use a strong passphrase, and an expiry at least 7 days away. The key’s email must be the exact email of the tenant administrator who will open the request.

  2. Export the public key in ASCII-armored form. It must not exceed 35,000 characters. If it does, add --export-options export-minimal to your gpg --export command to drop third-party signatures.

  3. Open a support case at support.auth0.com with your tenant name and the public key. The administrator who generated the key must be the one to open it.

  4. Wait for Auth0’s review. If the request is approved, Auth0 asks for your written approval, a confirmation from another tenant administrator (not needed if you are the only one), and a signed acknowledgment form. An executive at CISO, CSO or VP level or above must sign it, and typed names aren’t accepted.

  5. Download the file from the link Auth0 emails to the case opener, who must still be a tenant administrator. The link expires after 3 days. The file is encrypted with your public key, so only you can read it.

  6. Decrypt it:

    Terminal window
    gpg --output auth0-hashes.json --decrypt auth0-hashes.pgp

    Keep your private key and passphrase to yourself, including from Auth0 staff, and back them up offline. If you lose them, you have to submit a new request.

Auth0’s page doesn’t describe the layout of the decrypted file, and iamigrate doesn’t read it, so look at it first. Then add each user’s hash to the password of the matching record of users.cmf.jsonl.gz, matching on user_id (the CMF source_id):

"password": {
"algorithm": "bcrypt",
"hash": { "value": "$2b$10$...", "encoding": "utf8" },
"portable": true
}

Run iamigrate validate afterwards, as in the next step, to check the records against the target. Then test a handful of users by signing in on the target before you rely on the whole export.

If Auth0 declines the request, or you’d rather not ask, migrate with this export as is. Users are created without a password and have to reset it.

mapping.yaml is scaffolded with target: "". Set the target before you validate with it:

Terminal window
iamigrate map --target <target> --mapping ./export/mapping.yaml

Then check the export against the target’s capabilities. No network calls are made:

Terminal window
iamigrate validate --in ./export/users.cmf.jsonl.gz --mapping ./export/mapping.yaml --target <target>

From there, follow the import guide for your target:

SymptomCauseFix
--domain (or AUTH0_DOMAIN) is requiredNo tenant givenSet AUTH0_DOMAIN or pass --domain
unknown export field "..."A --fields name isn’t one of the attributes aboveUse the attribute names from Step 2
401/403 when creating the jobExpired token, wrong client credentials, missing scope, or a Free plan tenantGet a new token, check read:users, and check the plan
403 while waiting for the jobThe token can’t read job statusAlso grant create:users
429Management API rate limitiamigrate retries by itself. If it keeps failing, wait and run it again
ended with status "failed"The export job failed on Auth0’s sideRun it again, with --connection-id or --limit to make the job smaller