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.
Related
I am making an admin tool page to allow admins to change users email for when they change or set their account to deactivate so they can not access the site anymore. Everything I have looked at seems to be using 'CurrentUser' but this will not work due to the fact they will be logged in as themselves which is marked as Admin level so they have access to the tool. So is there any way to change a users email for authentication without logging in as them?
If the Firebase Authentication client-side SDKs had an API that allowed you to change the email address of anyone but yourself that'd be a major security risk.
This is the reason an API to update any user by their UID only exists in the Admin SDK, which can only be run on a trusted environment as it requires full administrative access to your project.
If you want to expose this functionality to specific users of your app, you'll have to wrap the relevant call of the Admin SDK into a custom endpoint that you then call from the app. Just make sure to check that the user is authorized, before changing some other user's account.
I wanted to create website where I have separate Sign In and Sign Up form. I also want to have Google authentication with Firebase.
I've implemented it like this both on sign in and sign up page:
await FIREBASE_AUTH.signInWithPopup(googleAuthProvider);
But this code will always create new user.
What I would like to do is to block creating new user on sign in page, only log them in if user already exists (e.g. as I require terms of use consent on sign up page, but I don't want to require it on sign up page - it would be quite weird)
There is no way in Firebase Authentication to prevent users from signing up, while still allowing them to sign in if they're already created. The reason for this is that Firebase Authentication merely focuses on allowing users to authenticate themselves, so to prove who they are by providing credentials. What they can then do in your app is known as authorization, and is up to you to implement in your front-end application code, back-end application code, and server-side security rules.
For example, if you use one of Firebase's databases (Cloud Firestore or Realtime Database), you'll typically maintain a list of approved user's in that list (either their email or their UID). Then before granting the user access to specific screens in your app or data in your database, you check if the users exists in that list. If not, you don't grant access to the screen or data.
I don't see an issue here, when a user uses google auth when they already have an account it will create a new account with their in some cases new data he might have changed in his google account.
In case your users hold other data in your database I'm pretty sure there's a google auth API for that issue.
An user login using Google account as the provider for authentication like the image above. I want to make when the user performs log out, then the provider should change from Google to be anonymous. so I want to make, when user logout, they will be anonymous but with the same userID Bdf2LPraRhbnWhP24eiSN3vTQ5G3
Can I do that?
I need to make it anonymous, because I want that user to still see some contents in my app even when they logout. They need to be in the logged-in state to pass the security rules.
I want to make when the user performs log out, then the provider should change from google to be anonymous.
There is no way you can automatically do that. When the user logs out, the created account still remains and cannot be converted in any way.
Firebase lets you create those anonymous accounts so you can authenticate with Firebase. These are only temporary accounts that can be used to allow users who haven't yet signed up to use your app. It's true that you can convert an anonymous account to a permanent account with Google, but the vice versa is not available.
It's also true that you can log a user out from Google, as well as from Firebase, and delete the Firebase account entirely, but if you try to create another anonymous account, a new UID will be generated. Unfortunately, there is no way to reclaim the old token for the user.
because I want that user to still see some contents in my app even when they logout.
If you want the user to see some content even if they log out, simply display that content also for non-authenticated users. If you want to restrict that only for a particular user, then the user should be authenticated.
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?
My current registration process looks like this:
App sends a registration request via my REST Api to my backend with information like username, password, email etc.
My backend checks if the username is available. If it is, it creates a new user with the admin api. If this is successful as well it saves the username to the realtime db.
When I want to log in with loginWithEmailAndPassword it says that I can't because PasswordLogin is disabled.
Since I don't want anybody to just register with registerWithEmailAndPassword I want to keep it disabled.
My question now is, how can I log a user in without enabling Email/Password?
Or would there even be a possibility to exploit the system when I enable Email/Password?
EDIT: What I'm not sure about is if registrations with registerWithEmailAndPassword are guaranteed to be from my app?
firebaser here
There is no way to sign the user in to a disabled provider. I'm actually quite surprised that you can register them.
There is no way to prevent users from registering after you enable the provider.
But it's quite easy to only allow users that your administrative back-end created access to certain data. Just make the admin script write the UID of users it creates to a whitelist:
/whitelist
uid1: true
uid2: true
And then in your security rules only allow access on whitelisted users:
".read": "root.child('whitelist').child(auth.uid).exists()"