Home > other >  Angular JWT retry REST call after refresh token with multiple interceptors
Angular JWT retry REST call after refresh token with multiple interceptors

Time:07-15

I'm using Angular 13.

Currently my error.interceptor it automatically catches the 401 error and automatically refreshes the jwt token.

In addition to this, I would need the error.interceptor try to make the previously intercepted call just after the subscribed "validateNewToken()".

Below is an example of my error.interceptor and the auth.interceptor:

error.interceptor

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {
  constructor(private authService: AuthService, private router: Router, private toastr: ToastrService) {
  }
  intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
    return next.handle(request)
      .pipe(catchError((err: HttpErrorResponse) => {
        console.error('Error Intercepted', err)
        if(err.error.code == '40102' || err.error.error == 'unauthorized_client'){
          this.authService.refreshToken().subscribe((res ) => {
            localStorage.setItem('access_token', res.access_token);
            this.authService.validateNewToken(res.access_token).subscribe((resVer: any) => {
              localStorage.setItem('username', resVer.sub);
            })
          })
        }
        return throwError(() => err);
      }));
  }
}

auth.interceptor

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private authService: AuthService) { }
  intercept(req: HttpRequest<any>, next: HttpHandler) {
    const authToken = this.authService.getToken();
    const username = localStorage.getItem('username');
    if (authToken && username) {
      req = req.clone({
        setHeaders: {
          'Authorization': `Bearer ${authToken}`,
          'OAM_REMOTE_USER': username,
          'rejectUnauthorized' : 'false'
        }
      })
    } 
    return next.handle(req)
  }
}

Thanks in advance

CodePudding user response:

MY SOLUTION EDIT error.interceptor:

@Injectable()
export class ErrorInterceptor implements HttpInterceptor {

  constructor(private authService: AuthService, private router: Router, private toastr: ToastrService) {
  }


  private isRefreshing = false;
  private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<Object>> {
    let authReq = req;
    const token = this.authService.getToken();
    const authToken = this.authService.getToken();
    const username = localStorage.getItem('username');
    if (token != null) {
      authReq = this.addTokenHeader(req);
    }
    return next.handle(authReq).pipe(catchError(error => {
      if (error instanceof HttpErrorResponse && (error.error.code == '40102' || error.error.error == 'unauthorized_client')) {
        return this.handle401Error(authReq, next);
      }
      return throwError(() => error);
    }));
  }


  private handle401Error(request: HttpRequest<any>, next: HttpHandler) {
    if (!this.isRefreshing) {
      this.isRefreshing = true;
      this.refreshTokenSubject.next(null);

      return this.authService.refreshToken().pipe(
        switchMap((res: any) => {
          localStorage.setItem('access_token', res.access_token);
          this.authService.verifyToken(res.access_token).subscribe((resVer: any) => {
            localStorage.setItem('username', resVer.sub);
            this.isRefreshing = false;
            this.refreshTokenSubject.next(res.access_token);
          })
          return next.handle(this.addTokenHeader(request));
        }),
        catchError((err) => {
          this.isRefreshing = false;
          return throwError(() => err);
        })
      );
    }
    return this.refreshTokenSubject.pipe(
      filter(token => token !== null),
      take(1),
      switchMap((token) => next.handle(this.addTokenHeader(request)))
    );
  }
  private addTokenHeader(request: HttpRequest<any>) {
    const authToken = this.authService.getToken();
    const username = localStorage.getItem('username');
      
    if (authToken && username) {
      return request = request.clone({
        setHeaders: {
          'Authorization': `Bearer ${authToken}`,
          'OAM_REMOTE_USER': username,
          'rejectUnauthorized': 'false'
        }
      })
    } else {
      return request;
    }
  }
}
  • Related