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

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!

Answers:

Answer

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.

Answer

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)

Answer

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();
      }
    });
  }
})
Answer

If you are using Angular 4 you can use AngularFire2 - Official Firebase Integration.

I have a AuthService that wraps AngularFire2. I just retrieve AuthSession in Service's constructor and use when I need it. Example:

@Injectable()
export class AuthenticationService {

    private authState: any;

    constructor(public afAuth: AngularFireAuth) {
        this.afAuth.authState.subscribe((auth) => {
          this.authState = auth
        });
    }

    get user(): any {
        return this.authenticated ? this.authState : null;
    }
}

Full authentication service code here Full Angular 4 with Firebase example here

Answer

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>;
}

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.