Using Firebase Custom Claims for Admins (Firestore & Cloud Storage) - firebase

Giving Admin Rights
I'm using Custom Claims to give admin rights to users, by triggering it when a document in "admins/{userId}" is created.
A Cloud Function then sets the "admin" property in the users custom claims to true. Then the user needs login again and he is admin.
Now I check for the admin Custom Claim in the security Rules of Firestore and Storage, so the user can delete/edit everything.
Revoking Admin Rights???
But when I want to revoke the Admin Rights on a user, how do I make sure that the rights are really revoked everywhere.
For the Firestore I can add an additional check, that also gets the data from the Firestore "admins/{userId}" direction and does not allow access.
BUT if I revoke the Rights and the user does not refresh his token, he can still edit/delete everything in the Firestorage.
And since I can't access Firestore data from the Storage-Security, I can't even double check the "admins/" direction.
So how do I reliably implement an admin functionality for firestore and storage?

As Doug Stevenson says, the token of a 'revoked admin' should expire within an hour after which the refreshed token wouldn't contain the admin custom claim. I think you're on the right track with using Firestore rules to check your 'admins' collection rather than the custom claim.
If immediately revoking rights to Firebase Storage is crucial, you may need to redesign your app so that rather than giving your client direct access to Storage, files can only be accessed through a Firebase Function you build that will validate access authorization against your Firestore 'admins' collection and, if approved, serve the file to the client.

Related

Authenticate only "admin" users registered with Firebase Auth

I have an app that lets users sign in via email and password. The app has a feed with posts that need to be moderated. I have an admin react website that lets the moderators remove or keep posts. Right now any user can login and see the content, however I wanna make the login only available for admin users. I made my account "admin" using Admin SDK of Firebase.
I was thinking to make a Cloud Function which verifies whether the email is an admin and return true or false accordingly. Then authenticate the user normally using Firebase Auth. Is this secure enough?
If you've set a custom claim marking the user as an application administrator, you can check in your client-side code for the presence of that claim. You can then use the result of that to show the correct UI.
On the server/in the database security rules, you'll also want to check the presence of this admin claim before allow the user to access/modify the moderator data.
Note that none of these prevents the users from authenticating. Authentication in Firebase is nothing more than entering your credentials to prove that you are you. Granting access to resources based on who you are, known as authorization, is up to the application, hence including it in your client-side code, and server-side code or security rules.

Firestore rules for creating a user

I am new to firebase and trying to use firebase authentication, along with firestore database. It looks like all the security lies in rules we set, however I want to know the following:
Is it possible to apply rules based on user authentication without using firebase authentication system ?
How can I make sure that the users are only created through my application ? Would anyone with my firebase credentials (Which are easily exposed in browser) be able to add users to the database ? I understand that there is no domain based locking on firestore, but is user creation atleast domain based ?
Thanks!
Firebase Authentication is the only way to populate the request.auth variable in security rules. So if you want to secure based on a user, you'll need to create that user in Firebase Authentication.
You can however:
Use anonymous authentication to generate a UID for users, without requiring them to enter credentials.
If you have an existing sign-in system, you can hook that up to Firebase Authentication as a custom provider. This would then make your user details available in request.auth in the security rules.
To lock access to your Firestore database down to users from a specific domain, you'd use something like this in your security rules:
request.auth.token.email_verified &&
request.auth.token.email.matches(".*#google.com")
So this only allows access once a user has verified the email address in their profile, and if that email address is from he given domain.

Firebase Auth, only activate account created after someone accept it

