Deleting Anonymous Users with Firebase

Firebase Auth has a little bit of a problem. The idea of having Anonymous accounts is nice, but they can pile up very easily and there is absolutely no easy way to get rid of them. Really there is no easy way to delete any large number of users. There’s a couple methods of dealing with this with code.

Don’t Let Them Pile Up in the First Place

If you’re using anonymous accounts for something one time, like a web game. It might be easier to just delete the user once they leave.

// delete the user when they exit the page
window.onbeforeunload = function(){
currentUser.delete()
};

Set Up a Scheduled Function

If you want to delete the users after a certain time period, you could set up a cloud function to run on a schedule. You’ll need to use the Admin API. I used the “firebase-functions-helper” module to make things a little easier.

There’s also the really annoying caveat that you can only delete 10 users a second. To get around that, I put in a Promise to just wait for a second before retrying the delete. Here’s all the code:


// The Cloud Functions for Firebase SDK to create Cloud Functions and setup triggers.
const functions = require('firebase-functions');
// The Firebase Admin SDK to access Cloud Firestore.
const admin = require('firebase-admin');
// Use moment library to check inactivity dates
const moment = require('moment');
// Make it easier to write the function
const helper = require("firebase-functions-helper")
helper.firebase.initializeApp(ServiceAccountKey,"Database URL")
exports.removeAnon = functions.pubsub.schedule('every day 12:00').onRun((context) => {
let deleted = [];
return helper.firebase
.getAllUsers()
.then(users => {
users.map(user => {
//A user is inactive if they haven't logged in in 7 days
let inactive = moment(user.metadata.lastSignInTime ).isBefore( moment().subtract( 7, "days" ))
//A user is anonymous if there is no providerData
if(user.providerData.length == 0 && !user.emailVerified && inactive){
deleted[deleted.length] = user.uid;
}
})
})
.then((async ()=>{
//Divide all the users into chunks of 10 since we can only delete 10 per second
let chunks = deleted.reduce((all,one,i) => {
const ch = Math.floor(i/10);
all[ch] = [].concat((all[ch]||[]),one);
return all
}, [])
// To avoid getting a timeout, we just delete 100 users in total
for (let i = 1; i < 10; i++) {
// Wait for 1 second before deleting the next batch
await new Promise(resolve => setTimeout(resolve, 1000));
// DELETED!!!
helper.firebase.deleteUsers(chunks[i]);
}
}))
.catch((err)=>{
console.log(`Delete Error: ${err}`);
})
});