Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sometimes firebase.auth().onAuthStateChanged returns user of null when I refresh the page

Precondition

$npm install --save [email protected]

issue

I'm using firebase authentication on my web application. In my app, I implemented onAuthStateChanged for client side js like below.

firebase.auth().onAuthStateChanged((user) => {
  if(user) {
    //logged in
  } else {
    //do sth
  }
});

After login, I confirmed this method will return actual user obj, but if I refresh the page, then user might be null. Curiously, sometimes user won't be null. I'm afraid there are some limitation of calling onAuthStateChanged, but currently I have no idea.

How should I deal with this issue?

update

Let me share my minimal example.

My app is working with express.js. There are two URLs like below. /login /main

In the login page, I implemented authentication method. If the login is successfully finished, then user will be redirected to '/main'.

//login.js
import firebase from 'firebase';
var config = {...};
firebase.initializeApp(config);

var provider = new firebase.auth.GoogleAuthProvider();
firebase.auth().signInWithPopup(provider)
.then((result) => {
  return result.user.getIdToken(true);
}).then((idToken) => {
  if(idToken) {
    location.href = '/main';
  }
});

In the main page, there is no login method. main.js is only checking whether user is logged in.

//main.js
import firebase from 'firebase';
var config = {...};
firebase.initializeApp(config);

firebase.auth().onAuthStateChanged((user) => {
  if (user) {
    //initialize main page.
  } else {
    location.href = '/login';
  }
}

I think login status is stored on LocalStorage of web browser. This means that, after finishing loading of main.js, onAuthStateChanged will be automatically fired with user information, but not working as I expected. I'm sure that persistence of login information is correct because official document says the default setting is LOCAL for web client.

https://firebase.google.com/docs/auth/web/auth-state-persistence

my question

Should I implement onAuthStateChanged with another way? How can I ensure user is logged in after reload?

e.g.

import $ from 'jquery';
$(document).on('ready', () => {
  onAuthStateChanged((user) => {...});
});

Or could you show me the correct way?

Workaround

I decided to remove session and set redirection to login page if null is returned. This is not a solution, but a workaround currently...

like image 526
Osamu Tokita Avatar asked Jun 04 '18 15:06

Osamu Tokita


3 Answers

You're not calling onAuthStateChanged. Instead you're telling Firebase to call you when the authentication state changes, which may happen a few times when the page is being re-loaded

When a page is getting loaded and there was previously a user signed in, the auth state may change a few times, while the client is figuring out if the user's authentication state it still valid. For that reason, you may see a call with no user before seeing the final call with the actual signed in user.

like image 54
Frank van Puffelen Avatar answered Sep 28 '22 01:09

Frank van Puffelen


The fact it's sometimes null and sometimes not null likely points to an async problem. Are you making the check in the if statement above? All references to the user should be within the callback. If that all checks out, maybe check that authentication is being properly initiated.

like image 35
Will Avatar answered Sep 28 '22 00:09

Will


onAuthStateChanged is an observer as stated in firebase docs, which gets triggered when the auth state is changed like user signed in, signed out, pwd change. To check if user is logged in or not you should use firebase.auth().currentUser which will give you the current logged in user. As you said your state is local firebase.auth().currentUser will always give you user unless user is signed out.

like image 40
pilku Avatar answered Sep 28 '22 02:09

pilku