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.

All of the commands below are idempotent. Re-running picks up from a cursor file written next to your export; existing users emit existed=true and are skipped.

Install the CLI

go install github.com/tcast/authio_cli/cmd/authio@latest
authio login

authio 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 to 50.
  • --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.json

Auth0 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.json

AWS 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.json

Users 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.json

Disabled 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.json

Users whose banned_until is in the future are skipped.

What happens to existing users

  1. The importer POSTs {email, name, email_verified} to POST /v1/users, which is idempotent on (project_id, email).
  2. If the user is new, Authio enqueues a single magic-link enrollment email so they can complete passkey registration on their first sign-in.
  3. If the user already exists (e.g. you’re re-running), nothing else happens.
  4. 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=0

You 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.

If the importer crashes mid-run, just re-run the same command. The cursor file (<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.