Firebase Authentication Admin Login Only - firebase

I'm building two Flutter apps that will use the same Firebase project.
The first app is public and used by users to create accounts, login and use the application within the allowed access rules.
The second is for admins to approve user posts.
You have to login to use both apps. With the first anyone can create an account and login. Admins can also login with the same admin account. But with the second only admin users should be able to login. I'm enforcing security via access rules. But I need the second admin app to reject non-admin users from login in in the first place. So I can't simply create a collection and put the admin user UIDs in it.
How do I differentiate regular users from admin users, and most importantly use that differentiation to disallow non-admin users from login in into the admin app?
Currently for login I'm simply using
FirebaseAuth.instance
.signInWithEmailAndPassword(email: email, password: password);
I read about something called user claims, but there doesn't seem to be a way to modify this in the dashboard nor is there a way to specify some kind of condition via the code above.
I hope this makes enough sense.
Thank you all

You cannot prevent anyone from logging in to your application. The best you can do is check if the user is an admin. If yes, proceed else force logout them. You can use Firebase Custom Claims to add admin users or you can even store their UIDs in Firestore or Realtime Database.
UserCredential userCredential = await FirebaseAuth.instance.signInWithEmailAndPassword(
email: "barry.allen#example.com",
password: "SuperSecretPassword!"
);
// Check for claims here
if (admin) {
//...
} else {
await FirebaseAuth.instance.signOut();
// or just show alert that user is not an admin
}
You can use the getIdTokenResult method to get user's custom claims. This answer explains how to verify custom claims in Flutter.

Related

Firebase cookies without user login [duplicate]

I use Flutter and Firebase, just ask myself how to allow users to add items to cart when they're not logged in yet and keep the cart when they logging in, anyone have an idea for this ?
On Firebase you'd typically start the user off with an anonymous authentication account. With that sort of account, Firebase generates a user ID (UID) for the user, without them having to enter any credentials. You then associate the cart/items with the UID, and then when you/they are ready to identify themselves, you can sign them in with another provider, and link that to the anonymous account.
I've provided links to the documentation for Android developers above, but the same functionality is available in the FlutterFire libraries too. For example, anonymous sign-in on Flutter is as simple as:
UserCredential userCredential = await FirebaseAuth.instance.signInAnonymously();
you can store this data in a separate database SQL lite as an example

Add to cart when the user is not logged in

I use Flutter and Firebase, just ask myself how to allow users to add items to cart when they're not logged in yet and keep the cart when they logging in, anyone have an idea for this ?
On Firebase you'd typically start the user off with an anonymous authentication account. With that sort of account, Firebase generates a user ID (UID) for the user, without them having to enter any credentials. You then associate the cart/items with the UID, and then when you/they are ready to identify themselves, you can sign them in with another provider, and link that to the anonymous account.
I've provided links to the documentation for Android developers above, but the same functionality is available in the FlutterFire libraries too. For example, anonymous sign-in on Flutter is as simple as:
UserCredential userCredential = await FirebaseAuth.instance.signInAnonymously();
you can store this data in a separate database SQL lite as an example

How do I change user's sign in method without changing UID in Firebase Auth?

I want to provide a way that users can change their sign in method in my App using Firebase Auth.
For example, if previously a user signed up using Email and Password, then he/she wants to switch to Facebook or Google Sign in method. Then how do I do this without changing the user's UID ?
Probably something like:
firebase.auth()
.signInWithEmailAndPassword('you#domain.com', 'password')
.then((userCredential) {
userCredential.user.updateSignInMethod(method: facebook)
.then((userData) => loginWithFacebookProcedure());
})
Is it possible? If yes, how to do that ?
Thanks
There is no direct ability to "switch" authentication providers with Firebase Authentication. Once an account signs up with a provider (such as email/password), that option will always be available to the user of that account.
What you can do instead is link additional providers to an existing account, which will allow the user to authenticate using any of the providers linked to that account. Until you unlink them.
So, if you really want to "switch", you will actually have to link to another provider, then unlink the old provider. But that seems like a waste of effort when you can simply retain all of the linked providers for the user to choose from.

