Angular 2 - Support for stateful Firebase update page

So, I am very close to understanding this. Basically, I have a login, and I have a code setting for viewing onAuthStateChanged, but the problem is that when I refresh the page, even if the user is currently logged in, it still redirects to the /login page, because The auth guard that I have set up checks to see if the user is logged in.

I have an authentication service that does all authentication.

In my auth service constructor, where I have my onAuthStateChanged setting onAuthStateChanged :

 constructor( private auth: AngularFireAuth, private router:Router, private db:AngularFireDatabase, ) { firebase.auth().onAuthStateChanged(function(user) { if (user) { // What do I need to put here to ensure that the auth guard goes to the intended route? } }); } 

Here is my canActivate() protection method:

  canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean> { if(this.authService.getAuthenticated()) { return Observable.of(true); } else { this.router.navigate(['/login']); } } 

And here is the getAuthenticated() method:

 getAuthenticated() { return firebase.auth().currentUser; } 

Update:

Here are the methods that are called when a user logs in. In the actual component, the login method is used here:

 login(data, isValid) { if(isValid) { this.authService.login(data.email, data.password) .then( (data) => { console.log('data', data); this.router.navigate(['/projects']) }, error => { this._utilities.createToasty({ msg: "The email/password combination is incorrect.", type: "error" }); } ); } } 

And in the auth service, here is the login method:

 login(email, password) { return firebase.auth().signInWithEmailAndPassword(email, password); } 

So right now, I'm not quite sure what code I need to put in to make sure that when my user refreshes the page, the auth defender takes care of this and actually allows the user to go on the route, and not always redirect to the /login route.

Thoughts?

+5
source share
5 answers

I really don't know the answer, since I am not using firebase, so these are more pointers.

Guess 1 : The user is in an intermediate state

The function that performs authentication in the background is not yet running when the canActivate method does. Therefore, the current user is not yet installed. I think firebase just goes to local storage and checks if the token is valid. If this is what it does, just make sure it happens before canActivate.

However, it can work before and have the current user undefined if it is asynchronous, which is quite possible. Then you will need to make sure that canActivate starts after it is resolved.

Actually, it’s even better: use the activation method observed in your case, as shown:

code:

  canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) { return this.af.auth.map((auth) => { if (!auth) { this.router.navigateByUrl('login'); return false; } return true; }).take(1); } 

Guess 2 . You must store something in local storage.

These authentication services usually require storing a token in localstorage, this token is then used to authenticate the user when the page is refreshed. From what I can read, this is done in the background using firebase. You can still check the local storage / storage session to make sure there is information there.

If you do not see anything meaningful in localStorage / sessionStorage, most likely you need to add something at the login.

+5
source

I had the same problem as you, I did the following to solve the problem with localStorage:

 login(email, password): Observable<AuthInfo> { return this.fromFirebaseAuthPromise(this.afAuth.auth.signInWithEmailAndPassword(email, password)); } 

I just added localStorage.setItem("user", this.afAuth.auth.currentUser.uid); to answer the input and localStorage.removeItem("user"); to the logout method.

 fromFirebaseAuthPromise(promise): Observable<any> { const subject = new Subject<any>(); promise .then(res => { const authInfo = new AuthInfo(this.afAuth.auth.currentUser.uid); this.authInfo$.next(authInfo); subject.next(res); subject.complete(); localStorage.setItem("user", this.afAuth.auth.currentUser.uid); }, err => { this.authInfo$.error(err); subject.error(err); subject.complete(); }); return subject.asObservable(); } logout() { this.afAuth.auth.signOut(); localStorage.removeItem("user"); this.authInfo$.next(AuthService.UNKNOWN_USER); this.router.navigate(['/login']); } 

and changed the canActivate() method to the following:

 canActivate() { //you can check token is exists or not here if (localStorage.getItem('user')) { console.log("user ist logged in ....", localStorage.getItem('user')); return true; } else { console.log("user is not logged in"); this.router.navigate(['/login']); return false; } } 
+2
source
 firebase.auth().onAuthStateChanged(function (user) { console.log('onAuthStateChanged: ', user); }); 
0
source

Let me try to solve this problem by storing user data in local storage. My logic is quite simple, when the user is logged in, we will save the user data in local storage, thanks to this we will get the user state even after the page is reloaded.

 userData: any; constructor( public afAuth: AngularFireAuth ) { this.afAuth.authState.subscribe(user => { if (user) { localStorage.setItem('user', JSON.stringify(this.userData)); JSON.parse(localStorage.getItem('user')); } else { localStorage.setItem('user', null); JSON.parse(localStorage.getItem('user')); } }) } 
0
source

Write your code inside setTimeout. Because this problem occurs after page refresh.

 setTimeout(()=>{ console.log("currentUser", firebase.auth().currentUser); },1000) 
0
source

Source: https://habr.com/ru/post/1268070/


All Articles