New Interceptors from Angular 17, local use of a BehaviorSubject does not work

Discussão em 'Angular' iniciado por alegeomx, Outubro 16, 2024.

  1. alegeomx

    alegeomx Guest

    In the new definition of interceptors in Angular 17, the local use of a BehaviorSubject does not work.

    I have an interceptor that seeks to fulfill the use case of the refreshToken by seeking to generate a queue of the http requests while the refreshToken process is being processed.

    For this I use a BehaviorSubject locally that can update the value of the response of the refreshToken process and then through the Observable process the pending requests.

    However, this BehaviorSubject never updates or emits the next value and the queue is not processed with the update of the pending requests with the new access token.

    export const RequestHeadersInterceptor: HttpInterceptorFn = (request, next) => {

    const logger: NGXLogger = inject(NGXLogger);
    const refreshTokenManageService: RefreshTokenManageService = inject(RefreshTokenManageService);
    const authService: AuthService = inject(AuthService);
    const notificationService: NotificationService = inject(NotificationService);
    const router: Router = inject(Router);

    refreshTokenManageService.isRefreshing = false;

    if (request.url === URL_AUTH_LOGIN) {
    return next(request);
    }

    if (request.url === URL_AUTH_REFRESH_TOKEN) {
    const requestClone = refreshTokenManageService.addTokenHeader(request);
    return next(requestClone);
    }

    if (refreshTokenManageService.isRefreshing) {
    return EMPTY;
    }

    const usuarioDataStorage = refreshTokenManageService.getUsuarioDataStorage();

    if (!usuarioDataStorage || !usuarioDataStorage.accessToken) {
    router.navigateByUrl('/').then();
    return EMPTY;
    }
    const requestAuthClone = refreshTokenManageService.addTokenHeader(request);
    const requestContentTypeClone = refreshTokenManageService.addContentTypeHeader(requestAuthClone);

    const refreshTokenSubject: BehaviorSubject<RefreshTokenResponse> = new BehaviorSubject<RefreshTokenResponse>({
    accessToken: '', refreshToken: ''
    });

    return next(requestContentTypeClone).pipe(
    catchError((requestError: HttpErrorResponse) => {
    if (requestError && requestError.status === HttpStatusCode.Unauthorized) {
    if (!refreshTokenManageService.isRefreshing) {
    refreshTokenManageService.isRefreshing = true;
    refreshTokenSubject.next({
    accessToken: '', refreshToken: ''
    });

    return authService.refreshToken().pipe(
    switchMap((refreshTokenResponse: RefreshTokenResponse) => {
    refreshTokenManageService.isRefreshing = false;
    refreshTokenSubject.next(refreshTokenResponse);
    refreshTokenManageService.updateTokens(refreshTokenResponse.accessToken, refreshTokenResponse.refreshToken);

    const requestBearerClone = refreshTokenManageService.addTokenHeader(request);
    const requestContentTypeClone = refreshTokenManageService.addContentTypeHeader(requestBearerClone);
    return next(requestContentTypeClone);
    }),
    catchError((error: HttpErrorResponse) => {
    refreshTokenManageService.isRefreshing = false;
    const authenticationError: AuthenticationError = new AuthenticationError(error.error.message);
    router.navigateByUrl('/').then();
    throw authenticationError;
    }),
    )
    } else {
    return refreshTokenSubject.pipe(
    filter((result: RefreshTokenResponse) => {
    return result.accessToken !== ''
    }),
    take(1),
    switchMap(() => {
    const requestBearerClone = refreshTokenManageService.addTokenHeader(request);
    const requestContentTypeClone = refreshTokenManageService.addContentTypeHeader(requestBearerClone);
    return next(requestContentTypeClone)
    })
    );
    }
    } else {
    return throwError(() => {
    const serverError: ServerError = new ServerError('Por el momento el servicio no se encuentra disponible. Favor de intentar más tarde.')
    throw serverError;
    });
    }
    })
    );
    }


    I would expect the BehaviorSubject to emit the new value of the access token with which the filter is activated, the headers to be updated and the requests that are made while the refreshToken process is taking place to be processed.

    Continue reading...

Compartilhe esta Página