Open Acterion opened 3 years ago
Would also like to know, what the way to go is, when needing auth data.
I have the same need.
For me, the following error occurs:
{
errorInfo: {
code: 'auth/invalid-credential',
message: 'Failed to determine project ID for Auth. Initialize the SDK with service account credentials or set project ID as an app option. Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.'
},
codePrefix: 'auth'
}
What I did:
export FIRESTORE_EMULATOR_HOST="localhost:8080"
fireway migrate
What to do to get the firebase-admin functions working with Fireway?
By the way, I came across this package (looks like a fireway fork?) that seems to support --emulator
as an option. FWIW, it seems to me like a neater solution.
I'd accept a PR for an --emulator
option!
I'd rather expose the result of admin.auth()
directly. This provides the ability to do a --dryrun
for auth in the future. I would also accept PRs for that, assuming there were tests.
I'd rather expose the result of admin.auth() directly
I'm not sure I understand this.
FWIW, here's a snapshot of the migration script that produces the error I shared above:
// v0.0.2_set_custom_claims.js
const { listAllUsers } = require("./helpers");
/**
* set custom claims on all firebase auth users
* */
module.exports.migrate = async ({ firestore }) => {
/**
* set the custom claims for all users
*/
const setCustomClaims = async () => {
// fetch all user entries from firebase auth
let firebaseAuthUsers = [];
await listAllUsers(firebaseAuthUsers); // firebaseAuthUsers is a List<JSON> representing the auth user objects
console.log("firebaseAuthUsers: ", firebaseAuthUsers);
// for each auth user:
for (authUser in firebaseAuthUsers) {
// set auth custom claims ...
}
};
// run the function
setCustomClaims();
};
// helpers.js
const admin = require("firebase-admin");
/**
* enumerates all [firebase auth] users from the firebase project
* adapted from https://firebase.google.com/docs/auth/admin/manage-users#list_all_users
*
* @param {List<JSON>} usersList empty list to append the results into
* @param {string} nextPageToken
* @returns {List<JSON>} a list of JSON objects representing users
*
*/
exports.listAllUsers = function(usersList, nextPageToken) {
// List batch of users, 1000 at a time.
return admin
.auth()
.listUsers(1000, nextPageToken)
.then((listUsersResult) => {
listUsersResult.users.forEach((userRecord) => {
usersList.push(userRecord.toJSON());
});
if (listUsersResult.pageToken) {
// List next batch of users.
return listAllUsers(usersList, listUsersResult.pageToken);
}
// the compiled list, after all the batches are fetched
return usersList;
})
.catch((error) => {
console.log('Error listing users:', error);
});
};
I'd rather expose the result of admin.auth() directly
I'm not sure I understand this.
I want to reduce surface area, because in my experience, more surface area is more that can break. If you need auth
, fireway
can expose auth
.
FWIW, here's a snapshot of the migration script that produces the error I shared above:
If it runs against localhost, but not remotely, continue to do what you're doing now (const admin = require("firebase-admin")
), but configure it with your remote credentials. Ideally, this would be handled nicely by fireway
, but isn't right now.
If you need auth, fireway can expose auth.
It'd be nice to see how to use the fireway
-provided auth
.
If it runs against localhost, but not remotely, continue to do what you're doing now
It doesn't work on localhost right now (the error I shared is from localhost - 'Failed to determine project ID for Auth . Initialize the SDK with service account credentials or set project ID as an app option. Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.'
).
To rephrase the issue: I don't know how else on localhost (besides setting the env variable) to tell fireway that I am using the Firebase emulator and that I don't have a real project ID or other credentials since I'm using the emulator.
Thanks for your patience, I am new to JS/NoSQL :)
If you need auth, fireway can expose auth.
It'd be nice to see how to use the
fireway
-providedauth
.
It doesn't work today, but ideally your migration file could look something like:
module.exports = async ({ firestore, auth }) => {
// your migration logic
};
If it runs against localhost, but not remotely, continue to do what you're doing now
It doesn't work on localhost right now (the error I shared is from localhost -
'Failed to determine project ID for Auth . Initialize the SDK with service account credentials or set project ID as an app option. Alternatively set the GOOGLE_CLOUD_PROJECT environment variable.'
).To rephrase the issue: I don't know how else on localhost (besides setting the env variable) to tell fireway that I am using the Firebase emulator and that I don't have a real project ID or other credentials since I'm using the emulator.
Ah. An --emulator
flag would make this less painful. For now, manually using the FIRESTORE_EMULATOR_HOST
env variable is probably your best bet. There might be a way to use @firebase/testing
, but I haven't explored that.
Thanks for your patience, I am new to JS/NoSQL :)
No worries! Happy to help.
For now, manually using the
FIRESTORE_EMULATOR_HOST
env variable is probably your best bet
It normally works for me but it's not working for me in this particular use case (i.e., when using the firebase admin SDK's modules - auth
in this case) :(
I have also tried running the script against a remote database by providing the --projectId
option (and unsetting FIRESTORE_EMULATOR_HOST
) but I still get the same error
app
property which is provided by fireway seems like works for me
--dryrun
option doesn't work for auth updates (only for firestore)--forceWait
option to make it worksconst clearClaims = async (auth, authUser) => {
if (authUser.customClaims) {
return await auth.setCustomUserClaims(authUser.uid, null);
}
};
const updateClaims = async (auth, authUser, changes) => {
const newCustomClaims = { ...authUser.customClaims, ...changes };
return await auth.setCustomUserClaims(authUser.uid, newCustomClaims);
};
module.exports.migrate = async ({ firestore, app }) => {
const auth = app.auth();
const usersSnapshot = await firestore.collection("users").get();
usersSnapshot.forEach(async (snapshot) => {
const userId = snapshot.id;
try {
const authUser = await auth.getUser(userId);
// await clearClaims(auth, authUser);
// console.log(authUser.customClaims);
await updateClaims(auth, authUser, { admin: true });
} catch (error) {
// console.log(error, userId);
}
});
};
Hi. In my case, the fireway app.auth()
(v1.0.2) was failing using emulator even with --forceWait
as suggested by @dsvgit (even with the --dryRun
switch).
I was getting the following error
FirebaseAuthError: Failed to determine project ID for Auth. Initialize the SDK with service account credentials or set project ID as an app option. Alternatively set the GOOGLE_CLOUD_PROJECT environment variable. at FirebaseAuthError.FirebaseError [as constructor] hereunder my command line to start the migration FIRESTORE_EMULATOR_HOST=localhost:8080 yarn fireway migrate --require=ts-node/register --forceWait --dryRun
I end up configuring my env using these two variables:
GCLOUD_PROJECT=myproject FIREBASE_AUTH_EMULATOR_HOST=localhost:9099
Local migration using 'app.auth' works properly with the emulator now !
Is it even possible to access the admin object from the migration script?
I want to change some filed names inside
customUserClaims
, so I thought it would be nice to create a migration for that. But for doing that I would need toaccess admin.auth().listUsers()
and then runsetCustomUserClaims()
for each individual user.I've added
const admin = require("firebase-admin");
before the script, which amazingly worked, but that feels like a workaround and not a proper solution.I would suggest adding
admin
object toMigrateOptions