If you are currently using Auth0, this guide will help you migrate to Nile Auth. Migrating production applications from one auth provider to another is a non-trivial task, and we recommend you do thorough testing.

Before you begin, you’ll need a Nile account. If you don’t have one, you can sign up here. You should also review the Nile Auth documentation and validate that Nile Auth meets your application requirements (That we support the providers you need, for instance). If you notice any features missing, please let us know!

Migration Steps

1

Export User Data from Auth0

This step is necessary if you use Auth0’s email/password or passwordless login methods. In this case, your users’ data is stored in Auth0’s database, and you will need to export it.

Auth0 has a friendly UI for exporting user data, but unfortunately, it does not contain the organizations that users belong to.

Therefore, you’ll need to use the management API to first list all the organizations, and then for each organization, list all the users.

Here is an example of how to do this:

var myHeaders = new Headers();
myHeaders.append("Accept", "application/json");

var requestOptions = {
  method: 'GET',
  headers: myHeaders,
  redirect: 'follow'
};

const allUsers = [];
const response = await fetch("https://login.auth0.com/api/v2/organizations", requestOptions);
const organizations = await response.json();

// Write organizations to a file
fs.writeFileSync('auth0-organizations.json', JSON.stringify(organizations, null, 2));

for (const organization of organizations) {
    const response = await fetch(`https://login.auth0.com/api/v2/organizations/${organization.id}/users`, requestOptions);
    const users = await response.json();
    // Add organization name to each user and collect them
    users.forEach(user => {
        allUsers.push({
            ...user,
            organizationName: organization.name
        });
    });
}

// Write all users to a file
const fs = require('fs');
fs.writeFileSync('auth0-users.json', JSON.stringify(allUsers, null, 2));

Note that Auth0 does not export user’s password hashes through these tools, you will need to open a support ticket to get this data.

2

Import User Data into Nile Auth

You’ll need a small script to import the user data into Nile Auth. The script will iterate over the exported user data and create users in Nile Auth.

The following example script shows how to import user data from a JSON file:

import { Nile } from "@niledatabase/server";
import * as fs from 'fs';

interface Auth0User {
    Id: string;
    Nickname: string;
    Name: string;
    email: string;
    Connection: string;
    "Created At": string;
    "Updated At": string;
}

interface Auth0Organization {
    id: string;
    name: string;
    display_name: string;
    metadata?: Record<string, any>;
}

async function migrateUsers(nile: any) {
    try {
        // Read and parse the JSON file
        const rawData = fs.readFileSync('auth0-users.json', 'utf8');
        const users: Auth0User[] = JSON.parse(rawData);
        let newUser;

        // Process each user
        for (const user of users) {
            try {
                // Generate a temporary password (you might want to adjust this strategy)
                const tempPassword = `temp-${Math.random().toString(36).slice(-8)}`;

                // Get the tenant id from the organization name
                const tenant = await nile.db.query(`SELECT id FROM tenants WHERE name = $1`, 
                    [user.organizationName]);

                if (!tenant.rows[0]) {
                    console.error(`Tenant ${user.organizationName} not found`);
                    continue;
                }
                nile.tenant_id = tenant.rows[0].id; // Set the tenant id so the user is created in the correct tenant
                newUser = await nile.api.users.createUser({
                    email: user.email,
                    password: tempPassword,
                    preferredName: user.Nickname || user.Name,
                });

                // uncomment this to update the password hash in the credentials table
                // only do this if you exported the password hashes in bcrypt format
                // await nile.db.query(
                //   `UPDATE auth.credentials SET payload = jsonb_build_object('crypt', 'crypt-bf/8', 'hash', $1) 
                //    WHERE user_id = $2 AND method = 'PASSWORD';`,
                //    [user.Password, newUser.Id]
                // )

                console.log(`Successfully migrated user: ${user.email}`);
                // You might want to store the temporary passwords to communicate them to users
                console.log(`Temporary password for ${user.email}: ${tempPassword}`);
            } catch (error) {
                console.error(`Failed to migrate user ${user.email}:`, error);
                // Continue with next user even if one fails
                continue;
            }
        }
        console.log('Migration completed');
    } catch (error) {
        console.error('Migration failed:', error);
    }
}

