John Montgomery
John Montgomery

Reputation: 7096

canActivate failure on initial load not redirecting as expected

I have a route guard that checks whether a user is currently logged in:

import {Injectable} from "@angular/core"
import {CanActivate} from "@angular/router"

import {Observable} from "rxjs/Observable"
import {UserService} from "./user.service"

@Injectable()
export class LoggedInGuard implements CanActivate {
    constructor (private userService: UserService) {}

    canActivate (): Observable<boolean> {
        return this.userService.getLoginStatus()
    }
}

user.service:

import {Injectable} from "@angular/core"
import {Router} from "@angular/router"

import {Observable} from "rxjs/Observable"
import {AngularFireAuth} from "angularfire2/auth"
import * as firebase from "firebase/app"

@Injectable()
export class UserService {
    private user: firebase.User

    constructor (private router: Router, private afAuth: AngularFireAuth) {
        this.afAuth.authState.subscribe(user => {
            this.user = user
        })
    }

    public login (email: string, password: string) {
        this.afAuth.auth.signInWithEmailAndPassword(email, password).then(user => {
            this.user = user
            this.router.navigateByUrl("/dashboard")
        })
    }
    public logout () {
        this.afAuth.auth.signOut()
    }
    public getLoginStatus (): Observable<boolean> {
        return this.afAuth.authState.map(Boolean)
    }
}

And a redirect from / to /login:

{path: "", redirectTo: "login", pathMatch: "full"}

Everything works fine when a user is logged in, or if I navigate directly to / or /login (the former correctly redirecting to the latter). However, if I try to navigate to a protected route while not logged in, it redirects me to /, but then instead of redirecting again it just stops on a blank page.

Is there a reason that second redirect isn't working? Or even better would be for the guard to go directly to /login instead, but I'm not sure how to do that in the context of the observable.

Upvotes: 0

Views: 800

Answers (1)

ChrisY
ChrisY

Reputation: 1783

I'm not sure if your approach should work, but as a workaround you could simply call this.router.navigate(['/login']) within your LoggedInGuard if getLoginStatus() returns false.

@see example: Angular 2 AuthGuard Service with redirect?

Upvotes: 2

Related Questions