KhoPhi
KhoPhi

Reputation: 9517

user.emailVerified doesn't change after clicking email verification link firebase

After learning sending email verification is possible in latest firebase, although the docs are missing that, I wanted to test it for myself.

Using the snippet below:

  Auth.$onAuthStateChanged(function(firebaseUser) {
    if (firebaseUser) {
      console.log(firebaseUser);
      if (firebaseUser.emailVerified) {
        // console.log(firebaseUser.emailVerified); 
        toastr.success('Email verified');
      } else {
        toastr.info('Do verify email');
      }
    }
  })

The console.log(firebaseUser.emailVerified) returns false, always, although a send verification was initiated, email received, and clicked on.

Right after login with email, I check to see if user is verified, if not, email should be sent:

Auth.$signInWithEmailAndPassword(email, password)
  .then(function(firebaseUser) {
    if (!firebaseUser.emailVerified) {
      firebaseUser.sendEmailVerification();
      console.log('Email verification sent');
    }
    $state.go('home');
  })

Under my https://console.firebase.google.com/project/my-app-name/authentication/emails, everything is by default, with a verify link as:

Follow this link to verify your email address. https://my-app-name.firebaseapp.com/__/auth/handler?mode=<action>&oobCode=<code>

The email I use to sign up receives the verify email message, yet, clicking the link does nothing to change the user.emailVerified to true.

Are the steps outline here all there is, or there's yet another step not found in the docs?

Upvotes: 17

Views: 16803

Answers (6)

Frank van Puffelen
Frank van Puffelen

Reputation: 599166

I just took the same steps:

auth.currentUser.emailVerified

false

auth.currentUser.sendEmailVerification()
  1. wait for the email
  2. click the link in the email
  3. sign out
  4. sign in again

And then

auth.currentUser.emailVerified

true

Note step 3 and 4: I needed to sign in again, before the new value of emailVerified was visible in my app. Instead of signing out and back in again, you can also reload the user profile, which forces it to refresh the data from the server.

This answer also seems relevant, but I only spotted it after writing the above: Firebase confirmation email not being sent

Upvotes: 9

Sivart
Sivart

Reputation: 191

As mentioned by Tope in a comment, you need to do a firebaseUser.reload() in order for the change to the firebaseUser's authentication status to be updated.

Upvotes: 17

John Doe
John Doe

Reputation: 1172

In my case, it seems currentUser.emailVerified switches to true, but not always. Not sure why. It switches to true with Chrome in most cases, but not always. It does not with Firefox.

Applying the reload() method seemed to fix the issue.

I have the following in a saga, after loading the URL that contains the oobCode :

const currentUser = firebase.auth().currentUser;
if(currentUser){
  currentUser.reload();
}

Upvotes: 2

Bhupiister singh
Bhupiister singh

Reputation: 119

We just need to reload the user's state after the user has clicked the user confirmation link. Especially if someone is using the firebase UI sign-in flow, one may have noticed that user Sign-up and Sign-in executes simultaneously. For such a case, the user needs to be reauthenticated by Sign-Out Sign-In, which is not a pleasant experience. However, Firebase provides an option to reload the user. Putting it inside the async-await function will make sure that the state is refreshed before executing the next commands.

async function confirmEmailVerified(){
    await auth.currentUser.reload();
    var isEmailVerified = auth.currentUser.emailVerified;
    if (isEmailVerified) {
        console.log("Email verified");

    }else{
        console.log("Email not verified, please verify or click on resend to get the verification email!");
    } 
}

Upvotes: 0

Leo Farmer
Leo Farmer

Reputation: 7900

We have just gone through the same issue and found the fix was to both reload user using user.reload() function and to also change the observer from onAuthStateChanged to onIdTokenChanged.

This is because you are updating the firebase token with the new emailVerifed property and onIdTokenChanged is listening for changes to the Id token and updates the user object with the correct values.

Code snippets:

export function* register_user(action) {
  try {
    //Call api which registers user and sets email verified to true
    let register_result = yield call(Register_API.create_registration, action.data)

    if (register_result && register_result.status >= 200 && register_result.status < 300) {
      let user = firebase.auth().currentUser
      //Force user to reload so we can trigger the onIdTokenChanged listener
      return user.reload()
    }

  } catch (e) {
    console.error(e)
  }
}


firebase.auth().onIdTokenChanged(function (user) {
      if (user && user.uid) {
        if (user.emailVerified) {
         //Stuff you want to do
        }
      }
    })

Upvotes: 2

KhoPhi
KhoPhi

Reputation: 9517

In a very minimalistic way, this is what I ended up with:

angular.module('theApp')

.controller('emailVerifyController', ['$scope', '$stateParams', 'currentAuth', 'DatabaseRef',
  function($scope, $stateParams, currentAuth, DatabaseRef) {
    // where currentAuth and DatabaseRef is what they sound like
    $scope.doVerify = function() {
      firebase.auth()
        .applyActionCode($stateParams.oobCode)
        .then(function(data) {

          // change emailVerified for logged in User
          // you can update a DatabaseRef endpoint in here
          // whatever!

          toastr.success('Verification happened', 'Success!');
        })
        .catch(function(error) {
          $scope.error = error.message;
          toastr.error(error.message, error.reason, { timeOut: 0 });
        })
    };
  }
])

Then in template, something like this:

<a ng-click="doVerify()" class="button large">Verify my Account</a>

Although the applyActionCode is not yet wrapped for AngularFire, you could still drop down to vanilla Javascript of the SDK in your AngularJS stuff, besides, why not!

I share more details for Email Verification in Firebase:
https://blog.khophi.co/email-verification-firebase-3-0-sdk/

Upvotes: 3

Related Questions