Migrate to Authio
Importing users from another auth provider
Bring users from Auth0, Clerk, Cognito, Firebase, or Supabase into Authio in a single command — no password hashes required.
Authio is passwordless. We never accept a password-hash file from your old IdP — instead, the importer creates each user with a verified email and queues a one-time magic-link enrollment so they land on their first sign-in attempt with a passkey instead of a password.
existed=true and are skipped.Install the CLI
go install github.com/tcast/authio_cli/cmd/authio@latest
authio loginauthio login walks you through the device-code flow and saves a project-scoped sk_live_ key to ~/.authio/credentials.toml.
Common flags
--file <path>— required; export file from your source IdP.--dry-run— parse and count without POSTing. Useful first run.--rate-limit-rps <n>— caps requests/sec. Defaults to50.--profile <name>— pick a non-default credentials profile.--force— resume even if the source file has been modified since the last run.
Auth0
Export users via the Auth0 Management API or the dashboard’s built-in “Export Users” tool. The output is a JSON array (or NDJSON) of {user_id, email, email_verified, name} records.
authio import auth0 --file users.json --dry-run
authio import auth0 --file users.jsonAuth0 Organizations and connection metadata are not imported in this version — the importer only moves user identities. After the run, recreate orgs/connections via POST /v1/organizations.
Clerk
Export with Clerk’s Backend-API user list — paginate GET /v1/users and concatenate the responses into a JSON array. Users with no email_addresses[] are skipped.
authio import clerk --file clerk-users.json --dry-run
authio import clerk --file clerk-users.jsonAWS Cognito
Run aws cognito-idp list-users --user-pool-id <id> and save the JSON — the importer accepts the AWS CLI’s default {"Users":[…]} shape or NDJSON of just the inner records.
aws cognito-idp list-users \
--user-pool-id us-east-1_abcd1234 > cognito-users.json
authio import cognito --file cognito-users.jsonUsers with Enabled=false or whose UserStatus isn’t CONFIRMED/EXTERNAL_PROVIDER are skipped.
Firebase Auth
Export with the Firebase CLI:
firebase auth:export users.json
authio import firebase --file users.jsonDisabled accounts are skipped. Password hashes that Firebase emits (passwordHash, salt) are ignored — Authio is passwordless and replaces the password material with a passkey registration on first sign-in.
Supabase
Export the auth.users table to JSON via the Supabase SQL editor:
SELECT json_agg(row_to_json(u)) FROM auth.users u;Save the result as a JSON array file and run:
authio import supabase --file supabase-users.jsonUsers whose banned_until is in the future are skipped.
What happens to existing users
- The importer POSTs
{email, name, email_verified}toPOST /v1/users, which is idempotent on(project_id, email). - If the user is new, Authio enqueues a single magic-link enrollment email so they can complete passkey registration on their first sign-in.
- If the user already exists (e.g. you’re re-running), nothing else happens.
- No password material is ever stored. There is no fallback to username/password sign-in.
Verifying the import
The importer prints a final tally:
Done. created=482 existed=18 skipped=3 errored=0You can also confirm via the management-API:
curl 'https://authiomanagement-api-production.up.railway.app/v1/users?limit=1' \
-H 'Authorization: Bearer sk_live_…' \
-H 'Authio-Total-Count: true'The Authio-Total-Count response header reflects the total user count for the project after the import.
<file>.authio-import.cursor) keys on (provider, file, fileSize); a clean re-run picks up from the last index.Coming soon
- Okta CIAM — for customers migrating from Okta B2C universal directory.
- Auth0 Organizations — preserve org-membership mapping during user import.
- SCIM-driven sync — for one-way replication from a still-active source IdP during a phased cutover.