0
votes

Context

I'm using Firebase phone authentication. and i have one mobile app for users and one web app for admin. both users are stored in one collection.

Requirement

Now I want to validate that user is a admin when a user try to login in Web Application. I keep data with users that "isAdmin" like this...


users:[
 {
   name:'John Doe', 
   phoneNumber:'+911234567890', 
   isAdmin:true
 } ]

Now I want to validate every web authentication that user is an admin. otherwise i want deny the authentication,

Language: Javascript

1
"I keep data with users that "isAdmin" like this" => Where do you keep this data? I a Firestore dataabse? - Renaud Tarnec
@RenaudTarnec maybe he want to use custom claims which will help him to validate user - Ashish
@Ashish Yes, this is what I had in mind but, before proposing him this approach, I wanted to understand where is the isAdmin property set. The idea was to emphasized, in an answer, the advantages & drawbacks of a solution based on a field in Firestore, compared to Custom Claims (e.g.: easier to modify by end users -no need to use the Admin SDK-, extra Firestore read, ...). - Renaud Tarnec
@RenaudTarnec that's one way to use authentication - Ashish
@RenaudTarnec I keep it in firestore - Faris MX

1 Answers

3
votes

Since the user's role is stored in a user document in a Firestore collection (named users if I correctly understand), when the user is signed-in (and therefore you have the user's uid and phone number) you should query the users Firestore collection to get his/her role (isAdmin true or false).

Then based on the role, you can either display the content of the Admin app or show an error and sign-out the user (you cannot "deny the authentication" but you can sign-out the user after he/she signs-in).

HOWEVER, the most important is to secure your database (and other Firebase backend services, if you use them) with some Security Rules based on the role. If your backend is secured, a non-authorized user who succeeds in opening or reverse-engineering your Admin frontend app can maybe see the GUI elements but cannot read and modify the corresponding data.

Since you store the role in a Firestore document, you need to use, in your Security Rules, the get() function, in order to get the contents of the user document. See the example in the doc.


Having said that, another classical approach to set up a role-based access-right strategy is to use Custom Claims, as explained by @Ashish in his answer.

One main advantage of using a Custom Claim is that the role (the claim) is contained by the ID token and therefore no additional lookup to a Firestore doc is needed to check for admin permissions.

You should note that you can only set Custom Claims from a privileged server environment by using the Firebase Admin SDK. This means via a server you own or via a Cloud Function (see this article, for example). You could also use the new dedicated "experimental" extension.

Setting the roles through a Firebase doc, as you do, is easier (just a document write or update), but you need to correctly secure the collection, in order to avoid a malicious user can modify a user doc.

Another advantage of Custom Claims is that they can be used in the Security Rules of all the services (Firestore, Cloud Storage, RTDB). With role declaration via a Firestore doc, you should note that you cannot get this role in a Cloud Storage or RTDB Security Rule (you cannot read Firestore from Security Rules of the other services).