I want to make unique usernames in firebase/firestore - javascript

app : {
users: {
"some-user-uid": {
email: "test#test.com"
username: "myname"
}
},
usernames: {
"myname": "some-user-uid"
}
}
I want to make unique usernames, like this: I would store all the usernames in a collection in firebase and than check if that doc with that username exists. This works perfectly fine but when I make a username with the same name on 2 accounts at the same time, user 1 makes the file and then user 2 overwrites that file.
How can I get around this?
This is not a copy of an asked question, all the answers answer how to make unique usernames but this bug is in all of them.

To prevent somebody being able to overwrite an existing username document, you'd use Firebase's security rules:
service cloud.firestore {
match /databases/{database}/documents {
// Allow only authenticated content owners access
match /usernames/{username} {
allow create: if !exists(/databases/$(database)/documents/usernames/$(username))
}
}
}
The above example allows creating the document if it doesn't exist yet. So with this the second write will be rejected.
You'll probably want to expand this to allow a user to only claim with their own UID, and unclaim a name too. To learn more on how to do that, I recommend reading the Firebase documentation on security rules.

Related

Auth0: How to add custom properties to UserObject?

Hello dear StackOverFlow community,
i don't know much about Auth0 and need help. And I wonder how to add my own properties when creating a user? just for info i have connected Auth0 to my own MongoDB atlas database.
i want to add a customId when creating a user, and this should be a 16-digit random number.
And my userObj should then look something like this:
{
_id: ObjectId("5f720126054c87001662a138"),
connection:"MongoDB"
client_id:"zoClZ3gZE56iwblHXQ1vgwEcLfYr81Bx"
email:"gustek#gustek.com"
username:"gustek"
password:"$2b$10$dE69gGsDqVfWtmnXZ6EaKetILUmEju8N9PVjtDpgzzAp4jYNQbe8G"
tenant:"dev-test"
email_verified:false
customId:"9829539769841530"
}
I mean I found something in the documentation but I do not know how to implement it:
https://auth0.com/docs/users/set-metadata-properties-on-creation
Do I have to do it over this surface?
As I said before, I have no idea how I could achieve this. I am grateful for every answer!
You can use an app_metadata property in the user object to store data that is not part of the normalized user profile. This would include a custom UUID like you described here.
The user object would look like this:
{
client_id: "<ID of creating client (application)>",
tenant: "<name of creating Auth0 tenant>",
email: "<email address for the user>",
password: "<password for the user>",
username: "<name associated with the user>",
user_metadata: {
"language": "en"
},
app_metadata: {
"custom_id": "1234567890"
}
}
While user_metadata and app_metadata are optional, if supplied, they do not need to be stored in the legacy identity store; Auth0 automatically stores these values as part of the user profile record created internally. These values are (optionally) provided as a reference: their contents potentially being influential to legacy identity creation.

How to get all users having custom claim as admin/moderator using firebase admin?

I want to send welcome message to all admins of my user database. Is there any method in firebase so that I can get list of all users with their custom claim as admin set to be true.
admin.auth().getUsers([
{ uid: 'uid1' },
{ email: 'user2#example.com' },
{ phoneNumber: '+15555550003' },
{ providerId: 'google.com', providerUid: 'google_uid4' },
])
Would above method applicable? If yes, then what parameter should I pass?
There is no built-in way to query Firebase Auth users based on custom claims on a user. If you want to be able to query, you would need to mirror the information into another database (like Firestore) and query that.
Otherwise, you will need to fetch every user and filter the results, which presumably is not an ideal solution.

Can a user update the script in a console and access other users' data in my firebase code?

