Why Firebase-Email-Verification doesn't work? - javascript

$("#btn1").on('click', function(e) {
e.preventDefault(); // <== disable form submit
const email = signupForm['signup-email'].value;
const password = signupForm['signup-password'].value;
// sign up the user & add firestore data
const auth = firebase.auth();
const promise = auth.createUserWithEmailAndPassword(email, password);
promise.then(user => {
user = firebase.auth().currentUser;
user.sendEmailVerification();
}).catch(error => console.log);
});
$("#btn2").on('click', function(e) {
e.preventDefault(); // <== disable form submit
var user = firebase.auth().currentUser;
if (user.emailVerified) {
// email is verified.
console.log("email is verified")
} else {
// email is not verified.
console.log("email is not verified")
}
});
I want that my Website sends an email to the user after the user enters his email and password.
In my Code, user.sendEmailVerification(); works fine and the user gets an email.
If the user verifies his email and clicks the btn2, the console should print "email is verified", but this doesn't happen. The console always prints "email is not verified". I tried also the firebase.auth().onAuthStateChanged method, but it's the same.
var user = firebase.auth().currentUser;
firebase.auth().onAuthStateChanged(user => {
if(user.emailVerified){
console.log('email is verified')
}else{
console.log('email not verified')
}
})

Verifying the email address happens out-of-band, typically in another tab of the same browser or in another application altogether. This means that your application code isn't immediately made aware of the update to the user's profile, but only once one of these things happens:
Their ID token is auto-refreshed, which happens every hour.
When the user logs out and logs in again.
When you force to refresh the ID token in your application code by calling reload on their user profile.
Once any of these happens, the user profile will contain the latest information from the server, including the user's email verification state.
Also see:
Angular firebase email verification false after verify
Android Firebase AuthStateListener Email Verified
Can I get updated emailVerified without logging out?
user.emailVerified doesn't change after clicking email verification link firebase

On the process of authentication, you are redirected to the auth server, and gets back to the page. The onAuthStageChange it's a observer to that redirection, you don't need to trigger an event, since when it's a realtime event.

Related

Verify if email is already in use from Firebase in HTML

