In order to protect certain routes (admin), I utilize the canActivate feature. In this scenario, I employ an authGuard
class/function:
The issue arises when attempting to return an observable of boolean using: return Observable.of(false);
. This approach does not yield the expected results and triggers the following Error:
Argument of type '(err: any) => Observable | Observable' is not assignable to parameter of type '(err: any, caught: Observable) => ObservableInput'. Type 'Observable | Observable' is not assignable to type 'ObservableInput'. Type 'Observable' is not assignable to type 'ArrayLike'. Property 'length' is missing in type 'Observable'.
Research on a similar issue was conducted, but the solutions found were not completely applicable. One suggested hint or solution recommended using .throw(err);
Upon switching the return statement to: return Observable.throw(err);
, the error disappears. However, it fails to return false
as required for route protection.
A potential root cause could be related to a type mismatch, yet attempts to rectify it have been unsuccessful while trying to maintain the use of observable.of(false)
.
canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean> | Promise<boolean> | boolean {
return this.userService.getAdminAuth()
.map( (res) => {
if ( res === true) {
return true;
} else {
......
return false;
}
})
.catch( (err) => {
if ( err.status === 403 ) {
console.log(`403: ${err.status}`);
return this.userService.refreshToken()
.map( (res) => {
console.log(`Res RefreshToken: ${res}`);
});
}
return Observable.of(false); // protect route!
});
}
Functions within user.service.ts:
....
isAdminAuthenticated = false;
public getAdminAuth() {
console.log('Saved token: ' + localStorage.getItem('ac_token') );
if ( this.isAdminAuthenticated === true ) {
return Observable.of(true);
} else {
return this.http.get(
'URL', {
headers: new HttpHeaders({"Accept": "application/json"}),
withCredentials: true,
observe: "response"
}
)
.map((res) => {
if (res.status === 200) {
this.isAdminAuthenticated = true;
return true;
} else {
return false;
}
}, (err) => {
console.log('Error: ' + err);
return false;
});
}
}
refreshToken() {
return this.http.get(
'URL',
{
headers: new HttpHeaders(
{
"Accept": "application/json",
"Authorization" : "Bearer " + localStorage.getItem('ac_token')
}
),
withCredentials: true,
observe: "response"
}
)
}
If the refreshToken
function is modified to:
refreshToken() {
return this._http.get(
'URL',
{
headers: new HttpHeaders(
{
"Accept": "application/json",
"Authorization" : "Bearer " + localStorage.getItem('ac_token')
}
),
withCredentials: true,
observe: "response"
}
).map( (res) => {
console.log(`Res: ${JSON.stringify(res)}` );
}), (err) => {
console.log(`Err: ${JSON.stringify(err)}` );
};
}
An error message indicates:
ERROR in src/app/admin.guard.ts(38,9): error TS2322: Type 'Observable' is not assignable to type 'boolean | Promise | Observable'. Type 'Observable' is not assignable to type 'Observable'. Type 'boolean | {}' is not assignable to type 'boolean'. Type '{}' is not assignable to type 'boolean'. src/app/service.guard.ts: error TS2339: Property 'map' does not exist on type '(err: any) => boolean'.