import { Injectable, Injector } from '@angular/core'; import {HttpRequest,HttpHandler,HttpEvent,HttpInterceptor,HttpErrorResponse} from '@angular/common/http'; import { BehaviorSubject, Observable, throwError } from 'rxjs'; import { AuthService } from '../../services/auth.service'; import { catchError, filter, switchMap, take, timeout } from 'rxjs/operators'; import { MiscService } from '../services/misc.service'; import { ServerException } from '../../services/app.server.response'; import { ErrorMessages } from '../../utils/enums'; @Injectable() export class AuthInterceptor implements HttpInterceptor { private isRefreshing = false; token: any; private refreshTokenSubject: BehaviorSubject = new BehaviorSubject(null); private logoutChannel = new BroadcastChannel('logout_channel'); constructor(private injector: Injector,private authService:AuthService) {} intercept(request: HttpRequest, handler: HttpHandler): Observable> { this.logoutChannel.onmessage = async (event) => { if (event.data === 'logout') { localStorage.clear(); window.location.href = '/#/auth'; } }; if (this.authService.getToken()) { request = this.addToken(request, this.authService.getToken()); } return handler.handle(request).pipe(catchError(error => { if (error instanceof HttpErrorResponse && error.status === 401) { return this.handleAuthError(request, handler); } else { this.handleServerError(error); return throwError(error); } }))as Observable>; } private handleAuthError(request: HttpRequest, handler: HttpHandler) { if (!this.isRefreshing) { this.isRefreshing = true; this.refreshTokenSubject.next(null); let authService: AuthService = this.injector.get(AuthService); return authService.refreshToken().pipe( switchMap((response: any) => { this.isRefreshing = false; this.refreshTokenSubject.next(response.token); return handler.handle(this.addToken(request, response.token)).pipe(catchError(error => { this.handleServerError(error); return throwError(error); })); })); } else { return this.refreshTokenSubject.pipe( filter(token => token != null), take(1), switchMap(token => { return handler.handle(this.addToken(request, token)); })); } } private handleServerError(error: HttpErrorResponse) { let url: string = error.url as string; let moduleName: string = ""; if (url != null && url != undefined) { moduleName = url.split(':').length > 2 ? url.split(':')[2].split('/')[1] : url.split('/')[3]; } let authService: AuthService = this.injector.get(AuthService); let miscService: MiscService = this.injector.get(MiscService); switch (error.status) { case 400: let errorResponse: ServerException = error as ServerException; if (errorResponse.error && errorResponse.error.errorCode != null) { errorResponse.error.arguments.forEach((argument, index) => { if (miscService.getErrorMessageTranslation(argument) != argument) { errorResponse.error.arguments[index] = miscService.getErrorMessageTranslation(argument); } }); miscService.handleError(errorResponse.error.errorCode); } else { miscService.handleError(ErrorMessages.BAD_REQUEST, [moduleName.toUpperCase()]); } break; case 401: miscService.handleError(ErrorMessages.UNAUTHORIZED_REQUEST,[error.error.message]); authService.logout(); break; case 403: miscService.handleError(ErrorMessages.FORBIDDEN_REQUEST,[]); authService.logout(); break; case 500: miscService.handleError(ErrorMessages.INTERNAL_SERVER_ERROR,[]); break; case 0: miscService.handleError(ErrorMessages.CONNECTION_ERROR,[]); break; } } private addToken(request: HttpRequest, token: string) { return request.clone({ setHeaders: { 'Authorization': `Bearer ${token}` } }); } }