I'm creating a web app with Firebase on the back end where multiple users can access a feature, created by a root user.
The real-time db structure looks like this
project
project id
userID:userID of the user who created it
meta:other information about the project ...
team:
memberid1:{}
memberid2:{}
Until now, I've only allowed the root user to access the project. To do this, I've used the ref.orderByChild('userID').equalsTo(userID of user logged in) method of firebase js sdk to determine if the logged in user can access it because userID is a direct child of projectID.
But now, I want to allow multiple users to access a project. For this I've added a new child called team under which members can be added. But I can't use the aforementioned method to determine if a user who's logged in can access the project because the memberID is a grandchild of the project and hence orderByChild chained with equalTo won't work.
How could I do this with the DB structure as I stated above, and if it's not, how could I do this with a change in DB structure.
get project_id and team members of all projects and store in object with project id and member_id.Then, get project_id of corresponding to member id of logged in user and retrieve the project if project exists.
Yes we can definitely do that,the below code tries to explain that.
var uid = UserId of user logged in
ref.get().then(function(doc) {
if(doc.data().userID == uid || doc.data().team['memberid1] == uid || doc.data().team['memberid2'] == uid) {
\\ checks here whether user is authorized
}
});
One thing to note here is, if there are more than 2 members then this code may not be optimized
Related
I have a custom claim "admin" attached to each user, carrying a boolean.
Now, in my frontend i am trying to generate a list of all admins.
For that i need to access all users who have said custom claim set to "true" and put them in an array, which i can then generate the list from.
The array should just look like the following:
const admins = ref([
{
uid: *uid of admin1*,
name: *name of admin1*,
},
{
uid: *uid of admin2*,
name: *name of admin2*,
},
...
])
So the following problems arise:
How do i access all users with said custom claim set to true, so that i can loop over them and populate my array?
Is this a case for a cloud function, so that it can not be manipulated?
I tried reading this Firebase documentation, however i could not make sense of it.
How do i access all users with said custom claim set to true, so that i can loop over them and populate my array?
There is no direct way to query users based on custom claims.
Is this a case for a cloud function?
Yes, you would have to list all users as in the documentation that you've shared and check for custom claims for each user separately.
It might be best to use a database like Firestore or Realtime Database and maintain a collection of all admins. Make sure this cannot be updated from client side directly using security rules.
Is there a way I can get a specific user account from firebase and then delete it?
For instance:
// I need a means of getting a specific auth user.
var user = firebase.auth().getUser(uid);
// Note the getUser function is not an actual function.
After, I want to delete that user and their additional data:
// This works
user.delete().then(function() {
// User deleted.
var ref = firebase.database().ref(
"users/".concat(user.uid, "/")
);
ref.remove();
});
Firebase Documentation states that users can be deleted if they are currently logged in:
firebase.auth().currentUser.delete()
My aim is to allow logged in admin user to delete other users from the system.
When using the client-side SDKs for Firebase Authentication, you can only delete the user account that is currently signed in. Anything else would be a huge security risk, as it would allow users of your app to delete each other's account.
The Admin SDKs for Firebase Authentication are designed to be used in a trusted environment, such as your development machine, a server that you control, or Cloud Functions. Because they run in a trusted environment, they can perform certain operations that the client-side SDKs can't perform, such as deleting user accounts by simply knowing their UID.
Also see:
delete firebase authenticated user from web application
Another common approach is to keep a allowlist/blocklist in for example the Firebase Database and authorize user based on that. See How to disable Signup in Firebase 3.x
I know this is an old question, but I found another solution to this.
You definitely don't want to use firebase-admin in your application itself, as I think was suggested by Ali Haider, since it needs a private key which you don't want to deploy with your code.
You can however create a Cloud Function in Firebase that triggers on the deletion of a user in your Firestore or Realtime database and let that Cloud Function use firebase-admin to delete the user.
In my case I have a collection of users in my Firestore with the same userid's as created by Firebase Auth, in which I save extra user data like the name and the role etc.
If you're using Firestore as me, you can do the following. If you're using Realtime database, just look up in the documentation how to use a trigger for that.
Make sure your Firebase project has cloud functions initialized. There should be a folder named 'functions' in your project directory. If not: initialize Cloud Functions for your project with the following command: firebase init functions.
Obtain a private key for your service account in the Firebase Console on the following page: Settings > Service accounts.
Place the json-file containing the private key in the functions\src folder next to the index.ts file.
Export the following function in index.ts:
export const removeUser = functions.firestore.document("/users/{uid}")
.onDelete((snapshot, context) => {
const serviceAccount = require('path/to/serviceAccountKey.json');
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://<DATABASE_NAME>>.firebaseio.com"
});
return admin.auth().deleteUser(context.params.uid);
});
Now deploy your Cloud Function with the command firebase deploy --only functions
When a user is deleted in your Firebase Firestore, this code will run and also delete the user from Firebase Auth.
For more information on Firebase Cloud Functions, see https://firebase.google.com/docs/functions/get-started
Just apply this code same way that you have done authentication.
var user = firebase.auth().currentUser;
user.delete().then(function() {
// User deleted.
}).catch(function(error) {
// An error happened.
});
Using the Javascript API (not the admin SDK)
Like this answer points out for user sign in, a second app must be created to be able to delete another user than the one logged in.
This is how I did it:
async deleteUser (user) {
// Need to create a second app to delete another user in Firebase auth list than the logged in one.
// https://stackoverflow.com/a/38013551/2012407
const secondaryApp = firebase.initializeApp(config, 'Secondary')
if (!user.email || !user.password) {
return console.warn('Missing email or password to delete the user.')
}
await secondaryApp.auth().signInWithEmailAndPassword(user.email, user.password)
.then(() => {
const userInFirebaseAuth = secondaryApp.auth().currentUser
userInFirebaseAuth.delete() // Delete the user in Firebase auth list (has to be logged in).
secondaryApp.auth().signOut()
secondaryApp.delete()
// Then you can delete the user from the users collection if you have one.
})
}
In my opinion, you can delete specific user without Firebase Admin SDK. You must to storage Username, Password of accounts you want to manage. And login with account - you declare a admin account. After that just follow steps: using firebase auth to logout -> using firebase auth to login with account you want to delete -> using firebase auth to delete that account -> using firebase auth to logout -> login again with that "admin account". Hope this solution help you to delete accounts without using Firebase Admin SDK
I am making a voice recording application in which the recording is saved in firebase storage in a folder named emailID (user email id when registered). I want that only the user can have access to that folder. Means that user can only open their own folder (matching name to their email). I want this feature to make my application more secure. I need the javascript code for the storage rules (according to my need) in firebase.
In this way, no one can get access to firebase storage until they log in, and after that, they can have access to their folder only.
It sounds like you're looking for this:
service firebase.storage {
match /b/{bucket}/o {
// Files look like: "Zrecorder/<email>/path/to/file.txt"
match /Zrecorder/{email}/{allPaths=**} {
allow read, write: if request.auth.token.email == email;
}
}
}
Also see:
The Firebase documentation on properties in the request variable
I am working on the vue-firebase application and want to know that how can I get the list of all registered users in firebase auth.
I am quite not sure if that is possible with one user try to get all the users, unless you are using firebase-admin. Though I have an idea how you can do that if you trying to get a list of added user being another user.
So, try to keep another list when a new user logs in, add the user details to a new node like userList.
And when ever you need them, call that node.
And incase you are using firebase-admin
admin.auth().listUsers(1000, nextPageToken)
.then(function(listUsersResult) {
will give the list.
Here's a reference. https://firebase.google.com/docs/auth/admin/manage-users#list_all_users
I'm currently using firebase-admin to create a web Dashboard with node.js as a backend which will have multiple users and those users have user specific data in my database, note that I need them to be able to delete or add stuff to the database as well, I've managed to add new users to Autentication using firebase.auth().createUser() programmatically, but how would one go about logging in a user, and then from there controlling which uid is logged in and displaying his data (giving him access to the correct data, obviously don't want him messing with someone elses data).
I know this might seem like a really newbie question, and it probably is, but firebase docs always get me confused for some reason. Any tips? I'd greatly appreciate.
Any questions don't hesitate.
To login a new user, try this:
firebase.auth().signInWithEmailAndPassword(email, password)
this returns a Firebase.Promise which you can use to track the operation progress. If successful, it will return the corresponding Firebase.User object.
From there, the logged-in user will also be available in the firebase.auth().currentUser property. You can then use the user's uid property as a key for his JSON branch on the database.