Migrate Firebase Users to Appwrite
Tags: opensource, appwrite, migration, tutorial
Published: 2022-09-14 13:18:11

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wntira29q6o22of38dyj.png)

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:

```bash
firebase auth:export users.json \
    --project [PROJECT_ID] \
    --format json
```

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:

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

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](https://appwrite.io/docs/sdks#server) to access the [Users](https://appwrite.io/docs/server/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](https://appwrite.io/docs/server/users#usersCreateScyptModifiedUser) function to create an Appwrite user from the Firebase one. 

Let's look at the signature of this function:

```js
async createScryptModifiedUser(
   userId,
   email,
   password,
   passwordSalt,
   passwordSaltSeparator,
   passwordSignerKey,
   name
)
```
 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:

```js
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
   );
}));
```

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/j7h8fp4hwnrvosx0sm11.png)

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

```js
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));
```

### 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](https://github.com/appwrite/appwrite/blob/master/CHANGES.md). If you're upgrading from Appwrite 0.15, be sure to follow our [upgrading guide](https://appwrite.io/docs/upgrade).

Our list of awesome tutorials, videos, and demos keeps growing. Head to the [awesome-appwrite](https://github.com/appwrite/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](https://30days.appwrite.io) series, where we explain step-by-step everything you need to know to build awesome Appwrite-powered apps. 

Come hang out on [Discord](https://appwrite.io/discord), follow us on [Twitter](https://twitter.com/appwrite_io), [Dev](https://dev.to/appwrite), or wherever you find your friendly neighbourhood Appwriter.