I have been trying to implement AuthGuard properly in my webapp. Currently when I navigate within the app, it works fine. But when I refresh, the authService.loggedIn is processed as false before the AuthService finished executing.
Here is my code:
auth.guard.ts
import {ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot} from '@angular/router';
import {Injectable} from '@angular/core';
import {AuthService} from './auth.service';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (state.url === '/login') {
if (this.authService.loggedIn) {
this.router.navigate(['/']).then().catch();
} else {
return true;
}
} else {
if (this.authService.loggedIn) {
return true;
} else {
this.router.navigate(['/login']).then().catch();
}
}
}
}
auth.service
import {Injectable, OnInit} from '@angular/core';
import {AngularFireAuth} from '@angular/fire/auth';
import {auth} from 'firebase';
import {Router} from '@angular/router';
import {Subject} from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class AuthService implements OnInit {
loggedIn = false;
constructor(public afAuth: AngularFireAuth, private router: Router) {
this.afAuth.authState.subscribe((user) => {
if (user) {
this.loggedIn = true;
}
});
}
ngOnInit() {
}
...
}
I research online and they mentioned different approach (e.g. https://gist.github.com/codediodeio/3e28887e5d1ab50755a32c1540cfd121) but could not make it work on my app.
One error I encounter when I try this approach is "ERROR in src/app/auth.guard.ts(20,8): error TS2339: Property 'take' does not exist on type 'Observable'." I use
import {AngularFireAuth} from '@angular/fire/auth';
and not
import { AngularFireAuth } from 'angularfire2/auth';
Any help / suggestion is appreciated.
Thanks everyone.
I was able to make AuthGuard with browser refresh work.
This link helped a lot: https://gist.github.com/codediodeio/3e28887e5d1ab50755a32c1540cfd121
I just used pipe() to chain operators and used tap() instead of do() since I'm using newer version of rxjs.
Here is the code:
...
import {Observable} from 'rxjs';
import {take, map, tap} from 'rxjs/operators';
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private afAuth: AngularFireAuth) {
}
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable {
return this.afAuth.authState
.pipe(
take(1),
map(user => !!user),
tap(
loggedIn => {
if (!loggedIn) {
this.router.navigate(['/login']);
}
}
)
);
}
}
Thanks.