Identify users with their username instead in firebase - firebase

I have a signup activity where users sign into firebase. But I want each user to have a different username of the format username#4-digit-code. How can I achieve this with Firestore as i found out with this post that we can't use queries in our transactions?
What would be the best approach for it to prevent two users from having the same userid?

What would be the best approach for it to prevent two users from having the same userid?
The best option that you have is to check if the username#4-digit-code already exists in Firestore. If it doesn't, add it with the corresponding data, otherwise, generate a new one. This operation should continue until you find an user name which is available.
If you want to make sure you aren't doing many checking operations, then you have to make sure you always generate unique user names, or you can use Firebase Authentication, and instead of that username#4-digit-code you can use the UID that comes from the authentication process.

Related

remove data from Firebase ID token

The data obtained from BaseAuth.verifyIdToken() contains, among other properties, the phone_number and email properties (like detailed here). It can be obtained with DecodedIdToken.phone_number.
What I want to do is hide these fields, so they wouldn't be passed at all in the token.
Is there a way to do that? from what I've seen here, you can add data using a custom token, but I couldn't find any information as for the other way around.
thanks!
The ID token that Firebase Authentication generates contains all information it has for that user. There is no way to hide part of the information from the token.
If you don't want certain properties to be present in the token you should leave them out of the Firebase Authentication profile for that user. For example, you could store them elsewhere, like in one of Firebase's cloud-hosted databases.

Is it dangerous to display the id of an Firestore document to the user?

i was wondering if its dangerous to show the user the id, which Firebase Cloud Firestore generates when creating an new document
Thanks for your answer
In general, no, it is not dangerous, unless you are using that document ID as a secret key somewhere else in your system. Since we don't know exactly how you're using this ID, it's not really possible to say for sure.
Primary Keys are usually shown to users. May it be your bank account number, your user id on platform X - it's not a problem in general, as long as the access in your application is limited properly.

Firestore dynamically update security rules

Imagine we have Chat application and in this application, we have many rooms, some private and some for everyone. Every room has an admin who can manage users (can invite and remove). Only members of the room can read and write messages. An Admin is a person who created a room in this scenario.
I want to create security rules on room creation and update it on membersChange so only members can read and write the content of the message board.
In this case, that's how it could look like:
databse/rooms/
private1
admin: memberX
members: member1, member2
//only admin can write into members fields
messages
message1...
message2...
message3...
//only members can write and read messages
private2
admin: memberXY
members: member1, member4
//only admin can write into members fields
messages
message1...
message2...
message3...
//only members can write and read messages
So is it possible to create and update security rules from cloud function instead of manually updating them in firebase console? Or is there any way to automate this process?
I noticed that I can deploy security rules using CLI. What should be the process here? When do I call it? How can I get members from the database?
EDIT:
for anyone who wants more information check How to Build a Secure App in Firebase
I would rethink this model. Instead of updating the security rules all the time, I see several viable approaches:
Option 1
You can save which users can access a specific room on Firestore, and then on the security rules you can access the document for the room and see which if the authenticated user is in the list of authorized users. The problem with this is cost, because this will fire an extra database read for every operation, which can get expensive.
Option 2
You can create custom claims for the user using a cloud function, like this:
admin.auth().setCustomUserClaims(uid, {"rooms": "room1,room2"})
Then on the security rules you can check if the user has the claims to a specific room:
match /rooms/{roomId} {
allow read: if roomId in request.auth.token.rooms.split(',');
}
I believe you can also save the claim as an array directly, but I haven't tested it.
For this option you need to take into consideration the size of the token, which has a limit and can cause performance problems if it's too big. Depending on your scenario you can create a smaller set of permissions and then set those to the rooms and the users.
Option 3
You could save the uid of the users who can access each document, and then check if the authenticated user's uid exists on that document. But this can get out of hand if you have too many users.
I would go with option 2 if it makes sense for your scenario. Or you could combine more than one of these techniques. My idea was to show a few of the possibilities so that you can choose what works for you.
Having different rules for each room and dynamicly updating your rules is a bad idea. Here are a couples problems that come to mind with this solution:
Who will be updating the rules?
What happens when two rooms get created at the same time?
What will happen when something goes wrong?
How will you maintain your rules when you have a million rooms?
Also It may be a few minutes before changes to your rules take effect.
Instead you can, first of all, split you datastructure into public rooms and private rooms: database/rooms/public/... and database/rooms/private/....
For securing your private rooms you can take a look at rules conditions and do something like: member can read/write IF his UID is in /members (pseudo code, won't work like this).
You can take a look at this question for an example.

What is the best practice for saving user data in Firestore/Firebase?

Specifically, should/can one one think of 'Collections' as table names and 'Documents' as unique keys ?
Should you use auto generated key, Auth uid or user email as documents names ?
What are the pros and cons of each if any ?
-Thanks
Yes, collections very closely resemble table names, as they would represent entities in object-oriented perspective. The documents are unique since each must have a unique id, the ids are the unique keys that identify each instance of an entity. No document can share a firebase id with another of the same collection.
Auth id keys seem to be the best idea for user firebase id's as it will allow you to sync between the firebase Auth, and Firestore/Firebase database, right out of the box. This is what I usually prefer. I would use autogenerated id's for other objects which have not been integrated into any other Firebase service. Having a consistent user id for both Firebase Auth,Firestore masks thing quite easy, since I only need to know one id, to access both services from the client end.

Allow users to see each other's data in firebase

Is there a why to let two user login with their own email and password and see the same data?
(Maybe one user well login and be transferred to the other user that has all the data).
Thanks,
Zvi Karp
What you were trying to do is about Database Design, it's actually not about Firebase. (watch out: the link is about relational database design, but Firebase is not using relational database. The idea is the same though.)
There are many ways to achieve your goal. Since you didn't describe your question clearly, I'll just give a general solution:
add a key sahredData to your User entity, and the value of this key is the id of the data you want to share between users. Different users can use the same value in this field(which means they share the same data).
whenever a user needs to access the shared data, use the value of sharedData, which is the id of the shared data, to access the data.

Resources