giozh
giozh

Reputation: 10068

Angular2: Route redirect with AuthGuard

I've an Angular2 app that should block route to a certain page if user is not logged in. This is my app.routes file

export const routes: Routes = [
  { path: '', component: LoginComponent },
  { path: 'login', component: LoginComponent },
  { path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
  { path: '**', component: LoginComponent },
];

and my AuthGuard file

@Injectable()
export class AuthGuard implements CanActivate {
response: ResponseInterface;

constructor(private router: Router, private localStorage: LocalStorageService,
 private services: MyService) { }
canActivate() {

let token = String(this.localStorage.get('token'));
if (token != null) {
  this.services.keepAlive(token).subscribe(
    response => this.response = response,
    error => alert(error),
    () => {
      if (this.response.status == 'OK') {
        console.log("response OK");
        return true;
      } else {
        console.log("response KO");
        this.router.navigate(['/login']);
        return false;
      }
    }
  )

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

now, if i try to navigate to http://localhost:4200/#/home path and I already have a token stored into localStorage, nothing happen: home page is not showed and path on navigation bar become http://localhost:4200/#/. What's wrong?

Upvotes: 3

Views: 3688

Answers (1)

seidme
seidme

Reputation: 13048

canActive method should return either Observable<boolean>, Promise<boolean> or boolean.

You're subscribing to the this.services.keepAlive Observable, and returning boolean value to the subscribe callback instead of returning it to the canActivate method. Change your code as following:

canActivate(): Observable<boolean> | Promise<boolean> | boolean {
    let token = String(this.localStorage.get('token'));
    if (token != null) {
        return this.services.keepAlive(token)
            .map(response => {
                if (response.status == 'OK') {
                    console.log("response OK");
                    return true;
                } else {
                    console.log("response KO");
                    this.router.navigate(['login']);
                    return false;
                }
            });
    } else {
        this.router.navigate(['login']);
        return false;
    }
}

This way, the Observable of a boolean type ( Observable<boolean> ) will be returned to the canActive method, and route resolving should work as expected.

Upvotes: 5

Related Questions