dvbooking/admin/src/app/auth/jwt.interceptor.ts
Roland Schneider f1f2fefdab logout works
2025-11-14 17:20:13 +01:00

85 lines
2.6 KiB
TypeScript

import { Injectable } from '@angular/core';
import {
HttpEvent,
HttpHandler,
HttpInterceptor,
HttpRequest,
HttpErrorResponse,
} from '@angular/common/http';
import { Observable, throwError, BehaviorSubject } from 'rxjs';
import { catchError, switchMap, filter, take, finalize } from 'rxjs/operators'; // Import finalize
import { AuthService } from './auth.service';
@Injectable()
export class JwtInterceptor implements HttpInterceptor {
private isRefreshing = false;
// Initialize refreshTokenSubject with null
private refreshTokenSubject: BehaviorSubject<any> = new BehaviorSubject<any>(null);
constructor(private authService: AuthService) {}
intercept(
request: HttpRequest<any>,
next: HttpHandler
): Observable<HttpEvent<any>> {
if (request.url.includes('/auth/refresh')) {
return next.handle(request);
}
const accessToken = this.authService.getAccessToken();
if (accessToken) {
request = this.addToken(request, accessToken);
}
return next.handle(request).pipe(
catchError((error) => {
if (error instanceof HttpErrorResponse && error.status === 401) {
return this.handle401Error(request, next);
}
return throwError(() => error);
})
);
}
private handle401Error(request: HttpRequest<any>, next: HttpHandler): Observable<any> {
if (!this.isRefreshing) {
this.isRefreshing = true;
// Reset the refreshTokenSubject to null so that subsequent requests will wait
// this.refreshTokenSubject.next(null);
this.refreshTokenSubject = new BehaviorSubject<any>(null);
return this.authService.refreshToken().pipe(
switchMap((token: any) => {
this.refreshTokenSubject.next(token.accessToken);
return next.handle(this.addToken(request, token.accessToken));
}),
catchError((err) => {
// If refresh fails, logout the user
this.authService.clientSideLogout();
return throwError(() => err);
}),
finalize(() => {
// When the refresh attempt completes, set isRefreshing to false
this.isRefreshing = false;
})
);
} else {
// If a refresh is already in progress, wait for it to complete
return this.refreshTokenSubject.pipe(
filter(token => token != null),
take(1),
switchMap(jwt => next.handle(this.addToken(request, jwt)))
);
}
}
private addToken(request: HttpRequest<any>, token: string) {
return request.clone({
setHeaders: {
Authorization: `Bearer ${token}`,
},
});
}
}