Reputation: 551
I am trying to protect my routes using authGaurd.
auth.service.ts
import { Injectable } from '@angular/core';
import { environment } from '../../../environments/environment';
import { Router, CanActivate } from '@angular/router';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { Response } from '../response.model';
const httpOptionsSecure = {
headers: new HttpHeaders({'Content-Type': 'application/json', 'Authorization': 'Bearer ' + localStorage.getItem("authToken")})
}
@Injectable()
export class AuthService implements CanActivate {
private baseUrl: string = environment.baseUrl + "auth/";
private signInUrl: string = this.baseUrl + "signIn";
private verifyUserUrl: string = this.baseUrl + "verify";
constructor(private http: HttpClient, public router: Router) {
}
canActivate(): Observable<boolean> {
return new Observable((observer) => {
this.verifyUser().subscribe((res) => {
if (res.code === 200 && res.isSuccess === true) observer.next(true);
else observer.next(false);
}, (err) => {
console.log("Err: ", err);
this.router.navigate(['/','login']);
observer.next(false);
});
});
}
// Verify loggedIn User
verifyUser(): Observable<Response> {
return this.http.post<Response>(this.verifyUserUrl, {}, httpOptionsSecure);
}
So whenever I am trying to go to the protected page and whenever the response from server is 400 code then the request is made again in infinte loop.
I am kind of new to angular, I don't know what am I doing wrong.
Thanks in advance.
Upvotes: 3
Views: 5450
Reputation: 3724
Most probably you are entering an infinite loop because the / path is being redirected to a path which is protected by the AuthGuard itself.
So for example. You try to access Route A, which is protected by the guard, which redirects to route B (the base route / ), and route B could be redirecting (view redirectTo attributes in the route) to route C which is also protected by the AuthGuard, resulting in the following routes.
A -> B -> C -> B -> C...
Make sure that the routing definition is correct.
Note that a route guard is activated for each Route that it is associated with
So for example if you have
/ <- Associated with an Auth Guard
/route1 <- Child of /
/route2 <- Child of /
with the following route definition
let routes:Routes = [
{
path: '',
canActivate: [ AuthGuard ]
children: [
{ path: '', redirectTo: 'route1', pathMatch:'full' },
{ path: 'route1' },
{ path: 'route2' }
]
}
];
Trying to access either of the routes, will trigger the AuthGuard associated with route /
. If you go for example, to route1
, the auth Guard will trigger, which will redirect to /
which will redirect again to route1
and the cycle begins again.
I suggest to read this documentation guide for further information how routing works in angular.
Furthermore, the use of Observables
does not have to do with Angular, but is RxJS
.
Your code can be simplified as below
For RxJS 5.5.x +
import { Observable } from 'rxjs/Observable';
import { catchError, map, of } from 'rxjs/operators';
canActivate(): Observable<boolean> {
return this.verifyUser().pipe(map((res) => {
if (res.code === 200 && res.isSuccess === true) {
return true;
}
this.router.navigate(['/','login']);
return false;
}, catchError((err) => {
console.log("Err: ", err);
this.router.navigate(['/','login']);
return of(false);
}));
}
// Verify loggedIn User
verifyUser(): Observable<Response> {
return this.http.post<Response>(this.verifyUserUrl, {}, httpOptionsSecure);
}
For RxJS 5.4.x and below
canActivate(): Observable<boolean> {
return this.verifyUser().map((res) => {
if (res.code === 200 && res.isSuccess === true) {
return true;
}
this.router.navigate(['/','login']);
return false;
}).catch((err) => {
console.log("Err: ", err);
this.router.navigate(['/','login']);
return Observable.of(false);
});
}
// Verify loggedIn User
verifyUser(): Observable<Response> {
return this.http.post<Response>(this.verifyUserUrl, {}, httpOptionsSecure);
}
Upvotes: 6