My route guard is implemented as follows:
@Injectable()
export class AuthGuard implements CanActivate {
constructor(private router: Router, private authenticationSvc: AuthenticationService) { }
canActivate(): Observable<boolean> {
return this.authenticationSvc.getAuthenticatedUser().map(
r => {
if (this.authenticationSvc.isAuthenticated()) {
// User is logged in, so return true
return true;
}
this.router.navigateByUrl('/login');
return false;
})
}
However, I am facing an issue where sometimes getAuthenticatedUser returns a 401 error. I have an HTTP interceptor that handles the 401 error and redirects to the login page. The problem arises when the .map function never resolves due to the error thrown by the HTTP request. This causes the Angular router to get stuck on the initial routing request and fails to handle subsequent requests from the interceptor. How can I manage this error and ensure that the Observable returned resolves to false without interrupting the flow?
getAuthenticatedUser() {
let getUserObservable = this.http.get(ApiUrl + 'security/getAuthenticatedUser')
.map((res: any) => res.json())
.share()
// Get the result for the cache
getUserObservable.subscribe(
r => {
if (r.success) {
this.authenticatedUser = r.result.user;
}
});
// Return the observable
return getUserObservable;
}
Here is the HTTP interceptor implementation:
export class HttpInterceptor extends Http {
authSvc: AuthenticationService;
lastClicked: any = 0;
constructor(backend: ConnectionBackend, defaultOptions: RequestOptions, private _router: Router, private injector: Injector) {
super(backend, defaultOptions);
}
request(url: string | Request, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.request(url, options));
}
get(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.get(url, options));
}
post(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.post(url, body, this.getRequestOptionArgs(options)));
}
put(url: string, body: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.put(url, body, this.getRequestOptionArgs(options)));
}
delete(url: string, options?: RequestOptionsArgs): Observable<Response> {
return this.intercept(super.delete(url, options));
}
getRequestOptionArgs(options?: RequestOptionsArgs): RequestOptionsArgs {
if (options == null) {
options = new RequestOptions();
}
if (options.headers == null) {
options.headers = new Headers();
}
options.headers.append('Content-Type', 'application/json');
return options;
}
intercept(observable: Observable<Response>): Observable<Response> {
return observable.catch((err, source) => {
// Handle 401 error - clear auth cookie and navigate to login page
if (err.status == 401) {
this._router.navigateByUrl('/login');
}
return Observable.throw(err);
});
}