frontend: Update HTTP interceptor to contemplate all possible cases when refreshing access/participant tokens

This commit is contained in:
juancarmore 2025-03-21 01:44:11 +01:00
parent 59320f517d
commit 13618af109

View File

@ -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<unknown>, 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<HttpEvent<unknown>> => {
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);
}
}