Can I use the auth:import and auth:export tools with the Firebase Auth Emulator?
I would like to preload the firebase auth emulator with my test user accounts whenever it starts up, the same way I do for the Firestore emulator with its import/export options. I tried using auth:import and auth:export while my emulators were running but it connected to our actual dev firebase project, and not the emulators. Is there anyway to run auth:import and auth:export against the auth emulator?
For reference, I am referring to these commands (https://firebase.google.com/docs/cli/auth) and this emulator (https://firebase.google.com/docs/emulator-suite/connect_auth).
Solution 1:
The ability to do this has now been added to the firebase tools
The older answers still work and may be useful
https://github.com/firebase/firebase-tools/releases/tag/v9.1.0
Support emulators:export and import for Auth Emulator (#2955).
https://github.com/firebase/firebase-tools/pull/2955
firebase help auth:import
Usage: firebase auth:import [options] [dataFile]
import users into your Firebase project from a data file(.csv or .json)
Options:
--hash-algo <hashAlgo> specify the hash algorithm used in password for these accounts
--hash-key <hashKey> specify the key used in hash algorithm
--salt-separator <saltSeparator> specify the salt separator which will be appended to salt when verifying password. only used by SCRYPT now.
--rounds <rounds> specify how many rounds for hash calculation.
--mem-cost <memCost> specify the memory cost for firebase scrypt, or cpu/memory cost for standard scrypt
--parallelization <parallelization> specify the parallelization for standard scrypt.
--block-size <blockSize> specify the block size (normally is 8) for standard scrypt.
--dk-len <dkLen> specify derived key length for standard scrypt.
--hash-input-order <hashInputOrder> specify the order of password and salt. Possible values are SALT_FIRST and PASSWORD_FIRST. MD5, SHA1, SHA256, SHA512, HMAC_MD5, HMAC_SHA1, HMAC_SHA256, HMAC_SHA512 support this flag.
-h, --help output usage information
Solution 2:
Thanks @alex-egli this was very helpful
Here's my version which is based on yours with 3 small changes
-
avoid an eslint warning https://eslint.org/docs/rules/no-await-in-loop
(I don't think your code is bad here and the warning could be muted) -
add in a check that this is being run on the emulator
-
added user display name
exports.populateAuthUsers = functions.https.onRequest(async (req, res) => {
if (!process.env["FUNCTIONS_EMULATOR"]) {
return res
.status(403)
.send("ACCESS DENIED. This function is ONLY available via an emulator");
}
const users = [
{
uid: "user1",
displayName: "one Local Admin",
email: "[email protected]",
password: "password",
},
{
uid: "user2",
displayName: "two Local Admin",
email: "[email protected]",
password: "password",
},
// put all test users you want populated here
];
const results = [];
const promises = [];
for (let user of users) {
let promise = admin
.auth()
.createUser(user)
.then((result) => {
return result;
})
.catch((error) => {
return error.message; // continue on errors (eg duplicate users)
});
promises.push(promise);
}
await Promise.all(promises).then((result) => {
results.push(result);
return;
});
res.header("Content-type", "application/json");
return res.status(200).send(JSON.stringify(results));
});
Solution 3:
Since firebase confirmed this is not supported I used a cloud function instead to do this. I first exported the users I would want to be loaded on startup into a json format, then I run this cloud function everytime I restart the emulators:
exports.populateAuthUsers = functions.https.onRequest(async (req, res) => {
try {
admin.initializeApp();
const users = [
{ uid: "user1", email: "[email protected]", password: "password" },
// put all test users you want populated here
];
const results = [];
for (let user of users) {
const result = await admin.auth().createUser(user);
results.push(result);
}
return res.status(200).send(results);
} catch (error) {
console.error('Error: ', error);
return res.status(500).send(error);
}
});
It only takes a couple seconds to run even with a few hundred users. Just make sure to never deploy this to any actual firebase environments! For local use only.