Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

firebase - get notified when user confirmed an email sent with sendEmailVerification

Is there a way for the client (web) to know/get notified when the user confirmed an email sent with sendEmailVerification ?

This is important for a single page application to wait and then change state to logged in once the user confirmed and authentication completed.

like image 310
kofifus Avatar asked Jun 19 '16 22:06

kofifus


2 Answers

It seems FireBase does not have a direct way for the client to get notified when an email was verified and such an interface is "currently not being considered".

I came up with the following solution:

function registerUserAndWaitEmailVerification(email, password, showWaitUI) {
    return new Promise(function(resolve, reject) {
        let interval=null;

        firebase.auth().createUserWithEmailAndPassword(email, password).then(
            user => {
                user.sendEmailVerification().then(
                    () => {
                        if (showWaitUI) showWaitUI();
                        interval = setInterval(() => {
                            user.reload().then(
                                () => {
                                    if (interval && user.emailVerified) {
                                        clearInterval(interval);
                                        interval=null;
                                        resolve(user);
                                    }
                                }, error => {
                                    if (interval) {
                                        clearInterval(interval);
                                        interval=null;
                                        console.log('registerUserAndWaitEmailVerification: reload failed ! '+error.message+' ('+error.code+')');
                                        reject(error);
                                    }
                                }
                            );
                        }, 1000);
                    }, error => {
                        console.log('registerUserAndWaitEmailVerification: sendEmailVerification failed ! '+error.message+' ('+error.code+')');
                        reject(error);
                    });
            }, error => {
                console.log('registerUserAndWaitEmailVerification: createUserWithEmailAndPassword failed ! '+error.message+' ('+error.code+')');
                reject(error);
            }
        );
    });
}

the code will:

  • call createUserWithEmailAndPassword
  • call sendEmailVerification
  • call showWaitUI (if given), here the client should prob show a modal with instructions ('Please check your email for the confirmation link.') and an hourglass
  • start an interval loop calling currentUser.reload() every second, and stopping either when auth successful with currentUser.emailVerified==true or an error occured
  • resolve with auth().user if auth was successful or reject with error

with this you can do:

function showRegisterUI() {
   // show a modal with instructions ('Please check your email for the confirmation link.') and an hourglass    
}

registerUserAndWaitEmailVerification(email, password, showRegisterUI).then(
     user => {
        // uid in user.uid
     , error => {
         // alert user with error.message, go back to login screen
     }
   );
}

Hope this helps :)

like image 113
kofifus Avatar answered Sep 27 '22 18:09

kofifus


Do keep in mind that calling reload() causes traffic between the client and Firebase servers - calling it every second might be far more traffic than you want to create. This might be only an issue if you have a lot of sign-ups, though.

However, I am not aware of a solution (at least in an app) other than calling reload(), unless you sign out the user and ask them to sign back in after they have clicked on the email link.

The solution I used was to instruct the user, after registration, to click the link in the email, and after that click continue. When they click continue, do a reload(), and in the onComplete() callback of the reload, check if the email verification has been received. If not, they get a message and stay on the same screen. This way I have reload() related traffic only when the user performs an action.

like image 35
Venu G. Avatar answered Sep 27 '22 20:09

Venu G.