Search code examples
angulartypescriptfirebasefirebase-authenticationangularfire

Angular fire app losing authstate upon refreshing the page


Hi all I am working on a sharing app with angular and firebase and I have encountered a problem that I have 1. Never encountered before 2. Tried solutions from stack overflow to no avail. I am implementing an auth guard into my app so that certain pages can only be viewed by authenticated users. Here is my sign in directive code:

import { Directive, HostListener } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import * as firebase from 'firebase/app';

@Directive({
  selector: '[appGoogleSignin]',
})
export class GoogleSigninDirective {
  constructor(private afAuth: AngularFireAuth) {}

  @HostListener('click')
  onclick() {
    this.afAuth
      .setPersistence(firebase.default.auth.Auth.Persistence.LOCAL)
      .then(() => {
        this.afAuth.signInWithPopup(
          new firebase.default.auth.GoogleAuthProvider()
        );
      });
  }
}

Here is my authguard code:

import { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import {
  CanActivate,
  ActivatedRouteSnapshot,
  RouterStateSnapshot,
  UrlTree,
} from '@angular/router';
import { Observable } from 'rxjs';
import { SnackService } from '../services/snack.service';

@Injectable({
  providedIn: 'root',
})
export class AuthGuard implements CanActivate {
  constructor(private afAuth: AngularFireAuth, private snack: SnackService) {}

  async canActivate(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot
  ): Promise<boolean> {
    const user = await this.afAuth.currentUser;
    const isLoggedIn = !!user;
    if (!isLoggedIn) {
      this.snack.authError();
    }

    return isLoggedIn;
  }
}

And here is my implementation of the auth guard:

    path: 'upload',
    loadChildren: () =>
      import('./upload/upload.module').then((m) => m.UploadModule),
    canActivate: [AuthGuard],
  },

I have tried multiple solutions on stack overflow including setting the persistence state to both session and local. None have worked for me.


Solution

  • The this.afAuth.currentUser value is refreshed asynchronously when you load the page. So by the time your code accesses this.afAuth.currentUser it probably hasn't been set yet.

    Instead of accessing the this.afAuth.currentUser value synchronously, observe the auth.user stream to make sure you are always reacting to the latest authentication state. See also the first code sample in Getting started with Firebase Authentication.