DEV Community 👩‍💻👨‍💻

Cover image for Migrate Firebase Users to Appwrite
Jake Barnby for Appwrite

Posted on

Migrate Firebase Users to Appwrite

With the release of Appwrite 1.0, a ton of new features are available. One of these features is the ability to import and export users. This means you can export your user's accounts from services like Firebase, Supabase, and others, then import them into Appwrite. This makes getting started with Appwrite a lot easier if you're coming from another backend as a service.

What is Appwrite?

Appwrite is an open-source, end-to-end backend server for web and mobile developers that allows you to build apps much faster. It abstracts and simplifies everyday development tasks behind REST APIs and tools, helping you build apps faster.

Step 1: Obtain Firebase Password Hash Parameters

The first step is obtaining the required properties from your Firebase project. To do this, head to your project and navigate to the Authentication service. Here you will see a list of your users. In the top right corner of the list, there is a settings menu. Opening this menu will reveal a Password hash parameters option. Clicking this will open a dialog with the information we are looking for.

Password hash parameters

From this dialog, we need to note down the base64_signer_key and base64_salt_separator. These will be used later when we import users into Appwrite.

Step 2: Export Firebase Users

The next step is to export all of the existing users in the project. There are two ways to do this, using the Firebase CLI directly or using the firebase-tools NodeJS wrapper. Let's first use the CLI and later look at an example script using NodeJS to export and import users. This assumes you already have the CLI installed and have logged in.

We can export users using the following command, ensuring you replace the project ID with your own:

firebase auth:export users.json \
    --project [PROJECT_ID] \
    --format json
Enter fullscreen mode Exit fullscreen mode

This will create a file named users.json with all of the user information for the given project. Looking at the output JSON, we can see that each user has the following structure:

{
    "localId": "7hlgnwk4jth123pv0QWs4I594Op2",
     "email": "user1@appwrite.io",
     "emailVerified": false,
     "passwordHash": "/Q+0ZSsrgG06/T+UAM1osdfkm9wra7MdKN+08nGyVl2HMXzlaA==",
     "salt": "ENsdflkmBkUJw==",
     "createdAt": "1663120692349",
     "disabled": false,
     "providerUserInfo": []
}
Enter fullscreen mode Exit fullscreen mode

We will need the email, passwordHash and salt specifically. We now have everything we need to move these users into Appwrite!

Step 3: Import Users to Appwrite

To import users into Appwrite, we can use any Server SDK to access the Users API. For this example, we will use the NodeJS SDK.

All server SDKs have the same functions and parameter names as listed below.

Newly added functions let you create a user with one of 7 different hashing algorithms. Firebase uses a modified version of the SCrypt algorithm, so we will use the createScryptModifiedUser function to create an Appwrite user from the Firebase one.

Let's look at the signature of this function:

async createScryptModifiedUser(
   userId,
   email,
   password,
   passwordSalt,
   passwordSaltSeparator,
   passwordSignerKey,
   name
)
Enter fullscreen mode Exit fullscreen mode

Going through the function parameters one by one:

  • userId: The ID to assign to the new user in Appwrite. It can be custom, or you can use the SDK's new ID.unique() function to assign a randomly generated ID.
  • email: Corresponds to the email value from users.json
  • password: Corresponds to the passwordHash value from users.json
  • passwordSalt: Corresponds to the salt value from users.json
  • passwordSaltSeparator: The base64_salt_separator from the Firebase console
  • passwordSignerKey: The base64_signer_key from the Firebase console
  • name: The name to assign to the user. Can be null

Putting this all together, we could import all of the exported users into Appwrite like so:

const json = await fs.readFile('users.json', {encoding: 'utf8'});
const exported = JSON.parse(json).users;

await Promise.all(exported.map(async user => {
   await users.createScryptModifiedUser(
       ID.unique(),
       user.email,
       user.passwordHash,
       user.salt,
       base64SaltSeparator,
       base64Signer,
       null
   );
}));
Enter fullscreen mode Exit fullscreen mode

Once complete, all the exported users can log in to Appwrite with their existing email and password! Even better, the first time the users log in to Appwrite after the import, their passwords will be re-hashed using the more secure Argon2 algorithm.

Imported Users in Appwrite

Automated Process with NodeJS

We can use the firebase-tools node module to automate more of the process. We export and import the Firebase users into Appwrite using node in the following script.

The configuration variables for both Appwrite and Firebase would need to be filled in with the appropriate values before running the script.

This script does not handle Firebase authentication, so you will still need to run firebase login beforehand or modify the script to provide credentials.

const {Client, Users, ID} = require("node-appwrite");
const firebase = require("firebase-tools");
const fs = require('fs/promises');

// Appwrite configuration
const endpoint = 'http://localhost/v1';
const appwriteProjectId = 'YOUR_PROJECT_ID';
const appwriteApiKey = 'YOUR_API_KEY';

// Firebase configuration
const firebaseProjectId = '';
const base64Signer = '';
const base64SaltSeparator = '';

const client = new Client()
   .setEndpoint(endpoint)
   .setProject(appwriteProjectId)
   .setKey(appwriteApiKey)
   .setSelfSigned()

const users = new Users(client);

const migrate = async () => {
   const outfile = 'users.json';
   await firebase.auth.export(outfile, {project: firebaseProjectId, format: 'json'})
   const json = await fs.readFile(outfile, {encoding: 'utf8'});
   const exported = JSON.parse(json).users;

   await Promise.all(exported.map(async user => {
       await users.createScryptModifiedUser(
           ID.unique(),
           user.email,
           user.passwordHash,
           user.salt,
           base64SaltSeparator,
           base64Signer,
           null
       );
   }));
};

migrate()
   .then(r => console.log('Done!'))
   .catch(e => console.log(e));
Enter fullscreen mode Exit fullscreen mode

Check Out Appwrite 1.0 For Much, Much More

That's not all! There are many other new features, fixes and optimizations to make everyone's Appwrite experience the best it can be. For full details of the 1.0 release, you can check out the full changelog on GitHub. If you're upgrading from Appwrite 0.15, be sure to follow our upgrading guide.

Our list of awesome tutorials, videos, and demos keeps growing. Head to the awesome-appwrite repo to check them out.

If you've just discovered Appwrite and want to get started, check out our 30 Days of Appwrite series, where we explain step-by-step everything you need to know to build awesome Appwrite-powered apps.

Come hang out on Discord, follow us on Twitter, Dev, or wherever you find your friendly neighbourhood Appwriter.

Top comments (0)

🌚 Friends don't let friends browse without dark mode.

Sorry, it's true.