Prevent user account creation with sign in by email in firestore

I have setup a passwordless login using firebase sign in with email link. Everything is working as expected, however when the user receives the email and clicks the link to login they are automatically created as a registered user.
https://firebase.google.com/docs/auth/web/email-link-auth
After a user signs in for the first time, a new user account is
created and linked to the credentials...
This means anyone who makes a request in the login screen will get an email and get access to the site.
I am not sure if there is any configuration or setup that i need to complete in order to require that the user requesting the signup link are only checked against the users that are registered.
Something like
firebase.auth().sendLoginLinkToEmail(email,{url:...,handleCodeInApp:true}).then(() =>{
....
}, error =>{
// return if not an authenticated user
})
And if the email is not registered then it returns an error.
The idea is to have an administrator that creates users and then those created users just login with an email link ( no password )
Is this possible? To prevent firebase from creating an account with.signInWithEmailLink() ?
Passwordless email sign in allows the user to prove they have access to a certain mail box. It does inherently do nothing more than that. Once the user clicks the link, they are authenticated. Beyond enabling/disabling the entire sign-in provider, you cannot control who can sign-in/authenticate.
After that it is up to your application to determine what this user is allowed to do. This is a separate step, typically called authorization.
Firebase Authentication takes (as its name implies) care of authentication only. You will have to handle authorization elsewhere, depending on what services you provide the users access to.
What makes an email "registered" in your app? I.e. where does the admin create those users? For example, if you store the users in the Cloud Firestore in a collection allowed_users, with documents like this:
allowed_users: // collection
"arkade#domain,com": { ... } // document
"puf#domain,com": { ... } // document
Now you can limit that only allowed users can access other data with Firestore's server-side security rules. Say you have a collection of posts, you can allow only these users to read posts with:
service cloud.firestore {
match /databases/{database}/documents {
match /posts/{post} {
// Make sure a 'allowed_users' document exists for the requesting user before
// allowing any reads from the 'posts' collection
allow read: if exists(/databases/$(database)/documents/allowed_users/$(request.auth.email))
}
}
The syntax is a bit long, but your can see that is only allows the reading of a post if the current user's email address (request.auth.email) exists as a document in allowed_users.
In rules version 2 of the Firestore rules, you access the current user's email address a little differently. You can do it via request.auth.token.email. The example below also shows how you can get a boolean property in the current user's document, if you identify that user by email:
allow write: if get(/databases/$(database)/documents/users/$(request.auth.token.email)).data.admin == true;

Firebase Auth: link two pre-existing accounts

I have read this:
"Account linking can only be performed at the point at which a new
account is created. It is not possible, in other words, to link two
pre-existing accounts."
Is it still true?
I'd like this workflow :
User logs in the app and take his Anonymous uid;
Then User does the login (user previously registered) and obviously has his uid;
Now when the user does the logOut I'd like to give him his previous Anonymous uid, not a new one.
Is this possible?
It's not possible if you want to link your anonymous user to an existing account. It will give you an error: 'auth/credential-already-in-use'. You have to manually merge your two accounts.
It is possible to convert an anonymous account to a permanent account. You can do that by logging in the user into the new account, getting it's credential and then use it to link with the anonymous account, as mentioned on the documentation:
auth.currentUser.link(credential).then(function(user) {
console.log("Anonymous account successfully upgraded", user);
}, function(error) {
console.log("Error upgrading anonymous account", error);
});
But when the user logs out, he can't get that previous uid back. Because anonymous accounts are temporary, as mentioned on the documentation:
You can use Firebase Authentication to create and use temporary
anonymous accounts to authenticate with Firebase
And I think it makes sense. Because if a user was anonymous, it means he has no identification. So there's no way you can tell who was using that uid before.

Resources