fix jwt handler to return proper error codes

This commit is contained in:
Krrish Ghimire
2026-07-01 10:25:37 +05:45
parent 77b32b4d32
commit 18fed113f9
2 changed files with 83 additions and 5 deletions

View File

@@ -1,11 +1,21 @@
import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Injectable, inject } from '@angular/core';
import {
HttpInterceptor,
HttpRequest,
HttpHandler,
HttpEvent,
HttpErrorResponse,
} from '@angular/common/http';
import { BehaviorSubject, Observable, catchError, filter, switchMap, take, throwError } from 'rxjs';
import { AuthService } from '../services/auth.service';
import { Router } from '@angular/router';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {}
private authService = inject(AuthService);
private router = inject(Router);
private isRefreshing = false;
private refreshTokenSubject = new BehaviorSubject<string | null>(null);
intercept(req: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
const token = this.authService.getAccessToken();
@@ -14,6 +24,65 @@ export class JwtInterceptor implements HttpInterceptor {
setHeaders: { Authorization: `Bearer ${token}` },
});
}
return next.handle(req);
return next.handle(req).pipe(
catchError((error) => {
if (
error instanceof HttpErrorResponse &&
error.status === 401 &&
!req.url.includes('/api/auth/refresh')
) {
return this.handle401Error(req, next);
}
return throwError(() => error);
}),
);
}
private handle401Error(
req: HttpRequest<unknown>,
next: HttpHandler,
): Observable<HttpEvent<unknown>> {
if (!this.isRefreshing) {
this.isRefreshing = true;
this.refreshTokenSubject.next(null);
const refreshToken = this.authService.getRefreshToken();
if (!refreshToken) {
this.authService.clearSessionForLogout();
this.router.navigate(['/login']);
return throwError(() => new Error('No refresh token available'));
}
return this.authService.refreshToken(refreshToken).pipe(
switchMap((res) => {
this.isRefreshing = false;
this.refreshTokenSubject.next(res.accessToken);
return next.handle(
req.clone({
setHeaders: { Authorization: `Bearer ${res.accessToken}` },
}),
);
}),
catchError((err) => {
this.isRefreshing = false;
this.authService.clearSessionForLogout();
this.router.navigate(['/login']);
return throwError(() => err);
}),
);
} else {
return this.refreshTokenSubject.pipe(
filter((token): token is string => token !== null),
take(1),
switchMap((token) =>
next.handle(
req.clone({
setHeaders: { Authorization: `Bearer ${token}` },
}),
),
),
);
}
}
}