Search code examples
firebasereact-nativefirebase-authentication

How do I listen to email verification event with firebase authentication and react native?


EDIT - this question is still unanswered. There was an idea to listen to onIdTokenChanged, however the token is refreshed once every hour, which is not practical solution for me. I posted follow up question here if people can give me a hand that would be grant, because I am sitting on this problem since one week.

I am writing a simple react native app, and I want to show my main page only after user has verified their email. As far as I understand, there is no listener which I can use to listen to event where the user has been verified their email. I am using firebase.auth().onAuthStateChanged((user) => {....}) but the listener onAuthStateChanged has been called after user is logged in or registered in, not after a user has verified their email. Few places suggested to use firebase.auth().user.reload() so that it will reload the current user and it will pick up the verification status from the database. However, I dont think it is a solution because I dont know when should I reload the current user, i.e. I dont know when the verification link has been clicked. So possible solution to this problem would be:

  1. Send a confirmation 6 digit code to the user, and wait for the user to type it in the app; after the user types it, if the code is the same, I refresh the user. However I dont know how to send custom verification emails with firebase. I checked the documentation, but it is not helpful for me. If someone can point me to example written in react native, or write a small working example with custom email which I can send to the user (again in react native) that would be grant! EDIT - this doesn't seem like possible solution, since Firebase doesn't let you customize the emails
  2. Is it possible solution for me to override onAuthStateChanged listener? S.t. it will listen for changes if the user's email has been verified or not? If that's a good idea can someone point me to the current onAuthStateChanged implementation in react-native, so I can see it as an "inspiration" when overriding? Or if someone has done something similar before, can you show me an example?
  3. I've read several suggestions to use a deep link and to intersept the event when the link has been clicked, but I am not sure how to do this, or even if this is a proper solution to the problem.
  4. Some people suggested to use firebase.auth().user.reload() when the app has been closed and reopened again. This comes from the assumption that when a user has been sent the link, in order for them to click on the link, they need to close the app, and reopen it again. I think this is pretty strong assumption, considering the fact, that they might verify their email via laptop and never close the app, so I dont think this is a good solution either.

Apparently this seems like a well known problem, yet there are not many good solutions. I think best possible solution would be to send 6 digit verification code to the user and after that code has been confirmed, I would reload the current user, pick up the emailVerified field, it will be set to true and then I will show the main screen. However, can someone help me with how do I send custom email in react native and firebase?

If anyone has any other suggestions, please let me know!


Solution

  • So, on my project I made a combination of sendEmailVerification() and reload().

    Try it:

    await firebase
            .auth()
            .currentUser.sendEmailVerification(actionCodeSettings)
            .then(() => {
              //useState used on my loading (user can cancel this loading and exit               this task
              setTextContent('Waiting for verification. Check your email!\nYou can close this verification and came back later');
              const unsubscribeOnUserChanged = firebase
                .auth()
                .onUserChanged(response => {
                   const unsubscribeSetInterval = setInterval(() => {//this works as a next in for-like
                      firebase.auth().currentUser.reload();
                   }, 30000);
                  if (response.emailVerified) {
                     clearInterval(unsubscribeSetInterval); //stop setInterval
                    setLoading(false); //close loading describes above
                    navigation.goBack(); //return to parent (in my case to profile)
                    return unsubscribeOnUserChanged(); //unsubscribe onUserChanged
                  } 
                });
            })
            .catch(error => {
              setLoading(false); 
              setError(true);
              errorHandle(error);
            });