meals-made-easy-app/src/app/interceptor/auth.interceptor.ts

51 lines
2.1 KiB
TypeScript

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);
}
};