'firebaseAuth.onAuthStateChanged return user null

I'm trying to implement authentification using firebase auth, the things is that when it comes to persistance i'm stuck. I tried to use local storage as you can see below :

AuthService.ts :

import {HttpClient} from '@angular/common/http';
import { Injectable } from '@angular/core';
import {AngularFireAuth} from '@angular/fire/auth';
import {Router} from '@angular/router';
import firebase from 'firebase/app';

@Injectable({
  providedIn: 'root'
})

export class AuthService {

  userData: any;

  constructor(private http: HttpClient, private firebaseAuth: AngularFireAuth, private router: Router) {
    this.firebaseAuth.useEmulator('http://localhost:9099');
    this.firebaseAuth.authState.subscribe(user => {
      if (user) {
        this.userData = user;
        localStorage.setItem('user', JSON.stringify(this.userData));
        JSON.parse(localStorage.getItem('user'));
      } else {
        localStorage.setItem('user', null);
        JSON.parse(localStorage.getItem('user'));
      }
    });
    this.firebaseAuth.onAuthStateChanged( user => {
      console.log(user);
    });
  }



  signIn(email: string, password: string): void {
    this.firebaseAuth.setPersistence(firebase.auth.Auth.Persistence.LOCAL).then(() => {
      this.firebaseAuth.signInWithEmailAndPassword(email, password)
        .then(result => {
          this.router.navigate(['/dashboard/accueil']);
          console.log('Nice, it worked!');
        })
        .catch(error => {
          console.log('Something went wrong:', error.message);
        });
    }).catch(error => {
      console.log('Something went wrong:', error.message);
    });
  }

  signOut(): void {
    this.firebaseAuth.signOut().then(() => {
      localStorage.removeItem('user');
      this.router.navigate(['/dashboard/connexion']);
    });
  }

  forgetPassword(email: string): void {
    this.firebaseAuth.sendPasswordResetEmail(email).then(() => {
      window.alert('Password reset email sent, check your inbox.');
    }).catch((error) => {
      window.alert(error);
    });
  }

  get isLoggedIn(): boolean {
    const user = JSON.parse(localStorage.getItem('user'));
    return (user !== null) ? true : false;
  }


}

But the problem is that firebaseAuth.onAuthStateChanged return null after refreshing the page with F5 even authState. It's like onAuthStateChange is losing his last state after refresh.

Note that i'm using firebase Emulator.

app.module.ts Firebase module has been well import

AngularFireModule.initializeApp(environment.firebase),
AngularFireAuthModule,

You can take a look at the confing here : environnement.ts

 firebase: {
    apiKey: 'xxxxxxxxxxxx',
    projectId: 'xxxx'
  }

Maybe it's link to this error that i'm getting in the web console when i'm refreshing the page :

POST https://www.googleapis.com/identitytoolkit/v3/relyingparty/getAccountInfo?key=xxxxxxx 400

Note that key is equal to my apiKey state in the config.

When i look closer here what the error say :

{
  "error": {
    "code": 400,
    "message": "INVALID_ID_TOKEN",
    "errors": [
      {
        "message": "INVALID_ID_TOKEN",
        "domain": "global",
        "reason": "invalid"
      }
    ]
  }
}

Any help would be greatly appreciate.

EDIT

Here what i get after refresh my page from onAuthStateChanged : enter image description here

There is no 2 calls, only 1 that return false.



Solution 1:[1]

Firebase Auth will persist the login state by default, so you don't have to manually save the token into local storage. As Frank said, onAuthStateChanged will fire will user being null initially, but if the user is signed in, it will fire again shortly after that with the actual user value.

Solution 2:[2]

Following to the comment section of the accepted answer, I decided to highlight the fact that this appears to be en emulator issue.

This was driving me crazy. No matter what I did, even jumping up and down, the currentUser was always null. I saw the same behavior: onAuthStateChanged() got called only once and all I got was a null-user.

After removing my provider for the Auth-emulator, everything started to work without issues.

  providers: [

    // ...
    { provide: REGION, useValue: envFirebase.region},

    // THE PROBLEM:
    {
        provide: USE_AUTH_EMULATOR, 
        useValue: envFirebase.useEmulators ? ['http://localhost:9099'] : undefined
    },
  ],

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 dshukertjr
Solution 2 Stefan Falk