diff --git a/frontend/projects/shared-meet-components/src/lib/interceptors/http.interceptor.ts b/frontend/projects/shared-meet-components/src/lib/interceptors/http.interceptor.ts index 7380f3c..b1e8488 100644 --- a/frontend/projects/shared-meet-components/src/lib/interceptors/http.interceptor.ts +++ b/frontend/projects/shared-meet-components/src/lib/interceptors/http.interceptor.ts @@ -1,5 +1,5 @@ -import { HttpErrorResponse, HttpHandlerFn, HttpInterceptorFn, HttpRequest } from '@angular/common/http'; -import { catchError, from, switchMap } from 'rxjs'; +import { HttpErrorResponse, HttpEvent, HttpHandlerFn, HttpInterceptorFn, HttpRequest } from '@angular/common/http'; +import { catchError, from, Observable, switchMap } from 'rxjs'; import { AuthService, ContextService, HttpService, SessionStorageService } from '../services'; import { inject } from '@angular/core'; import { Router } from '@angular/router'; @@ -11,50 +11,79 @@ export const httpInterceptor: HttpInterceptorFn = (req: HttpRequest, ne const sessionStorageService = inject(SessionStorageService); const httpService: HttpService = inject(HttpService); + const url = router.getCurrentNavigation()?.finalUrl?.toString() || router.url; + req = req.clone({ withCredentials: true }); + const refreshAccessToken = (firstError: HttpErrorResponse) => { + console.log('Refreshing access token...'); + return authService.refreshToken().pipe( + switchMap(() => { + console.log('Access token refreshed'); + return next(req); + }), + catchError((error: HttpErrorResponse) => { + if (error.url?.includes('/auth/refresh')) { + console.error('Error refreshing access token. Logging out...'); + const redirectTo = url.startsWith('/console') ? 'console/login' : 'login'; + authService.logout(redirectTo); + throw firstError; + } + + throw error; + }) + ); + }; + + const refreshParticipantToken = (firstError: HttpErrorResponse): Observable> => { + console.log('Refreshing participant token...'); + const roomName = contextService.getRoomName(); + const participantName = contextService.getParticipantName(); + const storedSecret = sessionStorageService.getModeratorSecret(roomName); + const secret = storedSecret || contextService.getSecret(); + + return from(httpService.refreshParticipantToken({ roomName, participantName, secret })).pipe( + switchMap((data) => { + console.log('Participant token refreshed'); + contextService.setToken(data.token); + return next(req); + }), + catchError((error: HttpErrorResponse) => { + if (error.url?.includes('/token/refresh')) { + if (error.status === 409) { + console.log('Participant token is still valid'); + // This means that the unauthorized error was due to an expired access token + // Refresh the access token and try again + return refreshAccessToken(firstError); + } + + console.error('Error refreshing participant token'); + throw firstError; + } + + throw error; + }) + ); + }; + return next(req).pipe( catchError((error: HttpErrorResponse) => { + console.log('Error with status', error.status); if (error.status === 401) { - // Expired access token - // Get current URL to determine if it's an admin or participant route - const url = router.getCurrentNavigation()?.finalUrl?.toString() || router.url; + // Error refreshing participant token + if (error.url?.includes('/token/refresh')) { + console.log('Refreshing participant token failed. Refreshing access token first...'); + // This means that first we need to refresh the access token and then the participant token + return refreshAccessToken(error); + } - if (url.startsWith('/console')) { - if (!url.includes('login')) { - console.log('Refreshing admin token...'); - return authService.adminRefresh().pipe( - switchMap(() => { - console.log('Admin token refreshed'); - return next(req); - }), - catchError(() => { - console.error('Error refreshing admin token. Logging out...'); - authService.adminLogout(); - throw error; - }) - ); - } - } else if (url.startsWith('/room')) { - console.log('Refreshing participant token...'); - const roomName = contextService.getRoomName(); - const participantName = contextService.getParticipantName(); - const storedSecret = sessionStorageService.getModeratorSecret(roomName); - const secret = storedSecret || contextService.getSecret(); - - return from(httpService.refreshParticipantToken({ roomName, participantName, secret })).pipe( - switchMap((data) => { - console.log('Participant token refreshed'); - contextService.setToken(data.token); - return next(req); - }), - catchError(() => { - console.error('Error refreshing participant token'); - throw error; - }) - ); + // Expired access/participant token + if (url.startsWith('/room')) { + return refreshParticipantToken(error); + } else if (!url.startsWith('/console/login') && !url.startsWith('/login')) { + return refreshAccessToken(error); } }