How can I list all users using firebase admin sdk
Asked Answered
W

9

25

Is there a way to list all the users using the firebase admin sdk? Documentation only shows getting one user either by uid or email.

Willette answered 7/12, 2016 at 7:40 Comment(0)
P
22

The latest firebase-admin sdk (as of now version 5.4.2) has listUsers API that would do that. The example is here.

One thing to add to the example, the nextPageToken has to be omitted or a valid userid. (IMO, it's not obvious in neither the example or the API doc.)

Palpitant answered 23/10, 2017 at 3:44 Comment(2)
great comment about the nextPageToken. so true.Regicide
you can also set initial nextPageToken to 'undefined'. (setting it to null will break)Leannaleanne
C
14

Update As @Webp says in their answer, there is now an API to list all users in the Admin SDK.

Original answer:

There is no public API to retrieve a list of users from the Firebase Admin SDK.

The typical way to deal with this scenario is to keep a list of the pertinent user information in the Firebase Database. See this original question for more: How do I return a list of users if I use the Firebase simple username & password authentication

Crawly answered 7/12, 2016 at 8:32 Comment(0)
S
7

You can use auth().listUsers() method provided in the admin sdk. Detailed example code can be found here. Firebase Admin SDK Documentation

Sontich answered 6/3, 2018 at 4:13 Comment(0)
B
4

Its not a good solution, but you can export user data using Firebase CLI and integrate with your application.

auth:export

firebase auth:export account_file --format=file_format

https://firebase.google.com/docs/cli/auth

Bede answered 14/7, 2017 at 13:56 Comment(1)
this is the only solution that works, it's really sadCarnallite
C
4

In March 2020, after a lot of fighting with documentation and various posts, i found the following works:

const admin = require("firebase-admin");
const serviceAccount = require('./serviceAccount.json'); // see notes below about this.

const listAllUsers = () => {

    const app = admin.initializeApp({
        databaseURL: 'https://your-project-name.firebaseio.com',
        credential: admin.credential.cert(serviceAccount) <-- see notes below about this
    });

    app.auth().listUsers(1000) // lists up to 1000 users
        .then((listUsersResult) => {

            let users = JSON.stringify(listUsersResult);

            const date = new Date();
            const day = date.getDate();
            const month = date.getMonth() + 1;

            fs.writeFileSync(__dirname + `/../my-backups/authentication-backup_${day}_${month}_2020.json`, users);
        })
        .catch(function (error) {
            console.log('Oh no! Firebase listUsers Error:', error);
        });
}

re serviceAccount.json

This is NOT the same as the usual Firebase config you pass-in when using things like react-firebase or the npm firebase module on front end.

To gain CRUD rights server-side, you seem to need the following:

{
  "type": "service_account",
  "project_id": "my-project-id",
  "private_key_id": "xxxxxxxxxxxxxxxxxxx",
  "private_key": "-----BEGIN PRIVATE KEY-----\nMxxxxxxxxxxxxxxzuUA=\n-----END PRIVATE KEY-----\n",
  "client_email": "firebase-adminsdk-em4gz@my-project-name-email-thing.iam.gserviceaccount.com",
  "client_id": "0000000000000000000",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-em4gz%40my-proj-name.iam.gserviceaccount.com"
}

If you haven't generated one yet, I got mine by going:

Firebase Console => Project Settings => Service Accounts => Generate New Private Key

Cisalpine answered 2/3, 2020 at 10:48 Comment(0)
R
2

I got this async version working:

(I haven't thought about the flow of the code so the use of async here may be inefficient in terms of performance... I honestly only use async because I don't like looking at deeply nested promise code)

const firebase = require('firebase-admin');
const credential = require('./credential.json');

firebase.initializeApp({
  credential: firebase.credential.cert(credential)
});

let users = [];

async function getAllUsers(pageToken) {
  const results = await firebase.auth().listUsers(1000, pageToken);
  for (let i = 0; i < results.users.length; i++) {
    const user = results.users[i];
    const {uid, email} = user;
    users.push({uid, email});
  }
  if (results.pageToken) {
    getAllUsers(results.pageToken);
  }
};

(async () => {
  await getAllUsers();
  console.log(users);
})();
Reasoning answered 20/11, 2021 at 15:25 Comment(2)
why (async () => { await getAllUsers(); console.log(users); })()? Why not just: await getAllUsers(); console.log(users);Vladamir
@MariamGhalleb I could be wrong because I haven't coded in JavaScript for awhile but I think it's because the await keyword has to be used within an async function: anthonychu.ca/post/async-await-typescript-nodejsReasoning
R
0

As described in the official doc. Firebase Documentation the method to get list of users is mentioned already but it only lists max of 1000 users at a time. But if users are more than 1000 we need to use our own logic to get those remaining users with pagetokens/pagination.

Here I have tried to use that method in recursive manner to get full list of users in firebase database.

async getAllUsers(nextPageToken?: String): Promise<any[]> {

    // List batch of users can be max 1000 at a time.
    var _users_list = [];
    await this.firebaseAdmin.auth()
        .listUsers(100, nextPageToken)
        .then(async (listUsersResult) =>

            _users_list = listUsersResult.users;

            console.log("list user page token =>", listUsersResult.pageToken);
            
            if (listUsersResult.pageToken) {
                // List next batch of users.
                const temp_list =  await this.getAllUsers(listUsersResult.pageToken);
                if (temp_list.length > 0) { _users_list = _users_list.concat(temp_list); }
            }

        })
        .catch((error) => {
            console.log('Error listing users:', error);
        });

    return _users_list
};

This function returns the list of all users registered in firebase auth.

Here I have used batch of length 100 just to check if the function is working properly, You can change it up to 1000 at max, after thousand it throws Exceptions as described in firebase documentation

Rive answered 1/8, 2022 at 8:49 Comment(1)
I don't think u should use await and then at the same time.Vladamir
V
0
public async getAllUsers(): Promise<UserRecord[]> {
    const records: UserRecord[] = [];

    const listAllUsers = async (maxResults = 1000, nextPageToken?: string): Promise<void> => {
        const listAllUsersResult = await firebase.auth().listUsers(maxResults, nextPageToken);

        listAllUsersResult.users.forEach(userRecord => {
            records.push(userRecord);
        });

        if (listAllUsersResult.pageToken) {
            await listAllUsers(maxResults, listAllUsersResult.pageToken);
        }
    };

    await listAllUsers();

    return records;
}
Vladamir answered 20/10, 2022 at 19:16 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Szymanski
B
0

You can also use recursion to return all user records (UserRecord[]).

import * as FAdmin  from 'firebase-admin/lib/auth'

export const findUnusedUsers = functions.https.onCall((data, context) => {
  return listAllUsers().then(allUsers => {
     return allUsers
  })
})

const listAllUsers = (nextPageToken?: string, accumulatorUsers: FAdmin.auth.UserRecord[] = []): Promise<FAdmin.auth.UserRecord[]> => {
  return admin.auth().listUsers(1000, nextPageToken)
    .then(function(listUsersResult) {
      const users = [...accumulatorUsers, ...listUsersResult.users]
      if (listUsersResult.pageToken) {
        return listAllUsers(listUsersResult.pageToken, users)
      } else {
        return users
      }
    })
}
Beals answered 7/1, 2023 at 14:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.