AuthGuard doesn't wait for authentication to finish before checking user

倖福魔咒の 提交于 2019-12-17 19:27:21

问题


I've read the guide here: https://angular.io/docs/ts/latest/guide/router.html

Seems pretty straightforward, however, I'm not sure how to use angularfire2's authentication within an auth guard (canActivate). What I've tried is:

AuthService

import { Injectable } from '@angular/core';
import { AngularFire } from 'angularfire2';

@Injectable()
export class AuthService {

  private user: any;

  constructor(private af: AngularFire) {
    this.af.auth.subscribe(user => {
      this.user = user;
    })
  }

  get authenticated(): boolean {
    return this.user ? true : false;
  }

}

AuthGuard

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private router: Router, private authService: AuthService) { }

  canActivate(): Observable<boolean> | boolean {
    if (this.authService.authenticated)
      return true;

    this.router.navigate(['/login']);
    return false;
  } 

}

I've also added AuthService to bootstrap providers.

This sort of works fine, however, my main problem is when I refresh (or initially load) the page on that has AuthGuard it always redirects me to the login page since the AuthGuard doesn't wait for the authentication response. Is there a way to wait for the authentication to finish (even if it's failed) and then check whether the user is authenticated?


回答1:


The problem is with your code. In the AuthGuard you check the result of authenticated() method that will most probably return false as the user property is still not set. Try this:

AuthService:

import { Injectable } from '@angular/core';
import { AngularFire } from 'angularfire2';';
import { Observable } from 'rxjs/Observable';

@Injectable()
export class AuthService {

  private user: any;

  constructor(private af: AngularFire) { }
  setUser(user) { this.user = user; }
  getAuthenticated(): Observable<any> { return this.af.auth; }
}

AuthGuard:

@Injectable()
export class AuthGuard implements CanActivate {

  constructor(private router: Router, private authService: AuthService) { }

  canActivate(): Observable<boolean> | boolean {
    // here check if this is first time call. If not return 
    // simple boolean based on user object from authService
    // otherwise:

    return this.authService.getAuthenticated.map(user => {
          this.authService.setUser(user);
          return user ? true : false;
    })

  } 
}



回答2:


It may be different in some versions of the router but I needed to return an observable that completes.

import { CanActivate, Router } from '@angular/router'

@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private af: AngularFire, private router: Router) { }

  canActivate(): Observable<boolean> {
    return this.af.auth.map(user => {
      if (user != null)
        return true
      this.router.navigate(['/login'])
    })
    .take(1) // To make the observable complete after the first emission
  }
}


来源:https://stackoverflow.com/questions/37897273/authguard-doesnt-wait-for-authentication-to-finish-before-checking-user

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!