Harshil Modi
Harshil Modi

Reputation: 436

Firebase: How to persist auth state?

I am using firebase web sdk without React. I have 4 pages in my application. I am using express js in for each pages to send html file of that route.

I have a file called common.js in which I defined methods that will be shared by all pages. In the same file I defined a method to act on auth changed is as following:

Modified below code

import { initializeApp } from 'firebase/app';
import { getAuth, onAuthStateChanged } from 'firebase/auth';
import { getFirestore } from 'firebase/firestore';
import { firebaseConfig } from './firebase.config';

const firebaseApp = initializeApp(firebaseConfig);
const db = getFirestore(firebaseApp);
const auth = getAuth(firebaseApp);

const addNavbar = () => {
   $('#nav').load('nav.html', () => {
      document.getElementById('btnSignOut').addEventListener('click', (e) => {
         auth.signOut();
      });
   });
}

// createAlert, createEditDeleteButtons, displayLoaderAndHideApp defined here

const unsubscribeOnAuthStateChanged = onAuthStateChanged(auth, async (user) => {
   if (user) {
      window.location.replace('/home');
   } else {
      window.location.replace('/login');
   }
});

export {
   addNavbar, auth, createAlert, createEditDeleteButtons, db, displayLoaderAndHideApp,
};

On each page I first call handleOnAuthStateChanged(), and it is also called after successful login. I want to persist the auth so I came across setPersistence(), so I used it in login.js and is as follows:

import { browserLocalPersistence, browserSessionPersistence, setPersistence, signInWithEmailAndPassword } from 'firebase/auth';
import { auth, handleOnAuthStateChanged } from './common';

document.getElementById('btnSignin').addEventListener('click', async (e) => {
   e.preventDefault();
   try {
      const form = document.querySelector('form.formLogin');
      const email = form.email.value.trim();
      const password = form.password.value;
      await setPersistence(auth, browserLocalPersistence);
      await signInWithEmailAndPassword(auth, email, password);
      handleOnAuthStateChanged(auth.currentUser); // here auth will retrieve the new logged in user
   } catch (e) {
      console.error(e);
   }
});

If I use onAuthStateChanged() on other pages my user is null then I am stuck in a loop.

Am I missing something?

Update

All of the minimal code is after removing all the functionalities except a few that might causing the problem.

I have a file called nav.html that is loaded into page by common.js and is as defined above.

Code for home, page 1 and page 2 adds navigation by calling addNav. Home will import methods from common.js, page 2's js, and page 1's js. Home page's js is as following:

import { addDoc, collection, deleteDoc, doc, getDocs, onSnapshot, query, setDoc, where } from 'firebase/firestore';
import { addNavbar, createAlert, createEditDeleteButtons, db, displayLoaderAndHideApp as displayLoader } from './common';
// imports from page 1 and page 2

addNavbar();

// Other methods are defined here...

// Nothing is exported as of now..

Upvotes: 0

Views: 3475

Answers (1)

Frank van Puffelen
Frank van Puffelen

Reputation: 600071

Firebase automatically persists the auth state on most browser environments, and restores it on app/page reload. To detect this restore of auth state (and other auth state changes) you will need to register an auth state listener with the SDK as shown in the first code fragment in the documentation on getting the current user:

import { getAuth, onAuthStateChanged } from "firebase/auth";

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

Most of the code of your handleOnAuthStateChanged can probably go into this handler.

Upvotes: 1

Related Questions