angularangular-http-interceptors

How to use functional interceptor for refreshing token in Angular 17


I was using the following class-based interceptor to refresh user token:

@Injectable()
export class AuthInterceptor implements HttpInterceptor {

    constructor(private inject: Injector) {}

    intercept(request: HttpRequest < any > , next: HttpHandler): Observable < HttpEvent < any >> {
        let tokenService = this.inject.get(TokenService);

        let authReq = request;
        authReq = this.AddTokenHeader(request, tokenService.getAccessToken())

        return next.handle(authReq).pipe(
            catchError(errorData => {
                if (errorData.status == 401) {
                    return this.handleRefreshToken(request, next);
                }
                return throwError(errorData);
            })
        );
    }

    AddTokenHeader(request: HttpRequest < any > , token: any) {
        return request.clone({
            headers: request.headers.set('Authorization', 'Bearer ' + token)
        });
    }

    handleRefreshToken(request: HttpRequest < any > , next: HttpHandler) {
        let tokenService = this.inject.get(TokenService);
        let authService = this.inject.get(AuthService);
        let sessionStorageService = this.inject.get(SessionStorageService);

        var refreshTokenVM = new RefreshTokenVM();
        refreshTokenVM.UserId = tokenService.getUserId();
        refreshTokenVM.RefreshToken! = tokenService.getRefreshToken() !;

        return tokenService.refreshToken(refreshTokenVM).pipe(
            switchMap((data: any) => {
                sessionStorageService.saveData('accessToken', data.accessToken);
                sessionStorageService.saveData('refreshToken', data.refreshToken);
                return next.handle(this.AddTokenHeader(request, data.accessToken))
            }),
            catchError(errorData => {
                authService.logout();
                return throwError(errorData);
            })
        );
    }
}

In Angular 17, we have to use functional interceptor. I tried to translate above code to a functional interceptor:

export const authInterceptor: HttpInterceptorFn = (request: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> => {
  const clonedRequest = request.clone({
    setHeaders: {
      Authorization: 'Bearer ' + 'token',
    }
  });
  return next(clonedRequest).pipe(
    catchError(errorData => {
      if (errorData.status == 401) {

      }
      return throwError(() => errorData);
    })
  );
};

The problem is that I cannot inject tokenService in the interceptor function (I store token in SessionStrorage). Also, I don't know how I can integrate handleRefreshToken function in the functional interceptor. How can I solve this problem?


Solution

  • You should be able to get access to TokenService by using inject function:

    import { inject } from '@angular/core';
    
    export const authInterceptor: HttpInterceptorFn = (request: HttpRequest<unknown>, next: HttpHandlerFn): Observable<HttpEvent<unknown>> => {
      const tokenService = inject(TokenService); 
    
      const clonedRequest = request.clone({
      ...