Migrate from Auth0
Bulk-import Auth0 users into Avnology ID, map Actions to Avnology Hooks, and reuse existing OAuth client IDs where possible.
Migrate from Auth0
This guide moves users, applications, and rules from an Auth0 tenant to Avnology ID.
Prerequisites
avnologyCLI installed — see installation.- An admin API key in your
.env(AVNOLOGY_SECRET_KEY=sk_live_…). - Auth0 tenant admin access with permission to run the bulk user export job.
Equivalent concepts
| Auth0 | Avnology ID |
|---|---|
| Tenant | Organization |
| Connection (Database) | Password identity method |
| Connection (Social) | Social provider (OIDC) |
| Rule / Action | Webhook Hook |
| Application (Regular Web) | OAuth 2.1 Confidential Client |
| Application (SPA) | OAuth 2.1 Public Client with PKCE |
| Application (M2M) | Service Account + API Key |
| Organization | Organization (same concept) |
| Role | Role (roles:<role> in Keto) |
| Permission | namespace:object#relation permission tuple |
| user_metadata | traits.metadata |
| app_metadata | private_metadata (admin-only) |
| Universal Login | Hosted sign-in page (/sign-in) |
Export users from Auth0
- In the Auth0 dashboard, go to User Management → Users.
- Click Export Users. Auth0 emails you a JSON file containing every user in your tenant.
- Save the file as
auth0_users.jsonin your working directory.
The export format is documented in the Auth0 bulk import docs. Each record looks like:
{
"user_id": "auth0|64a1b…",
"email": "[email protected]",
"email_verified": true,
"given_name": "Ada",
"family_name": "Lovelace",
"password_hash": "$2b$10$…",
"created_at": "2024-01-02T03:04:05Z",
"user_metadata": { "locale": "en-GB"
Import with the CLI
# Preview the canonicalised records.
avnology migrate auth0 --import auth0_users.json --dry-run
# Execute the import.
avnology migrate auth0 --import auth0_users.jsonThe CLI:
- Normalises each record to the shared
MigrationIdentityshape. - Sets
external_id = <user_id>so re-running is idempotent. - Carries bcrypt hashes verbatim.
- Copies
given_name,family_name,nickname, anduser_metadatainto the identity traits.
Social identities (google-oauth2|…, github|…, etc.) are imported as link-later records: the next time the user signs in with the social provider, Avnology reconciles the external_id with the new social identity.
OAuth client migration
For each Auth0 Application:
- Register a new OAuth client in the Avnology dashboard under Developer → Applications. Pick the same client type (Regular Web / SPA / M2M).
- Copy the old Auth0 client ID into the Avnology client's
legacy_client_idfield so existing access tokens can be recognised during the cutover window. - Move Allowed Callback URLs to Avnology's Redirect URIs list. Exact-match is required — wildcards are not accepted.
- For SPAs using PKCE, no secret is needed. For Regular Web + M2M, copy the new secret from the dashboard into your app's env (
AVNOLOGY_SECRET_KEY).
Redirect URL mapping
| Auth0 URL | Avnology ID URL |
|---|---|
https://<tenant>.auth0.com/authorize | https://<Domain id="api"/>/oauth2/auth |
https://<tenant>.auth0.com/oauth/token | https://<Domain id="api"/>/oauth2/token |
https://<tenant>.auth0.com/.well-known/jwks.json | https://<Domain id="api"/>/.well-known/jwks.json |
https://<tenant>.auth0.com/.well-known/openid-configuration | https://<Domain id="api"/>/.well-known/openid-configuration |
https://<tenant>.auth0.com/userinfo | https://<Domain id="api"/>/userinfo |
https://<tenant>.auth0.com/v2/logout | https://<Domain id="api"/>/oauth2/sessions/logout |
Actions → Hooks
Auth0 Actions (post-login, post-change-password, pre-registration, etc.) map to Webhook Hooks on Avnology. Each Action translates to a webhook subscribed to the equivalent event:
| Auth0 Action trigger | Avnology event |
|---|---|
post-login | session.created |
pre-user-registration | user.pre_create |
post-user-registration | user.created |
post-change-password | user.password_changed |
credentials-exchange | oauth.token_issued |
Port the Action logic into a JS/TS webhook handler, subscribe it under Developer → Webhooks, and verify signatures with @avnology/backend's verifyRequest.
Cutover plan
- Run the user import in a non-production tenant and smoke-test with a handful of real emails.
- Dual-write window: keep Auth0 receiving all writes while Avnology ID handles reads. Set
trust_forwarded_headers=falseon both so session cookies don't cross over. - Flip your app's
AVNOLOGY_DOMAIN+AVNOLOGY_SECRET_KEYto the production Avnology tenant. - Keep Auth0 online for 30 days for audit-log export, then decommission.