// This is necessary only if the organizations don't already exist in Nile
async function migrateTenants(nile: any) {
    try {
        // Read and parse the organizations JSON file
        const rawData = fs.readFileSync('auth0-organizations.json', 'utf8');
        const organizations: Auth0Organization[] = JSON.parse(rawData);

        // Process each organization
        for (const org of organizations) {
            try {
                const tenant = await nile.api.tenants.createTenant({
                    name: org.name,
                });

                console.log(`Successfully created tenant: ${org.name}`);
            } catch (error) {
                console.error(`Failed to create tenant ${org.name}:`, error);
                // Continue with next organization even if one fails
                continue;
            }
        }

        console.log('Tenant migration completed');
    } catch (error) {
        console.error('Tenant migration failed:', error);
    }
}

// Single initialization of Nile
async function migrateAll() {
    const nile = await Nile({});
    await migrateTenants(nile);
    await migrateUsers(nile);
}

migrateAll();

If you did not have the password hashes exported, your users will need to reset their passwords after the migration (unless you used passwordless authentication) - you can read how to do this in our password reset docs.

For staged migration, or for edge cases, you can implement the fallback strategy in your application. Attempt authentication with Nile Auth, and in the failure handler, attempt the Auth0 authentication. If Auth0 authentication succeeds, you can call nile.api.users.createUser to create the user in Nile Auth.

3

Migrate Social Providers

If you used social identity providers with , you will need to configure the same providers in Nile Auth.

You can configure social providers by going to “Tenants and Users” page in Nile Console and selecting the “Providers” tab.

Simply click on the provider you want to configure and you’ll see the provider configuration page. All providers use OAuth, so you’ll need to provide the OAuth client ID and secret. It is recommended to use the same client ID and secret as the one used in . And to use the same redirect URI in the social provider configuration.

You can see more details on how to configure and use each provider in the Single Sign-On section of the documentation.

Testing

We recommend you do thorough testing in a staging environment before migrating to production.

Before starting a migration, both in staging and in production, we recommend you create a few test users and organizations in your existing auth provider. Make sure you have a mix of email/password, passwordless and social providers users.

Then, after migrating to Nile Auth, test the following (both in test and in production):

  • Sign up and sign in with email/password, passwordless and social providers.
  • Sign in with email/password, passwordless and social providers.
  • Sign out
  • Reset password
  • Email verification
  • Validate that the users have access to the correct organizations.

It is also important to test negative flows. For example, trying to sign in with an invalid password, or an invalid email/password combination. You want to be sure that unauthorized users are not able to sign in.

Finally, use the “Tenant and Users” page in Nile Console to verify that the all the expected user data and metadata was migrated, and that the users have access to the correct organizations.

Best Practices

Here are some recommended practices for a smooth migration from Auth0 to Nile Auth:

  1. Staged Migration: Consider migrating users in batches rather than all at once. Start with a small subset of non-critical users or test accounts. Monitor for issues and gather feedback before proceeding with larger groups. This will allow you to test the migration and make sure it works as expected before migrating all users. The “fallback strategy” described in the migration steps can be used to support both Auth0 and Nile Auth during the migration.

  2. Communication Plan: Notify users well in advance of the migration. Provide clear instructions for any actions they n eed to take (like password resets). Set up support channels for users who encounter issues during the transition.

  3. Backup and Rollback Plan: Keep backups of all Auth0 data before starting the migration. Maintain the Auth0 configuration until the migration is complete and verified. Have a clear rollback plan in case of critical issues.

  4. Monitoring and Validation: Set up monitoring for authentication failures during and after migration. Implement logging to track successful and failed migrations. Validate user counts and access permissions after migration.

Was this page helpful?