angularhttpjwtrequestangular-http-interceptors

Retry original request with HttpInterceptorFn in Angular 17 (Functional Http Interceptor)


I'm having trouble when my interceptor is intercepting a request based on a JWT expiration. I'm able to perform the refresh of the token, but the original request is never retried again.

I have the following error interceptor which is working perfectly except the retrying the original request code (the part that is inside the complete()). It executes the alert and the console log inside the complete method, so the execution gets until there, but the original request is never retried.

export const ErrorInterceptorMethod: HttpInterceptorFn = (
req: HttpRequest<unknown>,
next: HttpHandlerFn,
) => {
const loginService = inject(LoginService);
return next(req).pipe(
  catchError ( error => {

    if (error.status === 401 && req.url !==  environment.urlApiAdmin + '/login') {
      // Unauthorized - JWT Token expired

      console.log("Performing refreshToken request!");

      let reqCloned = req.clone();

      loginService.refreshToken().subscribe({

        error: (errorData) => {
          console.error(errorData);
          console.log("Error refreshing token, logout");
          loginService.logout();
        },

        complete: () => {
          alert("Refresh done, execute again the request!");
          console.log(reqCloned);
          return next(reqCloned); // THIS IS NEVER EXECUTED / DOES NOTHING
        }
      });
    }
    if (error.status === 403) {
      console.log("403 error");
      loginService.logout();
    }
    return throwError(() => error);
  })
)
};

I've been searching for options and I'm not able to find anything useful as all the examples found use HttpHandler instead of HttpHandlerFn.

HttpHandlerFn doesn't have the .handle method, so I can't find a valid way to implement it.

I've also tried to execute this request outside the interceptor (in an external service)n and I was not able to do it.

Can someone please point me in the right direction?

Cheers!


Solution

  • Guys I've managed to solve it with the following code:

          if (error.status === 401 && req.url !==  environment.urlApiAdmin + '/login') {
          // Unauthorized - JWT Token expired
          return loginService.refreshToken().pipe(
            switchMap((tokenReceived) => {
              console.log(tokenReceived);
              sessionStorage.setItem("token", tokenReceived.token);
              loginService.currentAdminToken.next(tokenReceived.token);
              loginService.currentAdminLoginOn.next(true);
              let token : String = tokenReceived.token;
              if (token != '') {
                req = req.clone({
                  setHeaders: {
                    'Accept' : 'application/json',
                    'Authorization' : `Bearer ${token}`,
                  },
                })
              }
              return next(req);
            }
            
          ));
        }
    

    The key to the question was to call the refreshToken method, take the response back inside a pipe -> switchMap, and then return the original request changing its token.

    I hope this can help you as well.

    Cheers