I'm trying to verify an email on Google Firebase without adding credentials to the database.
For example, I want it to acknowledge if an email is typed in the database will say the email cannot be used because it is already in use or is incorrect format. Also, I want it to verify that the password is valid for firebases '6' character passwords. I do not want to add any credentials to the database, only verify that the needs are being met
signUp.addEventListener('click', (e) => {
//check if email and password valid first
//then display verification message
var email = document.getElementById('email').value;
var password = document.getElementById('password').value;
createUserWithEmailAndPassword(auth, email, password)
.then((userCredential) => {
// Signed in
// redirect to another page HERE!
const user = userCredential.user;
alert('Credentials are eligible! Complete your account!')
// ...
})
.catch((error) => {
const errorCode = error.code;
const errorMessage = error.message;
// ..
alert(errorMessage)
});
here is a sample GUI design, if I clicked verify the email and password would be accepted because these credentials are not into the database using the current code I have. However, I do not want them to be added to the database. I want the verify button to check if the email is already in use and the password meets the parameters then display an alert saying so
If you want to verify email if it already exists without saving data into database, you can use fetchSignInMethodsForEmail method. To display custom error messages you can use Try and catch block as suggested in this documentation.
For Example:
.catch((error) => {
if (error.code == "Firebase: auth error") {
alert("The email address is already in use");
}
To display detailed useful error messages use functions.https.HttpsError.
For more information have a look at these thread1 &thread2.

How to add email verification into my Vue firebase app? [duplicate]

I wish to create a user account in Firebase Auth using createUserWithEmailAndPassword() - without logging in the user. I wish for the user to verify the email address first. Signing in the user directly causes a lot of unwanted side effects.
The /signup page has the following code - I wish for the user to stay on the /signup page after registration to be able to see the registration message.
firebase.auth().createUserWithEmailAndPassword(data.email, data.password)
.then((user)=> {
//Send email verification link
user.sendEmailVerification()
//Show message - "Your account was created - please verify using link in email"
handleStatusMessage(AUTH_SUCCESS)
})
.catch((error)=>{...})
The app.js has the following login and redirect handler
//handle login and redirect
firebase.auth().onAuthStateChanged((user) => {
if (user) {
if(!user.emailVerified){
//Exit if email is not verified
console.log('auth.js exit')
//Line 7
}
store.dispatch(setInitialStore()).then(() => {
renderApp()
//Brings user to start page
if (history.location.pathname === '/login') {
history.push('/start')
}
})
} else {
renderApp()
//Brings user to /login or /verifyEmail page when logged out
if(!history.location.pathname.includes('/verifyEmail')){
history.push('/login')
}
}
My problems are:
The user gets redirected after successful signup unless I cancel execution on line 7
If I cancel execution on line 7, the user gets stuck when moving away from /signup
Logging out the user causes the onAuthStateChanged() to trigger twice - redirecting the user
How can I keep the user on the /signup page after successful account creation while still allowing the user to navigate to the /login /verifyEmail location? Preferably in logged out state.
What I ended up doing was adding checks for when the user was logged in and logged out during signup.
signupPage.js
firebase.auth().createUserWithEmailAndPassword(data.email, data.password)
.then((user)=> {
//Login is triggered --> line 4 in app.js
user.sendEmailVerification() //Send email verification
handleStatusMessage(AUTH_SUCCESS) //Show success message
firebase.auth().signOut() //Logout is triggered --> line 16 in app.js
})
.catch((error)=>{ ... }
app.js
//handle login and redirect
firebase.auth().onAuthStateChanged((user) => {
if (user) {
//** line 4 ** EXIT if logged in from /signup
if(!isEmailVerified && history.location.pathname.includes('/signup')){
return
}
store.dispatch(setInitialStore()).then(() => {
renderApp()
//Brings user to start page
if (history.location.pathname === '/login') {
history.push('/start')
}
})
} else {
//** line 16 ** EXIT if logged out from /signup
if(history.location.pathname.includes('/signup')){
return
}
renderApp()
//Brings user to /login or /verifyEmail page when logged out
if(!history.location.pathname.includes('/verifyEmail')){
history.push('/login')
}
}
I really wish there was a option for createUserWithEmailAndPassword() to be able to automatically send the email verification email and not logging in the user to avoid this kind of cat-and-mouse game code. :)
A separate method along the lines of createUserWithEmailAndPasswordEmailVerificationRequired() that automatically sends the email link and does not sign in the user would also work ;)
The Firebase Auth function createUserWithEmailAndPassword automatically signs in users upon successful account creation (which does not require email verification).
If you need to verify email addresses for new user sign-ups without automatic sign-in, then an alternative is Email Link Authentication.
You can use Firebase Authentication to sign in a user by sending them an email containing a link, which they can click to sign in. In the process, the user's email address is also verified.
There are numerous benefits to signing in by email:
Low friction sign-up and sign-in.
Lower risk of password reuse across applications, which can undermine security of even well-selected passwords.
The ability to authenticate a user while also verifying that the user is the legitimate owner of an email address.
A user only needs an accessible email account to sign in. No ownership of a phone number or social media account is required.
A user can sign in securely without the need to provide (or remember) a password, which can be cumbersome on a mobile device.
An existing user who previously signed in with an email identifier (password or federated) can be upgraded to sign in with just the email. For example, a user who has forgotten their password can still sign in without needing to reset their password.
After users successfully created accounts via email link authentication, you could provide the option to create a password and link to the existing account.

Getting Uncaught TypeError in Firebase Auth get current user email

I am trying to get the email of the currently signed in user in my Firebase app, but it keeps giving me an error.
This is my code for getting the current user email:
user_email = firebase.auth().currentUser.email
The error that I get is:
Error Image
It looks like firebase.auth().currentUser is null at the time when your firebase.auth().currentUser.email runs. This is quite common, as Firebase refreshes the user's authentication state when the page loads, and this requires it to make an asynchronous call to the server.
For this reason, you should not assume there is a user signed in. You should either put a check around your current code:
if (firebase.auth().currentUser) {
user_email = firebase.auth().currentUser.email
}
Or (and often better) you should use a so-called auth state listener, to have your code automatically respond to changes in the user's authentication state. From the Firebase documentation on getting the currently signed-in user, that'd be:
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// User is signed in, see docs for a list of available properties
// https://firebase.google.com/docs/reference/js/firebase.User
var uid = user.uid;
user_email = firebase.auth().currentUser.email;
// TODO: execute code that needs `user_email`
} else {
// User is signed out
// ...
}
});

Check if an email already exists in firestore auth on signup (Angular)

As a user signs up to our app, I want them to know whether the email they are trying to sign up with already exists, without having to submit the form (A.K.A on blur of the email field). As it stands, the user has to enter their details and click signup before it let's them know whether the email is taken or not.
The required behaviour can be observed with spotify signup where you enter the email, and as soon as you click away you see the following:
So far, I have written a cloud function (http) that is triggered on blur that calls the getUserByEmail function from firestore admin auth. The function is as follows:
export const checkUserEmail = https.onRequest((req, res) => {
corsHandler(req, res, async () => {
try {
const email = req.body.email;
await admin.auth().getUserByEmail(email);
res.send({status: 200});
return;
} catch(e) {
return Helpers._handleError(res, 400, e.message);
}
})
});
This does work as I can now check at this moment whether or not an email exists, however the problem is it takes anywhere between 3-10 seconds to validate (long enough for the user to get deeper into the signup process).
Is there a way to either:
Speed up the cloud function or
Validate whether a user has already authenticated with the email provided directly on the client side with firestore?
Thanks in advance
You can use a users collection, which you may be doing already. This can store user information and often proves to be really handle since the auth user can't be updated with fields it doesn't how out of the box.
You can store users' emails here and check the collection for the user's input compared to the email field of the users collection here.

Firebase Auth - createUserWithEmailAndPassword() - prevent login until email is verified

I wish to create a user account in Firebase Auth using createUserWithEmailAndPassword() - without logging in the user. I wish for the user to verify the email address first. Signing in the user directly causes a lot of unwanted side effects.
The /signup page has the following code - I wish for the user to stay on the /signup page after registration to be able to see the registration message.
firebase.auth().createUserWithEmailAndPassword(data.email, data.password)
.then((user)=> {
//Send email verification link
user.sendEmailVerification()
//Show message - "Your account was created - please verify using link in email"
handleStatusMessage(AUTH_SUCCESS)
})
.catch((error)=>{...})
The app.js has the following login and redirect handler
//handle login and redirect
firebase.auth().onAuthStateChanged((user) => {
if (user) {
if(!user.emailVerified){
//Exit if email is not verified
console.log('auth.js exit')
//Line 7
}
store.dispatch(setInitialStore()).then(() => {
renderApp()
//Brings user to start page
if (history.location.pathname === '/login') {
history.push('/start')
}
})
} else {
renderApp()
//Brings user to /login or /verifyEmail page when logged out
if(!history.location.pathname.includes('/verifyEmail')){
history.push('/login')
}
}
My problems are:
The user gets redirected after successful signup unless I cancel execution on line 7
If I cancel execution on line 7, the user gets stuck when moving away from /signup
Logging out the user causes the onAuthStateChanged() to trigger twice - redirecting the user
How can I keep the user on the /signup page after successful account creation while still allowing the user to navigate to the /login /verifyEmail location? Preferably in logged out state.
What I ended up doing was adding checks for when the user was logged in and logged out during signup.
signupPage.js
firebase.auth().createUserWithEmailAndPassword(data.email, data.password)
.then((user)=> {
//Login is triggered --> line 4 in app.js
user.sendEmailVerification() //Send email verification
handleStatusMessage(AUTH_SUCCESS) //Show success message
firebase.auth().signOut() //Logout is triggered --> line 16 in app.js
})
.catch((error)=>{ ... }
app.js
//handle login and redirect
firebase.auth().onAuthStateChanged((user) => {
if (user) {
//** line 4 ** EXIT if logged in from /signup
if(!isEmailVerified && history.location.pathname.includes('/signup')){
return
}
store.dispatch(setInitialStore()).then(() => {
renderApp()
//Brings user to start page
if (history.location.pathname === '/login') {
history.push('/start')
}
})
} else {
//** line 16 ** EXIT if logged out from /signup
if(history.location.pathname.includes('/signup')){
return
}
renderApp()
//Brings user to /login or /verifyEmail page when logged out
if(!history.location.pathname.includes('/verifyEmail')){
history.push('/login')
}
}
I really wish there was a option for createUserWithEmailAndPassword() to be able to automatically send the email verification email and not logging in the user to avoid this kind of cat-and-mouse game code. :)
A separate method along the lines of createUserWithEmailAndPasswordEmailVerificationRequired() that automatically sends the email link and does not sign in the user would also work ;)
The Firebase Auth function createUserWithEmailAndPassword automatically signs in users upon successful account creation (which does not require email verification).
If you need to verify email addresses for new user sign-ups without automatic sign-in, then an alternative is Email Link Authentication.
You can use Firebase Authentication to sign in a user by sending them an email containing a link, which they can click to sign in. In the process, the user's email address is also verified.
There are numerous benefits to signing in by email:
Low friction sign-up and sign-in.
Lower risk of password reuse across applications, which can undermine security of even well-selected passwords.
The ability to authenticate a user while also verifying that the user is the legitimate owner of an email address.
A user only needs an accessible email account to sign in. No ownership of a phone number or social media account is required.
A user can sign in securely without the need to provide (or remember) a password, which can be cumbersome on a mobile device.
An existing user who previously signed in with an email identifier (password or federated) can be upgraded to sign in with just the email. For example, a user who has forgotten their password can still sign in without needing to reset their password.
After users successfully created accounts via email link authentication, you could provide the option to create a password and link to the existing account.

Categories