I currently have an website that uses firebase auth as my authentication. My problem is that I don't want to open registration to everyone, only a selected few people that are supposed to use the website. I read about .htaccess and .htpasswd but since I'm hosting on firebase hosting I don't think it's possible.
My question is how can I secure the account creation? I don't want to create the accounts manually at firebase console but have the users create it on a page. Is it possible to have the account work only after someone "accept" it at the firebase console or add an extra step after creation, can I somehow protect the registration page if using firebase hosting?
There is no way to prevent any user from creating an account after you enable Firebase Authentication. But the fact that they can create an account, does not necessarily mean that they can then use your application.
The typical approach for your use-case is to store a list of approved users somewhere. Since you're using Firebase Authentication, this would take the form of a list of UIDs.
So to be authorized to use your application a user needs to be authenticated, and approved. Firebase Authentication takes care of them being authenticated, and your back-end functionality should take care of checking their approval status.
For example, if you're using Cloud Firestore as your database, you'd store the approved user UIDs in a collection:
approvedUsers <collection>
UID1 <document>
UID2 <document>
And then you can check in the server-side security rules of your database that the user is authorized (authenticated and approved) before allowing them to (for example) read any data.
exists(/databases/$(database)/documents/$(document.reference))
service cloud.firestore {
match /databases/{database}/documents {
match /myCollection/{document} {
function isApproved() {
return exists(/databases/$(database)/documents/approvedUsers/$(request.auth.uid))
}
allow read, write: if isApproved();
}
}
}

determine if user in auth has firebase admin role

CONTEXT:
In firebase settings, there's a permissions tab. This shows the users/emails that are associated with accounts that have admin access to the firebase project and console.
I could have sworn I once saw a document describing a method or some way of checking if a user account in firebase auth is also an administrator of the firebase project.
I seriously can't tell if it was in a dream (yes I dream code) or if I actually saw it. I often work late nights and fall asleep in front of my computer.
Question: Is there any way to tell if a user is also an administrator of the firebase app?
IE the user email matches an email that’s listed in the IAM/access management section of firebase as an 'owner' role?
Im currently writing an admin panel for my app, so such a feature would be very useful.
If such a thing does not exist, can anyone suggest an alternative way to manage and authorise users that are capable of logging into the admin dashboard to have control over the app? I already understand custom claims so I will use them if no better solution is suggested.
Well, using only the FirebaseAuth through your app, I don't think you can (as far as my knowledge goes). But you can easily implement the Admin SDK to manage your Custom Claims. Basically, you can use the Admin SDK and find out which "role" you want to access.
Referencing Firebase
Custom claims can contain sensitive data, therefore they should only
be set from a privileged server environment by the Firebase Admin SDK.
and
Custom claims can only be retrieved through the user's ID token.
Access to these claims may be necessary to modify the client UI based
on the user's role or access level. However, backend access should
always be enforced through the ID token after validating it and
parsing its claims. Custom claims should not be sent directly to the
backend, as they can't be trusted outside of the token.
Once the latest claims have propagated to a user's ID token, you can
get them by retrieving the ID token.
Therefore, you'll only need the FirebaseAuth implemented on your app's (client), but will need an extra implementation using a server.
Please see the Firebase use cases, they'll probably fit your needs, and you can pick the one that is "easier" for you.
It turns out it can't do what I wanted in the first place because it's only available on certain triggers.
Here it is: context.authType
https://firebase.google.com/docs/reference/functions/functions.EventContext#.authType
The level of permissions for a user. Valid values are:
ADMIN Developer user or user authenticated via a service account. USER
Known user. UNAUTHENTICATED Unauthenticated action null For event
types that do not provide user information (all except Realtime
Database).
Although it would be great if we could get this information on callable functions and firebase triggers because it would help further secure hosted backend admin apps for customer service or developers, who have high-level access to admin functions. This variable seems to not be available on callable functions but is available on newUser trigger - which is strange, because how can user signup ever be authenticated anyway?

Possibility to manage all existing users with firebase simple login

I am using firebase simple-login in my angularjs-app.
Is there any possibility to manage all existing user accounts (not with forge console)?
An admin-user should be enabled to edit and delete these accounts.
When you allow (for example) Twitter users to log in to you Firebase application, all Twitter users can log in to your Firebase application. You can't directly control specific user accounts, unless you implement your own custom authentication.
What you do have control is over what those user accounts have (read and write) access to. You do this through Firebase's security rules. If you'd remove an accounts read/write access from all your data, you've essentially locked them out of your Firebase.
You can programmatically set the security rules through the REST API. See updating security rules through rest api.

Resources