Migrating users between projects and tenants

This document explains how to migrate users from an existing Identity Platform project to a different one. It also shows how to migrate users from a non-tenant project to a tenant, or migrate users between tenants.

Before you begin

Configuring service account keys

Before you can migrate user accounts, you need service account keys for both the source and target projects. The service accounts must be granted at least the IAM Editor role (roles/editor) to access the users and their hashed passwords from the source project. See the IAM documentation to learn more about creating service accounts, granting permissions, and obtaining keys.

After downloading the keys, use them to instantiate two auth instances.

var admin = require('firebase-admin');

var sourceApp = admin.initializeApp({
  credential: admin.credential.cert('source-project-service-account.json'),
}, 'source-app');

var targetApp = admin.initializeApp({
  credential: admin.credential.cert('target-project-service-account.json'),
}, 'target-app');

var authFrom = sourceApp.auth();
var authTo = targetApp.auth();

If your access control policies don't allow the use of multiple service accounts in a single workload, you can still use the example code from this document, but you'll need to download all users from the source project to a storage system first, then upload them to the target project in a separate workload.

Migrating users between projects

To migrate users, call the admin.auth().listUsers method, which returns a a paginated list of users. You can then call admin.auth().importUsers() to upload them to the target project.

A maximum of 1000 users can be downloaded or uploaded at a time.

For password users, you need to supply the hash config for password hashing. You can retrieve the hash config by navigating to the Identity Platform Users page in the Google Cloud console, and then clicking Import Users.

The following example shows how to migrate users:

function migrateUsers(userImportOptions, nextPageToken) {
 var pageToken;
 authFrom.listUsers(1000, nextPageToken)
   .then(function(listUsersResult) {
    var users = [];
    listUsersResult.users.forEach(function(user) {
      var modifiedUser = user.toJSON();
      // Convert to bytes.
      if (user.passwordHash) {
       modifiedUser.passwordHash = Buffer.from(user.passwordHash, 'base64');
       modifiedUser.passwordSalt = Buffer.from(user.passwordSalt, 'base64');
      }
      // Delete tenant ID if available. This will be set automatically.
      delete modifiedUser.tenantId;
      users.push(modifiedUser);
    });
    // Save next page token.
    pageToken = listUsersResult.pageToken;
    // Upload current chunk.
    return authTo.importUsers(users, userImportOptions);
   })
   .then(function(results) {
    results.errors.forEach(function(indexedError) {
       console.log('Error importing user ' + indexedError.index);
     });
     // Continue if there is another page.
     if (pageToken) {
         migrateUsers(userImportOptions, pageToken);
     }
   })
   .catch(function(error) {
     console.log('Error importing users:', error);
   });
}
var userImportOptions = {
 hash: {
   algorithm: 'SCRYPT',
   // The following parameters can be obtained from the "Users" page in the
   // Cloud console. The key must be a byte buffer.
   key: Buffer.from('base64-secret', 'base64'),
   saltSeparator: Buffer.from('base64SaltSeparator', 'base64'),
   rounds: 8,
   memoryCost: 14
 }
};

migrateUsers(userImportOptions);

For more information, see the Admin SDK API reference.

Migrating users to a tenant

Migrating users from a non-tenant project to a tenant is almost exactly the same as migrating users between projects.

Assuming the tenant belongs to a different project than the source Identity Platform project, use the same code as before, but call admin.auth().tenantManager().authForTenant() on the target app instance and set the target tenant ID before calling importUsers().

var authTo = targetApp.auth().tenantManager().authForTenant('tenant');

Migrating users between tenants

Migrating users between tenants is very similar to migrating users between projects, with two key differences:

  1. You'll need to delete the tenant ID from users of the old tenant before uploading them to the new tenant. Skipping this step will result in tenant ID mismatch errors.

  2. Call admin.auth().tenantManager().authForTenant() to set the tenant ID on the source and target tenants.

    // Migrate from tenant1 to tenant2 in same project.
    var authFrom = admin.auth().tenantManager().authForTenant('tenant1');
    var authTo = admin.auth().tenantManager().authForTenant('tenant2');
    

The rest of the code is the same.