12

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...

4
  • .onAuthStateChanged is asynchronous and resolves null for a microsocond on page load/refresh. That's how it works. You can grey out or put loader gif's . Commented Jun 5, 2018 at 4:38
  • Do you mean that, after reload, the first onAuthStateChanged event will be fired with null user and after a few secounds the event will be re-fired with actual user info? I implemented loading gif for 10 seconds until loading is finished like you mentioned, however, unfortunately my onAuthStateChanged is fired only once with null user... Commented Jun 5, 2018 at 4:48
  • try the web app / your app on another browser. I've noticed that if you set Firefox, for example, to never remember History (presumably turning off storage), my auth fails w no meaningful error. Commented Jun 5, 2018 at 20:05
  • Are you using hosting rewrites? The delay is quite significant for me, but it goes away completely if I do not use hosting rewrites. Commented Sep 7, 2019 at 10:51

3 Answers 3

9

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your advice. In my case, firebase won't guarantee to call onAuthStateChanged when the page is reloaded whether user is logged in or not... is my understand correct? If so, should I call some other method like auth.currentUser after finishing reload clearly?
Your onAuthStateChanged callback will be called with the current state when the page loads, and then with every stage change. That is precisely its purpose. It'll be easier to help more if you update your question to include a minimal complete reproduction of the problem, as right now all I can say is that it sounds like things are working as expected.
I've updated my question with your advice. I appreciate it if you check my update.
...I actually just tested w console.log and firebase.auth() is not firing with null initially like it used to. It does still fire asynchronously, and my UI still blinks. ...proly my coding should be updated to mute the blink (e.g. signin button display:none vs photoURL <img> acct menu)...
Hmmm, I feel it's interesting (or strange) behavior on my app. My understand is: Null won't be returned unless the user remove his auth status or local storage. Finally, I found that removing any caches on my chrome, then the issue won't appear for a moment, however, sometimes this still might happen. So I decided to remove session and set redirection to login page if the authentication failed. Your advice helped me a lot. Thanks!
2

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.

Comments

1

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.

1 Comment

Thank you for you comment. Yes, I'm sure that the user obj is only referenced within onAuthStateChanged method.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.