Search code examples
angulartypescriptobservableangular2-guards

Angular 2 how to make auth guard work with observable


I'm trying to implement an auth guard to one of my routes but I can't get it to work since I'm not sure how to do it with an observable.

I use ngrx/store to store my token and then in the guard I fetch it using this.store.select('auth'), which fetches an object that looks like this (if you're logged in):

{
  token: 'atokenstring',
  isAuthenticated: true,
  isPending: false
}

And the guard looks like this:

export class AuthGuardService implements CanActivate {

  constructor(private router: Router, private store: Store<IStore>) {}

  canActivate(): Observable<any> {

    return this.store.select('auth').let((state: Observable<IAuthStorage>) => state.filter((auth: IAuthStorage) => !auth.isPending && auth.isAuthenticated)).map(
      (auth: IAuthStorage) => {

        if (!auth.isAuthenticated) {
          return this.router.navigateByUrl('admin/login');
        }
        else {
          return true;
        }
      }
    );
  }
}

Now, the problem appears to be that the guard returns an observable rather than a boolean value. Which causes the route not to render even if you get inside the else which returns true.

How can I make it so that the guard returns a boolean value rather than an observable?


Solution

  • Not sure if this still is the case but a while ago something like this was required

      canActivate(): Observable<any> {
    
        return this.store.select('auth').let((state: Observable<IAuthStorage>) => state.filter((auth: IAuthStorage) => !auth.isPending && auth.isAuthenticated)).map(
          (auth: IAuthStorage) => {
    
            if (!auth.isAuthenticated) {
              return this.router.navigateByUrl('admin/login');
            }
            else {
              return true;
            }
          }
        ).first(); // <<<=== added
      }
    

    for the router only to wait for one event, not for the observable itself to complete.

    first needs to be imported to be available.