I have been scratching my head at this for hours and I am hoping someone can help me and guide me. So, I am developing an Angular 7 application authentication module. One of the requirements is to develop an HTTP interceptor to add an Authorization (JWT) token and also to handle all error messages.
I am using an NPM package to handle localstorage of the tokens. This package uses set and get methods to store and returns a promise rather than the actual value of the token.
Now, my problem is in my interceptor function as we can see below. I have tried to comment where I am getting stuck.
intercept(request: HttpRequest<any>, next: HttpHandler):
Observable<HttpEvent<any>> {
// Trying to get the token here but this returns a promise
// this.token is a service for managing storage and retrieving of tokens
const token = this.token.getToken();
// If token is got, set it in the header
// But when i console log, i see [object promise] other than the token
if (token) {
request = request.clone({
headers: request.headers.set('Authorization', 'Bearer ' + token)
});
}
return next.handle(request).pipe(catchError(err => {
// Logs out the user if 401 error
if (err.status === 401) {
this.token.remove()
.then(() => {
this.auth.changeAuthStatus(false);
this.router.navigateByUrl('/login');
});
}
// Returns the error message for the user to see
// for example in an alert
const error = err.error.message || err.statusText;
return throwError(error);
}));
}
I hope I have well explained this problem. I have tried using async
before the interceptor function but I get a red nasty error saying TS1055: Type 'typeof Observable' is not a valid async function return type in ES5/ES3 because it does not refer to a Promise-compatible constructor value. Types of parameters 'subscribe' and 'executor' are incompatible.
.
I will appreciate any help towards fixing this issue.
Thank you!
to incorporate asynchronous processing into your interceptor, you want to promote your promise to an observable, and switchMap
your observables together, returning the proper request:
import { from as observableFrom } from "rxjs";
import { switchMap } from "rxjs/operators";
intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return observableFrom(this.token.getToken()).pipe(
switchMap(token => {
// do something with your promise-returned token here
return next.handle(request).pipe(catchError(err => {
// Logs out the user if 401 error
if (err.status === 401) {
this.token.remove()
.then(() => {
this.auth.changeAuthStatus(false);
this.router.navigateByUrl('/login');
});
}
// Returns the error message for the user to see
// for example in an alert
const error = err.error.message || err.statusText;
return throwError(error);
}));
})
);
}
have not tested this code directly, so i apologize for any typos, but it should get you where you want to go.
1) promote your promise to an observable with from
2) chain your observables with switchMap
i notice you're not actually using the token returned in your example, you would do that in the function within switchMap that receives the result of the promise