0

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:

enter image description here

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..

2
  • 1
    "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." - Masking status responses is not a good practise.. Commented Nov 18, 2020 at 8:49
  • @iLuvLogix I understand but can't do anything about it. It's an enterprise application and they have been doing this like for 3-4 years. That's how they built their backend. Commented Nov 18, 2020 at 8:51

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.