Set isEmailVerified of already verified firebase Users to false - firebase

Every year i want my Firebase users to verify their account-email again, to check that their Email address are still in use.
To test this i sent a new verification email to my (already verified) account. The mail was sent, but this did not set my .isEmailVerified to false, also after reloading the currentUser and the app.
Does anyone know if it´s possible to set the .isEmailVerified to false, once it is true at all, and if so how to do it?

Sending a verification email does not set the emailVerified property to false. That is the expected and intended behavior.
If you want to set the emailVerified property of a user to false, you can do so with the Firebase Admin SDK. For example, in Node.js it would be:
admin.auth().updateUser(uid, {
emailVerified: false
})
For more examples (including in other languages) see the Firebase documentation on updating a user profile.
Note that the Admin SDK has full administrative access to your Firebase project, so should only be run from a trusted environment, such as your development machine, a server you control, or Cloud Functions for Firebase. In no instance should you try to put this functionality in the app you give to your uses, as doing so will give them administrative access to your Firebase project.

Related

Firebase Auth - Disable a user and prevent him interacting with the backend

If a user of my app performs some unwanted action, his account may be disabled by a moderator. However, even if disabled, he will be able to use the app if he is already logged in. How can I prevent this?
The code I use to disable a user is within a Cloud Functions and use the following:
admin.auth().updateUser(uid, {
disabled: true
});
Disabling a user's account prevents them from signing in to the app in the future, and prevents their ID token from being refreshed. But their current ID token is still valid for up to an hour.
To detect the disabling of the user account, you can add their ID token to a blocklist and check against that list. You'd typically do that in your security rules, in your server-side code, and (for good measure) in the client. For more on this, see the Firebase documentation on detecting ID token revocation.

Firebase Auth – State Update on emailVerified

I have ignored the email/password sign up process and the necessary email verification for a long time and only used the very basic functionality to get started and build on top of that. But now I reached the point where I cannot avoid to use a more production-grade email/password sign up process. Currently I am using these Firebase services: Authentication (email/password only), Firestore and Cloud Functions with a react-native application.
When a user signed up successfully (signed in but without an verified email!) the react native application won't offer functionality until the user has verified his/her email. Right after the sign up the client will send an email with an verification link (through the default firebase server), the user can verify his/her email by clicking the link.
The issue: How to react suitable to a change of emailVerified or any other event which fires if the email got verified?
I have now searched the whole day for a working solution. These are my approaches:
Use your own website to which all verification links are linked (tried this but did not work at my first attempt)
use actionCodeSettings in the email verification link to redirect the user and let the client reload its components
Use Cloud Messaging and inform the client about changes to the email verification status
call a Cloud Function (from an external server) which updates a tmp document in Firestore to which the client subscribed
reload()/loop
I am thankful for all comments, helpful links etc.!
There is a method in the Firebase SDK: isEmailVerified() which tells if the user has verified the email or not.
For react native, I found straightforward documentation: Email Verified. On the launch of the app, you can check if the user has verified the email or not and then make changes accordingly!
Happy Coding!

Firebase Dashboard set email verified

I created a user via the console and inside my client (iOS App) I require the user to have their email verified before they can use it.
However the test user does not have a valid email (it does not exist).
The email is testing#project-name.com.
Is there any way I can set the account as "verified email"? I don't find anything in the console, is it possible to set this status on a user (maybe in a onCreate auth trigger?)?
Thank you
There is no option in the Firebase Console to set the emailVerified state of a user. So you'll have to do it in code.
The easiest way to do this is through the Firebase Admin SDK, which is available for Node.js, Java, Python and Go. In Node.js it's as simple as:
admin.auth().updateUser(uid, { emailVerified: true })
You can find the user's UID in the Firebase console.
adding for laravel-firebase SDK:
app('firebase.auth')->updateUser($uid, [ 'emailVerified' => true ]);

Keeping emails synchronized between Firebase auth and database

I am using Firebase Web for a SaaS solution. My purpose is to have access to users' email at any time, either for sending notifications or triggering alerts from the backend.
For security reasons, Firebase auth does not allow to list users' email or to fetch emails based on user IDs. As a consequence, I keep a copy of the email into a specific collection in the Firebase database when a user account is created. The copy is made by a Cloud function that is triggered on user creation (following guidelines: https://firebase.google.com/docs/auth/extend-with-functions).
Thanks to the copy available in the Firebase database, I can access users' email. However, my issue is when a user changes his email.
Firebase auth provides the updateEmail function that returns a promise. I use this last to update the email in Firebase auth. Then, when the promise resolves I update the user email in the Firebase database. However, this has a major drawback: all the logic is performed on the client side and since both operations are not performed in a transaction if the client refreshes or closes his browser (or assume it crashes), then it is possible that Firebase auth is updated but not the Firebase database, thus leading to an inconsistent state.
I looked at the documentation, expecting the possibility to trigger a Cloud function when user auth information is updated. Unfortunately, I cannot find such a feature.
Another solution I thought about is to update the database from the Web client. Then, this last triggers a Cloud function that updates Firebase auth with the admin SDK. This last solution works but bypasses the check performed by updateEmail that ensures the new email is not used by another account. Also, the account hijacking protection performed by updateEmail is evicted, which is really bad from a security point of view.
Any idea to solve this problem properly is welcome.
Here are a couple of options:
When calling updateEmail, update the email in your database first before calling updateEmail. THowever, if an error occurs, you need to catch it and undo that change in your db.
When a user wants to updateEmail, send their id token and new email to your server or firebase function http endpoint. There you verify the ID token with the admin SDK, then use the client SDK require('firebase'), using the uid from the ID token, admin.auth().createCustomToken(uid), then using client SDK, firebase.auth().signInWithCustomToken(customToken). You can then call user.updateEmail(newEmail) on the backend and save the email.
Always save the uid only and just use Admin SDK admin.auth().getUser(uid) to look up the user and get their email. This guarantees you get the user's latest email as you will not be able to catch the email revocation if the user chooses to do so.
No need to save anything. Use the CLI SDK to download all your users and their emails. Check https://firebase.google.com/docs/cli/auth#authexport
This is also better as you will always be able to get the latest email per user even if they revoke the email change.

Login with Email/Password without enabling it

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()"

Resources