Reputation: 996
I am implementing JWT refresh token in my angular project. I am following the below guide for that.
https://angular-academy.com/angular-jwt/
Here is my code:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const user: any = this.storage.user;
const addToken = !req.urlWithParams.includes('token');
const token = user ? user.token : null;
if (token && !req.url.includes('token=') && addToken) {
req = this.addToken(req, user.token);
}
return next.handle(req).pipe(switchMap((event) => {
if (event instanceof HttpResponse && event.body.code === 401 && token) {
return this.handle401Error(req, next);
}
return next.handle(req);
}));
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
Authorization: `Bearer ${token}`,
},
setParams: {
token
}
});
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
return this.getRefreshedJWT().pipe(
switchMap((res: any) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(res.token);
return next.handle(this.addToken(request, res.token));
}));
} else {
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => {
return next.handle(this.addToken(request, jwt));
}));
}
}
getRefreshedJWT() {
const jwt_refresh_url = 'api/v3/token/refresh?token=' + this.storage.user.token;
return this.http.getFromAccountsApi(jwt_refresh_url)
.pipe(tap((token) => {
this.storeJwtToken(token);
}));
}
private storeJwtToken(jwt: string) {
const user = this.storage.user;
user.token = jwt;
this.storage.user = user;
}
Btw. the reason I am not doing this inside catchError
is because our backend is structured like it will always send HTTP status code 200 and inside that response they will send custom http code based on error such as 401, 500 or success such as 200 and etc. So it won't go inside catchError
since it looks for HTTP status codes other than 200.
Now my issue is after implementing the inceptor now my API's getting called multiple times. See screenshot below:
Been stuck since yesterday and haven't found any proper solution yet. Would be great if anyone could point what I am doing here and how do I solve it?
If you have any further query, do let me know. Thank you..
Upvotes: 0
Views: 790
Reputation: 38
A tip for:
Btw. the reason I am not doing this inside catchError is because our backend is structured like it will always send HTTP status code 200 and inside that response they will send custom http code based on error such as 401, 500 or success such as 200 and etc. So it won't go inside catchError since it looks for HTTP status codes other than 200.
You can do a map in the response from the server and check if theres an error, and then throw an error from there, then catchError should work on sequent pipes.
The error is because you are returning the handle in the switchMap making the request being called again.
return next.handle(req);
Change that line to:
return of(event)
And it should work
Upvotes: 1