Angular2 auth guard with HTTP request and observables

I am currently using the angular2 example application with spring loading as the backend. I had some problems with the external defense mechanism and the observables.

I am trying to achieve:

  • when someone enters a secure route, the auto-guard should check if it is already set in the service variable
  • If it is not installed, an http request should be issued to check if the session is available.
  • the service method should return true / false (asynchronously due to a possible HTTP request)
  • If the service returns false, auth guard should be redirected to the login page
  • auth guard must return true / false so that the route can be activated or not

My code currently looks like this (I'm using RC5 btw.):

Auth guard

import {Injectable} from "@angular/core"; import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from "@angular/router"; import {Observable, Subject} from "rxjs/Rx"; import {AuthService} from "./auth.service"; @Injectable() export class AuthGuard implements CanActivate { constructor(private authService: AuthService, private router: Router) {} canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean { var authenticated = this.authService.isAuthenticated(); var subject = new Subject<boolean>(); authenticated.subscribe( (res) => { console.log("onNext guard: "+res); if(!res && state.url !== '/signin') { console.log("redirecting to signin") this.router.navigate(['/signin']); } subject.next(res); }); return subject.asObservable(); } } 

Auth service

 import {Injectable} from "@angular/core"; import {User} from "./user.interface"; import {Router} from "@angular/router"; import {Http, Response, Headers} from "@angular/http"; import {environment} from "../environments/environment"; import {Observable, Observer, Subject} from "rxjs/Rx"; @Injectable() export class AuthService { private authenticatedUser : User; constructor(private router: Router, private http: Http) {} signupUser(user: User) { } logout() { //do logout stuff this.router.navigate(['/signin']); } isAuthenticated() : Observable<boolean> { var subject = new Subject<boolean>(); if (this.authenticatedUser) { subject.next(true); } else { this.http.get(environment.baseUrl + '/user') .map((res : Response) => res.json()) .subscribe(res => { console.log("next: returning true"); this.authenticatedUser = User.ofJson(res); subject.next(true); }, (res) => { console.log("next: returning false"); subject.next(false); }); } return subject.asObservable(); } } 

The problem is that the guard never activates the router component, even if I logged in.

Thanks for the help!

+5
source share
1 answer

Edit

 return subject.asObservable(); 

to

 return subject.asObservable().first(); 

The router waits for monitoring to complete. first() terminates it after the first event.

+9
source

All Articles