Files
listify/listify-client/src/app/auth/auth.interceptor.ts
Bastian Wagner e1cc78ca27 collab
2026-06-10 15:44:18 +02:00

78 lines
2.0 KiB
TypeScript

import {
HttpErrorResponse,
HttpEvent,
HttpHandlerFn,
HttpInterceptorFn,
HttpRequest,
} from '@angular/common/http';
import { inject } from '@angular/core';
import { Router } from '@angular/router';
import { Observable, catchError, switchMap, throwError } from 'rxjs';
import { AuthService } from './auth.service';
export const authInterceptor: HttpInterceptorFn = (
request: HttpRequest<unknown>,
next: HttpHandlerFn,
): Observable<HttpEvent<unknown>> => {
const auth = inject(AuthService);
const router = inject(Router);
const authenticatedRequest = withAccessToken(request, auth.accessToken());
return next(authenticatedRequest).pipe(
catchError((error: unknown) => {
if (!shouldRefresh(request, error)) {
return throwError(() => error);
}
return auth.refreshSession().pipe(
switchMap((response) =>
next(withAccessToken(request, response.accessToken)),
),
catchError((refreshError: unknown) => {
auth.logout();
void router.navigateByUrl('/login');
return throwError(() => refreshError);
}),
);
}),
);
};
function withAccessToken(
request: HttpRequest<unknown>,
accessToken: string | null,
): HttpRequest<unknown> {
if (!accessToken || !isApiRequest(request) || isAuthRequest(request)) {
return request;
}
return request.clone({
setHeaders: {
Authorization: `Bearer ${accessToken}`,
},
});
}
function shouldRefresh(request: HttpRequest<unknown>, error: unknown): boolean {
return (
isApiRequest(request) &&
!isAuthRequest(request) &&
error instanceof HttpErrorResponse &&
error.status === 401
);
}
function isApiRequest(request: HttpRequest<unknown>): boolean {
return request.url.startsWith('/api/');
}
function isAuthRequest(request: HttpRequest<unknown>): boolean {
return [
'/api/auth/login',
'/api/auth/register',
'/api/auth/refresh',
'/api/auth/resend-verification',
'/api/auth/verify-email',
].some((publicAuthUrl) => request.url.startsWith(publicAuthUrl));
}