Is there a built-in method to check for the existence of a user without exposing your 'user' collection to unauthenticated users? (Read-only access will still expose the entire collection of users.) Below is the traditional solution:
usersRef.child('users').child(userId).once('value', function(snapshot) {
var exists = (snapshot.val() !== null);
});
My use-case is a registration flow with multiple steps. I want to check for the existence of a user before the candidate arrives at the final step.
My initial thought on how to resolve this issue is to create an Admin service that can return the result while limiting queries from individual users (similar to how the built-in sign-in logic restricts multiple invalid retries).
I am aware of the "auth/email-already-in-use" error code returned from createUserWithEmailAndPassword
. However, the check needs to be performed before the password is provided.
Just making sure it doesn't exist before I start hammering out the service ;)
To be able to check whether a certain node exists, you must be able to read that node. If we look specifically at your code:
usersRef.child('users').child(userId).once('value', ...
This code requires that the user has read access to /users/$userId
. It does not require that they have access to all of /users
.
Same if you'd create a top-level emails
node, where you keep the emails that are already in use. To check if a specific email is already in use, all the user needs is access to /emails/$email
, they don't need to have access to /emails
.
So:
{
"rules": {
"users": {
"$uid": {
".read": "auth.uid !== null"
}
},
"emails": {
"$email": {
".read": "auth.uid !== null"
}
}
}
}
The big deal about these rules is that anyone trying to read from /users
or /emails
will be rejected, so that prevents them from getting access to a list of all users or emails. But given an individual UID or email address, they can check whether that is already claimed or not.
Note that hammering out your own service is fine too. But if the basic use-case is to securely check whether a specific UID/email is already claimed, you can probably get by with just the database.