For context, I display my Firebase app's configuration in the app.js file (is this safe?) and in order to give a user their data I list the following code:
db.collection('whispers').where("sender", "array-contains",
userID).orderBy('time').onSnapshot(snapshot => {
let changes = snapshot.docChanges();
changes.forEach(change => {
renderSay(change.doc);
});
});
Could a user remove the 'where' condition and access all data in this collection? I only use anonymous sign in so nothing special required in accessing their own data besides using the same device and not clearing data.
I doubt that could be possible by reverse-engineering but the actual security lies in the security rules.
You can change them from the Firebase Console
Here is a video from Firebase and here is the documentation
service cloud.firestore {
match /databases/{database}/documents {
// Match any document in the 'users' collection
match /users/{userID} {
allow read: if request.auth.uid === userID;
allow write: if request.auth.uid === userID;
}
}
}
Using the above security rules will allow users to read and write their data ONLY.
So even if they reverse-engineer your code, it will harm their data only and other data will be safe.
For more details please check the links above and you will get familiar with wildcard [{userID} in this case]
PS: Only you or anyone with access to your Firebase Console can change the rules
EDIT: This Medium Article has many types of rules explained. Please have a read there too :D

Build private chats in Firebase and Javascript

I am building an app with Firebase that requires private messaging between users.
What I need is to build single chats for 1-1 chats, storing messages in Firestore.
My idea: I guess the best way is to build a single collection for each chat, with the right security rules. Let's say an user with tokenID 1234 wants to talk with user with tokenID 1111, a new collection called 1234_1111 will be created (if not existing), and the security will allow only these two users to read and write.
My question: Is it the right way? And how to do that in Javascript? I'm not sure how to define security rules directly in the JS code, neither how to create a collection with the two users ID.
Security Rules are not defined in your JavaScript code, they are defined separately. What you suggest would be a reasonable approach to take although I'd use a subcollection for it, and a simplified version of your security rules might look something like:
service cloud.firestore {
match /databases/{database}/documents {
match /dms/{idPair}/messages/{msgId} {
allow read, write: if
idPair.split('_')[0] == request.auth.uid ||
idPair.split('_')[1] == request.auth.uid;
}
}
}
Then in your JS code you could do something along the lines of:
// generate idPair
function dmCollection(uid) {
const idPair = [firebase.auth().currentUser.uid, toUid].join('_').sort();
return firebase.firestore().collection('dms').doc(idPair).collection('messages');
}
// send a DM
function sendDM(toUid, messageText) {
return dmCollection(toUid).add({
from: firebase.auth().currentUser.uid,
text: messageText,
sent: firebase.firestore.FieldValue.serverTimestamp(),
});
}
// retrieve DMs
function messagesWith(uid) {
return dmCollection(uid).orderBy('sent', 'desc').get();
}
Note that the idPair is constructed by joining a sorted pair of UIDs so that it will be stable no matter which user sends.

Firebase - Allow user access to parts of database based on database information

I know how you can give a user read/write access to parts of the database using his UID, but I want to do something that is a little but more complicated, and I don't know how to do it. If I have a database structure like this:
Users:
oixMNpuyaaTTntNVl17MC74wL8e2:
accesTo:
Some Name: 'some value'
Some Other Name: 'some other value'
Stuff
Some Name
Information: 'More information'
InformationMore: 'Some more information'
In this case, I need user oixMNpuyaaTTntNVl17MC74wL8e2 to be able to access all the data under Some Name, which was specified somewhere else in the database. I hope I was able to explain my issue properly, and that this is possible! Also, it is not okay to set the Some Name child of Stuff to oixMNpuyaaTTntNVl17MC74wL8e2, because other users might also have access to Some Name.
Note: I'm using Firebase Web and Admin as well, using Python (Flask) and JavaScript.
I'm having a bit of trouble understanding your problem, if this isn't what you're looking for, please edit your question and explain what you're looking for in more depth.
If you want to limit access to "Some Name" to only users who have that access granted under the "Users" table, then you can write a rule that looks for the "Some Name" permission under that user. This rule would apply to all users of your app, so any user that has the access granted will be able to access that data.
Your rule would look like:
{
"rules": {
"Stuff": {
"$someName": {
".read": "root.child('Users').child(auth.uid).child('accesTo').val() == $someName"
}
},
// ...etc... other rules for other tables in your database
}
There are plenty more examples of this kind of thing in the documentation.

Categories