apps/docs/content/guides/migrate/sources/auth0.mdx
This guide will walk you through the steps to migrate users from Auth0 to ZITADEL, including password hashes (which requires Auth0's support assistance), so users don't need to reset their passwords.
What you'll learn with this guide
The migration tool is written in Go. Download and install the latest version of Go from the official Go website.
You'll need a target organization in ZITADEL to import your users. You can create a new organization or use an existing one.
If you don't have a ZITADEL instance, you can sign up for free here to create a new one for you. See: Managing Organizations in ZITADEL.
Note: Copy your Organization ID since you will use the id in the later steps.
Auth0 does not export hashed passwords as part of the bulk user export. You must create a support ticket to download password hashes and password-related information. Please also refer to the Auth0 guide on how to Export Data.
<Callout> You can also import users into ZITADEL with an verified email but without the passwords. Users will be prompted to create a new password after they login for the first time after migration. </Callout>You will receive a JSON file including the password hashes. See this community post for more information about the contents and format.
Reference: Export hashed passwords from Auth0
Create a bulk user export from the Auth0 Management API, or use the User Import/Export extension. You will receive a newline-delimited JSON with the requested user data.
This is an example request, we have included the user id, the email and the name of the user, but you can also export all the available user profile attributes. Make sure to export the users in a json format.
curl --request POST \
--url $AUTH0_DOMAIN/api/v2/jobs/users-exports \
--header 'authorization: Bearer $TOKEN' \
--header 'content-type: application/json' \
--data '{
"connection_id": "$CONNECTION_ID",
"format": "json",
"fields": [
{"name": "user_id"},
{"name": "email"},
{"name": "name"},
]
}'
We have developed a tool that combines your exported user data with their corresponding passwords to generate the import request body for ZITADEL.
Follow the installation instructions to set up the ZITADEL migration tool from ZITADEL Tools.
Use the migration tool to convert the Auth0 export file to a ZITADEL-compatible JSON. Step-by-step instructions can be found here: Migration Tool for Auth0
Typical steps:
Example: After obtaining the 2 required input files (passwords and profile) in JSON lines format, you can run the following command:
Sample passwords.ndjson content, as obtained from the Auth0 Support team:
{"_id":{"$oid":"emxdpVxozXeFb1HeEn5ThAK8"},"email_verified":true,"email":"[email protected]","passwordHash":"$2b$10$d.GvZhGwTllA7OdAmsA75uGGzqr/mhdQoU88M3zD.fX3Vb8Rcf33.","password_set_date":{"$date":"2025-06-30T00:00:00.000Z"},"tenant":"test","connection":"Username-Password-Authentication","_tmp_is_unique":true}
Sample profiles.json content, as obtained from the Auth0 Management API:
{"user_id":"auth0|emxdpVxozXeFb1HeEn5ThAK8","email_verified":true,"name":"Tommie Krajcik","email":"[email protected]"}
Run the following command in your terminal (replace ORG_ID with your own organization ID):
zitadel-tools migrate auth0 --org=<ORG_ID> --users=./profiles.json --passwords=./passwords.ndjson --multiline --email-verified --output=./importBody.json --timeout=5m0s
The tool will merge both objects into a single one in the importBody.json output, this will be used in the next step to complete the import process.
To call the ZITADEL Admin API, you need to authenticate using a Service Account with the IAM_OWNER Manager permissions.
There are two recommended authentication methods:
Client Credentials Flow Learn how to authenticate with client credentials.
Personal Access Token (PAT) Learn how to create and use a PAT.
Reference: Service Accounts & API Authentication
Import Endpoint:
POST /admin/v1/importAuthorization: Bearer <token>curl --location 'https://${CUSTOM_DOMAIN}/admin/v1/import' \
--header 'Content-Type: application/json' \
--header 'Accept: application/json' \
--header 'Authorization: Bearer <access-token>' \
--data-raw '{
"dataOrgs": {
"orgs": [
{
"orgId": "<your-org-id>",
"humanUsers": [
{
"userId": "auth0|emxdpVxozXeFb1HeEn5ThAK8",
"user": {
"userName": "[email protected]",
"profile": {
"firstName": "Tommie Krajcik",
"lastName": "Tommie Krajcik"
},
"email": {
"email": "[email protected]",
"isEmailVerified": true
},
"hashedPassword": {
"value": "$2b$10$d.GvZhGwTllA7OdAmsA75uGGzqr/mhdQoU88M3zD.fX3Vb8Rcf33."
}
}
}
]
}
]
},
"timeout": "5m0s"
}'
Use the ZITADEL login page or your integrated app to test logging in with one of the imported users.
Password for the sample user:
Password1!
Confirm that the migrated password works as expected.
Common issues:
The import endpoint returns an errors array which can help you identify any issues with the import.
You can also verify that a user was imported by calling the events endpoint and checking for the following event type:
"user.human.added"
Q: What is the maximum number of users that can be imported in a single batch? A: There is no hard limit on the number of users. However, there is a timeout. For ZITADEL Cloud deployments, the timeout is 5 minutes, which typically allows for importing around 5,000 users per batch.