0
votes

I'm developing an hybrid app using Ionic 3 and Firebase as authentication provider. The app consist in 2 pages. A login page and an home page. On the login page there's a button that log-in the user using email+password and on the home page another button logout the current user. Basically, the first time the app is loaded everything works fine. But after loggin-in then logging-out then logging-in again the function inside onAuthStateChange gets called twice, then three times, then five and so on following the Fibonacci's series. This is the login page code:

firebase.auth().onAuthStateChanged(function(user) {
      if (user) {
        console.log('User logged-in');
        if (user.emailVerified) {
          self.goToHome();
        } else {
          self.showAlert();
          firebase.auth().signOut();
        }
      }
    });
  }

and this is the logout code:

firebase.auth().onAuthStateChanged(function(user) {
      if (user == null) {
          console.log('User logged-out');
          navCtrl.push(WelcomePage);
        }
      });

chrome console shows this behavior:

(the error at the end of the image was my fault as I used the wrong password)

Chrome console showing the functions getting called following the Fibonacci series

The functions called by the buttons (but I'm 99% sure that the problem is onAuthStateChanged):

  doLogin() {
    console.log('Trying to log in...');
    var email = this.account.email;
    var password = this.account.password;
    if (this.validateEmail(email) && password.length >= 8) {
      loading.present();
      firebase.auth().signInWithEmailAndPassword(email, password)
      .then(function(data) {
        loading.dismiss();
       });
}

logout() {
    firebase.auth().signOut();
  }

The function goToHome to move the user to the homepage:

goToHome() {
    this.navCtrl.push(MainPage);
  }

Solution as pointed out by Ben in his comment:

1: moving all navController related functions from onAuthStateChanged 2: using setRoot instead of pop() and push()

goToHome() {
    this.navCtrl.setRoot(HomePage);
  }
logout() {
  firebase.auth().signOut();
  this.navCtrl.setRoot(WelcomePage);
}

3) To fix be able to auto-login the user if he/she didn't logout I check if firebase.auth().currentuser exist, but using a timeout because Firebase needs some time before functioning properly:

setTimeout(function(){
        var user = firebase.auth().currentUser;
        if (user != null) {
          self.goToHome();
        }
      }, 1500);
3
Please also mention your component route logic. what this do self.goToHome();?Hareesh

3 Answers

0
votes

You should send the user to the page after the firebase.auth().signInWithEmailAndPassword(email, password), not on the listener. Firebase listeners have a weird behaviour...

Try this:

doLogin() {
    console.log('Trying to log in...');
    var email = this.account.email;
    var password = this.account.password;
    if (this.validateEmail(email) && password.length >= 8) {
        loading.present();
        firebase.auth().signInWithEmailAndPassword(email, password).then(function(data) {
            loading.dismiss();
            var user = firebase.auth().currentUser;
            if (user) {
                console.log('User logged-in');
                if (user.emailVerified) {
                    self.goToHome();
                } else {
                    self.showAlert();
                    firebase.auth().signOut();
                }
            } else {
            // No user is signed in.
            }
        }, function(error) {
        //error handling
        });
    }
}
0
votes

I had a similar problem in my login. The function/listener firebase.auth().onAuthStateChanged( will trigger every time the authentication state changes, I expect the problem in your onAuthStateChanged code is with firebase.auth().signOut(); which will trigger a new onAuthStateChanged ... resulting in weird inception behavior.

You already placed firebase.auth().signOut(); in your logout button and I suggest you remove firebase.auth().signOut(); from the onAuthStateChanged on the login page, then I expect the Fibonacci would stop (but do you really want it to stop?)

Let me know if this gets any result. Hope it helps,

0
votes

I see you are pushing pages in your onAuthStateChanged. Which can cause a problem.

  1. On the first Login page you create 1 onAuthStateChanged login when you click login you PUSH 1 new home page
  2. On the Home page you create 1 onAuthStateChanged logout when you click logout you PUSH 1 new Login Page (so you have 2 Login Pages & 2 onAuthStateChanged login loaded after click)
  3. After clicking login on the new Login Page you don't create 1 new Logout Page, but 2 because you already had 2 onAuthStateChanged login, so this results in 3 Logout Pages loaded and 3 onAuthStateChanged logout
  4. When you click logout on the new home page, you call the 3 onAuthStateChanged logout and thus create 3 new login pages + 2 existing login pages = 5
  5. And so on.

To test if this is the case, you can start loading your Module with the login page, when you login you PUSH the home page and when you logout you DON'T push the login page but popToRoot()

Hope this helps,