Firebase android: unique username

At the end of the year, Parse will be closed, so I decided to start using Firebase. I need to implement a registration process with three fields: email, username, password ( Email and username must be unique for my application).

Since Firebase does not provide an easy way to manage a username, such as Parse, I decided to use only email / password registration and save some additional data, such as username. Here is my user data structure:

app : { users: { "some-user-uid": { email: "test@test.com" username: "myname" } } } 

But I want to make a unique username and verify it before creating an account. These are my rules:

 { "rules": { ".read": true, ".write": true, "users": { "$uid": { ".write": "auth !== null && auth.uid === $uid", ".read": "auth !== null && auth.provider === 'password'", "username": {".validate": "!root.child('users').child(newData.child('username').val()).exists()"} } } } } 

Many thanks for your help.

+22
android firebase firebase-authentication firebase-security
Feb 06 '16 at 16:37
source share
3 answers

Part of the answer is to store an index of usernames that you check in your security rules:

 app : { users: { "some-user-uid": { email: "test@test.com" username: "myname" } }, usernames: { "myname": "some-user-uid" } } 

Thus, usernames node maps username to uid. It essentially reads that the "username" myname "belongs to" some-user-uid ".

With this data structure, your security rules can check if there is already an entry for a given username:

 "users": { "$uid": { ".write": "auth !== null && auth.uid === $uid", ".read": "auth !== null && auth.provider === 'password'", "username": { ".validate": " !root.child('usernames').child(newData.val()).exists() || root.child('usernames').child(newData.val()).val() == $uid" } } } 

This confirms that the username has not yet been declared by someone else, or it is claimed by the current user.

+35
Feb 06 '16 at 18:22
source share

Keep the usernames suggested by Frank, but when saving usernames, use the RunTransaction function in Firebase to make sure the username is not taken. This feature is guaranteed by Firebase as an atomic operation, so you can be sure of no collision.

 firebaseRef.child("usernames").child(username).runTransaction(new Transaction.Handler() { @Override public Transaction.Result doTransaction(MutableData mutableData) { if (mutableData.getValue() == null) { mutableData.setValue(authData.getUid()); return Transaction.success(mutableData); } return Transaction.abort(); } @Override public void onComplete(FirebaseError firebaseError, boolean commited, DataSnapshot dataSnapshot) { if (commited) { // username saved } else { // username exists } } }); 
+3
Mar 24 '16 at 13:15
source share

I don’t know much about firebase security, but I may have solved the problem using Java. I posted it below.

my data structure

 myapp { users: { <unique generated-id> { username: "example.username" } } } public boolean isUsernameExists(final String enteredUsername) { final Boolean[] isExist = {false}; FBref.child("users").addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { for (DataSnapshot userSnapshot : dataSnapshot.getChildren()) { String existingUsername = (String) userSnapshot.child("userName").getValue(); if (existingUsername.equals(enteredUsername)) { isExist[0] = true; } } } @Override public void onCancelled(FirebaseError firebaseError) { //some error thrown here } }); return isExist[0]; } 
-2
Mar 21 '16 at 10:33
source share



All Articles