Search code examples
javascriptreactjsfirebasepersistencegoogle-signin

React - Firebase handling Auth persistence using a separate auth class


I am building a react app that uses a simple login feature. I am only using google sign in, and am calling the signInWithPopop function to handle that. I have created a separate class to handle all the auth related code. On the navbar of my website I have a login button if the user is not signed in which switches to a profile button when the user has signed in.

This is how I am currently checking if the user is signed in (not working):

console.log(authHandler.getUser());
const[loginState, setLogin] = useState(authHandler.getUser()? true : false);
return(
    <div className="navbar">
      <div className="nav-options">
        <NavItem name="About"></NavItem>
        <NavItem name="Listings"></NavItem>
        <NavItem name="Dashboard"></NavItem>
        {loginState ? <NavItem name="Profile"><DropDown loginState={setLogin}></DropDown></NavItem> : <NavItem name="Login" click={() => authHandler.signIn(setLogin)}></NavItem>}
      </div>
    </div>
  );

This is what I have for my authHandler class:

import firebase from 'firebase';

export default class Auth{
    constructor(){
        var firebaseConfig = {
            ...
        };
        !firebase.apps.length? firebase.initializeApp(firebaseConfig) : firebase.app();
        firebase.analytics();
        this.provider = new firebase.auth.GoogleAuthProvider();
    }

    signIn(state){
        firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION).then(() => {
            return firebase.auth().signInWithPopup(this.provider).then((result) => {
                console.log("signed in " + result.user.uid);
                this.user = result.user
                state(true);
            }).catch((error) => {
                console.log(error.message);
            });
        }).catch((error) => {
            console.log(error.message);
        })
    }

    getUser(){
        return firebase.auth().currentUser;
    }

    logout(state){
        //TODO: logout of firebase
        state(false);
    }
}

I have tried adding session and local persistence on firebase, but when I refresh the page, the user is signed out. What would be the proper way of maintaining persistence, in a separate class like this? I am trying to build this app with best practices in mind so that the code will be split up properly, and security is maintained.

Thanks!


Solution

  • You're supposed to use an auth state observer to get a callback whenever the user's sign in state changes. When a page first loads, the user is always immediately considered to be signed out. The callback will be invoked some time soon after the user's token has been loaded from persistence and verified. Use this state callback to determine what to render.

    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        // User is signed in, see docs for a list of available properties
        // https://firebase.google.com/docs/reference/js/firebase.User
        var uid = user.uid;
        // ...
      } else {
        // User is signed out
        // ...
      }
    });
    

    You might want to show a loading screen until the first callback tells you for sure if the user was previously signed in or is definitely signed out.

    I suggest reading this for more information.