Reputation: 364
I'm trying to create a canActivate()
function that will :
return false;
this.router.navigateByUrl('/login');
when the status code it 401
from an Observable
i.e when HttpErrorResponse
is raised.
==============================================
This is my service :
currentUser(token): Observable<any> {
const url = `${this.BACKEND_URL}/status`;
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
})
};
return this.http.post(url, {'token': token}, httpOptions);
}
The response data is a Json blob and can a 401
or 200
status code, this is the Python code:
post_data = request.get_json()
post_token = post_data.get('token')
resp = User.decode_auth_token(post_token)
if not isinstance(resp, str):
user = User.query.filter_by(id=resp).first()
response_object = {
'status': 'success',
'data': {
'user_id': user.id,
'email': user.email.lower(),
'first_name': user.first_name,
'last_name': user.last_name,
'admin': user.admin,
'registered_on': user.registered_on
}
}
return make_response(jsonify(response_object)), 200
response_object = {
'status': 'fail',
'message': resp
}
return make_response(jsonify(response_object)), 401
I currently have this code which fails with ERROR Error: Uncaught (in promise): HttpErrorResponse
when the status code is 401
:
@Injectable()
export class EnsureAuthenticated implements CanActivate {
constructor(private auth: AuthService, private router: Router) {}
canActivate(): Observable<boolean> {
console.log('AUTH');
return this.auth.currentUser(localStorage.getItem('token')).pipe(map(suc => {
if (suc.status = 'success') {
return true;
} else {
this.router.navigateByUrl('/login');
return false;
}
}));
}
}
I'm using angular 7.0.4.
Upvotes: 1
Views: 1739
Reputation: 101
This worked for me Instead of returning false that do nothing, return UrlTree directly to navigate to where you want to go.
canActivate(
route: ActivatedRouteSnapshot,
state: RouterStateSnapshot
):
| Observable<boolean | UrlTree>
| Promise<boolean | UrlTree>
| boolean
| UrlTree {
return this.accountClientService.isLoggedIn().pipe(
map((responseData: ResponseService<boolean>) => {
if (responseData.model) {
return responseData.model;
}
return this.router.createUrlTree(['/signin']);
}),
catchError((err) => {
return of(this.router.createUrlTree(['/signin']));
})
);
}
Upvotes: 0
Reputation: 364
The answer was to catch the error using catchError
:
import { Injectable } from '@angular/core';
import { CanActivate, Router } from '@angular/router';
import { AuthService } from './auth.service';
import {Observable, of} from 'rxjs';
import {catchError, map} from 'rxjs/operators';
import {HttpErrorResponse} from '@angular/common/http';
@Injectable()
export class EnsureAuthenticated implements CanActivate {
constructor(private auth: AuthService, private router: Router) {}
canActivate(): Observable<boolean> {
return this.auth.currentUser(localStorage.getItem('token')).pipe(map(suc => {
if (suc.status = 'success') {
return true;
} else {
this.router.navigateByUrl('/login');
return false;
}
}), catchError((err: HttpErrorResponse) => {
this.router.navigateByUrl('/login');
return of(false);
}));
}
}
Upvotes: 4