import { HttpErrorResponse, HttpInterceptorFn } from '@angular/common/http'; import { inject } from '@angular/core'; import { AuthService } from '../service/auth.service'; import { catchError, from, switchMap, throwError } from 'rxjs'; import { Router } from '@angular/router'; export const authInterceptor: HttpInterceptorFn = (req, next) => { const authService = inject(AuthService); const router = inject(Router); const token = authService.accessToken(); if (token) { // first we try with the current token return next( req.clone({ headers: req.headers.set('Authorization', `Bearer ${token}`), }), ).pipe( catchError((error: HttpErrorResponse) => { // if the request with the current token returned 401, // try refreshing, then retry the request with the new token // for this first scenario, do not retry if we are getting 401 from login or refreshing if ( error.status === 401 && !(error.url?.endsWith('auth/login') || error.url?.endsWith('auth/refresh')) ) { return authService.refresh().pipe( switchMap((loginView) => { const newToken = loginView.accessToken; return next( req.clone({ headers: req.headers.set('Authorization', `Bearer ${newToken}`), }), ); }), ); } else if (error.status === 401 && error.url?.endsWith('auth/refresh')) { // our refresh token is expired // redirect to login page return from(router.navigate(['/'])).pipe( switchMap(() => throwError(() => error)), ); } else { return throwError(() => error); } }), ); } else { return next(req); } };