How to trigger an http request that has has a 401 error after the token has been refreshed?

1.8k Views Asked by At

I have the following problem: I make a request to an endpoint that validates if the token has expired. If it has expired, it returns a 401 error, I need the token to be refreshed at the time of the error (so far I am doing well). Once the token is refreshed, I would like the http request that I made at the beginning to be executed again.

Here is some of my code:

fetchTours() {
const headers = new HttpHeaders({
  Authorization: `Bearer ${localStorage.getItem('a_t') ?? ''}`,
});

return this.http
  .get<TourInterface[]>(`${this.baseUrl}/tours`, { headers })
  .pipe(catchError((error) => of(error)))
  .pipe(
    switchMap((data) => {
      if (data.error) {
        this.authService.validateToken().subscribe();
      }
      return of(data);
    })
  );
}

This is the method that I will call from my component. thanks a lot for your help and time!!

2

There are 2 best solutions below

1
On

This sounds like a wonderful example for an angular http interceptor.
Documentation

You can just create an angular service that intercepts every http request. In the handle part you can add your catchError block to catch the 401 and add special handling to re-login and execute your original request again.

A simple example of an interceptor that tracks the request time looks like this.
You can just adapt this and change the time tracking part with your catchError and login functionality

0
On

you can implement the below interceptor to achieve this.

if (this.isRefreshingToken && !req.url.endsWith(tokenURL)) {
      // check if unique url to be added in cachedRequest

      if (urlPresentIndex == -1) {
        this.cachedRequests.push(req);
        return this.tokenSubject.pipe(
          switchMap(() => next.handle(req)),
          tap((v) => {
            // delete request from catchedRequest if api gets called

            this.cachedRequests.splice(
              this.cachedRequests.findIndex(
                (httpRequest) => httpRequest.url == req.url
              ),
              1
            );
            return EMPTY;
          })
        );
      } else {
        //already in cached request array

        return EMPTY;
      }
    }

want to deep dive check my medium article Token-Refresh-Interceptor-retry-failed-Requests

Check it out, how it works on stackblitz