Search code examples
angularangular-httpclientangular-httpclient-interceptors

Auth Interceptor is not firing


I have an Angular v19 project.

I have the following AuthInterceptor

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
    private isRefreshing = false;

    constructor(private authService: AuthService) {
        console.log('AuthInterceptor constructed'); // 🟢 Debugging log
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        console.log('AuthInterceptor triggered');

        let accessToken = localStorage.getItem('accessToken');
        console.log('accessToken:', accessToken);

        if (accessToken) {
            req = this.addToken(req, accessToken);
        }

        return next.handle(req).pipe(
            catchError((error: HttpErrorResponse) => {
                if (error.status === 401 && !this.isRefreshing) {
                    return this.handle401Error(req, next);
                }
                return throwError(() => error);
            })
        );
    }

    private handle401Error(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.isRefreshing = true;
        return this.authService.refreshToken().pipe(
            switchMap((response: LoginResponse) => {
                this.isRefreshing = false;
                return next.handle(this.addToken(req, response.accessToken));
            }),
            catchError(error => {
                this.isRefreshing = false;
                this.authService.logout();
                return throwError(() => error);
            })
        );
    }

    private addToken(req: HttpRequest<any>, token: string): HttpRequest<any> {
        return req.clone({
            setHeaders: {
                Authorization: `Bearer ${token}`
            }
        });
    }
}

The goal for this AuthInterceptor is to check for accessToken, if exists, append to headers before any request is made.

I have the following ApiService,

@Injectable({
  providedIn: 'root'
})
export class ApiService {
  private baseUrl = environment.apiBaseUrl;

  constructor(private http: HttpClient) { }

  get<T>(endpoint: string) {
    return this.http.get<T>(this.baseUrl + endpoint);
  }

  post<T>(endpoint: string, data: any) {
    return this.http.post<T>(this.baseUrl + endpoint, data);
  }

  put<T>(endpoint: string, data: any) {
    return this.http.put<T>(this.baseUrl + endpoint, data);
  }

  delete<T>(endpoint: string) {
    return this.http.delete<T>(this.baseUrl + endpoint);
  }
}

The AuthInterceptor is registered within app.config.ts

export const appConfig: ApplicationConfig = {
  providers: [
    provideHttpClient(),
    provideZoneChangeDetection({ eventCoalescing: true }),
    provideRouter(routes),
    importProvidersFrom(ReactiveFormsModule),
    { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } // Here!!!!
  ]
};

Within my component I call

async ngOnInit() {
    try {
      const response = await firstValueFrom(this.teamService.getTeams());
      console.log(response);
    } catch (error) {
      console.log(error);
    }
  }

Which calls my TeamsService:

 getTeams(): Observable<ApiResponse<TeamDetail>> {
    return this.apiService.get<ApiResponse<TeamDetail>>(`api/Team/all`);
  }

But no matter what I try, the AuthInterceptor isn't registered, nor is the accessToken added to the headers.. I have search the web, but keep hitting bricks walls, can someone spot what I'm doing wrong here?


Solution

  • When using auth interceptor configuration object { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } for interceptor, we have to specify withInterceptorsfromDI within provideHttpClient so that the interceptor is recognized.

    export const appConfig: ApplicationConfig = {
      providers: [
        provideHttpClient(withInterceptorsFromDi()), // <- notice!
        provideZoneChangeDetection({ eventCoalescing: true }),
        provideRouter(routes),
        importProvidersFrom(ReactiveFormsModule),
        { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } // Here!!!!
      ]
    };