How do I keep a user logged into a firebase app after refresh?

26,749

Solution 1

The code you now have handles the case where the user logs on. To handle cases where the user has already logged, you use theonAuthStateChanged method:

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  } else {
    // User is not signed in.
  }
});

Typically you only want to show the log on button in the else of this function.

Documentation: firebase.auth.Auth


Old answer (deprecated/archived):

The code you now have handles the case where the user logs on. To handle cases where the user has already logged, you monitor auth state. From the Firebase documentation on monitoring auth state:

// Create a callback which logs the current auth state
var ref = new Firebase("https://<YOUR-FIREBASE-APP>.firebaseio.com");
ref.onAuth(function(authData) {
  if (authData) {
    console.log("User " + authData.uid + " is logged in with " + authData.provider);
  } else {
    console.log("User is logged out");
  }
});

Typically you only want to show the log on button in the else of this function.

Solution 2

As mentioned in a comment, the accepted answer no longer works. The current way of checking if a user is logged in is

firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  }
});

(from https://firebase.google.com/docs/reference/js/firebase.auth.Auth#onAuthStateChanged)

Solution 3

I have the challenge that my web app has public pages with protected features. With the following code, the user always gets loaded via Firebase SDK before anything else (if logged in). But also gets redirected to the login page, if the page requires authentication. This work fine with page reloads.

Router.beforeEach((to, from, next) => {

  // If route required authentication
  if (to.matched.some(record => record.meta.requiresAuth)) {

    // Load user
    firebase.auth().onAuthStateChanged(user => {

      // If user obj does not exist --> redirect to login page
      if (!user) {
        next({ name: 'login' });
      } else {
        store.commit("user/SET_USER", user);
        user.getIdToken().then(token => {
          store.commit("user/SET_TOKEN", token)
        });

        next();
      }
    });
  } else {

    // Path does not required auth - Still we check the user
    firebase.auth().onAuthStateChanged(user => {

      // If user exist (is logged in) --> store in state.
      if (user) {  
        store.commit("user/SET_USER", user);
        user.getIdToken().then(token => {
          store.commit("user/SET_TOKEN", token)
        });
        next();

      } else {
        next();
      }
    });
  }
})

Solution 4

For any ReactJS users, here's a simple Hook that I have created based on the answers provided in this thread which redirects the user to login route if the current user is not loggedIn.

import { useEffect } from 'react';
import * as firebase from 'firebase';
import { useHistory } from 'react-router-dom';

export default function useProtectedRoute() {
  const history = useHistory();

  useEffect(() => {
    firebase.auth().onAuthStateChanged(function(user) {
      if (!user) {
        console.error(
          'Access to protected route denied, redirecting to login...'
        );
        history.push('/auth/login');
      }
    });
  }, [history]);
}

You just need to import this hook and run inside any component that you don't want to render unless the user is logged in.

Example:

import React from 'react';
import useProtectedRoute from 'hooks/useProtectedRoute';

export default function UserDetailsComponent() {
  useProtectedRoute();
  return <div>This is only visible when user is logged in</div>;
}
Share:
26,749
Justin Haddock
Author by

Justin Haddock

Updated on July 09, 2022

Comments

  • Justin Haddock
    Justin Haddock almost 2 years

    I have an application built in firebase and angular, and am wanting to be able to keep users logged in after refreshing the page. Right now I have a login screen with two basic input fields which bind to a controller

        this.email = "";
        this.pass = "";
        this.emessage = "";
    
        this.loginUser = function() {
            ref.authWithPassword({
                email: this.email,
                password: this.pass
            }, function(error, authData) {
                if (error) {
                    console.log("Login Failed!", error);
                    this.emessage = error.message;
                    $scope.$apply();
                } else {
                    dataStorage.uid = authData.uid;
                    $location.path('/projects');
                    $scope.$apply(); 
                }
            }.bind(this));
        }
    

    This is all fine and dandy and it works, but when the user refreshes the page they are logged back out. Is there some way to, when the controller loads, see if the user is already logged in and auto-redirect? Thanks!