The Problem

An HTTP interceptor is supposed to add an Authorization header to every request, but the header is missing from the actual network requests. Authentication fails with 401 errors.

Symptoms

  • API returns 401 Unauthorized on every request
  • Network tab shows no Authorization header
  • Interceptor code looks correct but header never appears
  • Works for some requests but not others
  • Token is valid in localStorage but not sent

Real Error Scenario

```typescript // auth.interceptor.ts @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const token = localStorage.getItem('token');

// WRONG: This modifies the original request (immutable!) req.headers.set('Authorization', Bearer ${token});

return next.handle(req); // Sent WITHOUT the header } } ```

HttpRequest is immutable. req.headers.set() returns a NEW headers object but does not modify the original.

How to Fix It

Fix 1: Clone the Request with New Headers

```typescript @Injectable() export class AuthInterceptor implements HttpInterceptor { intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const token = localStorage.getItem('token');

if (token) { const authReq = req.clone({ headers: req.headers.set('Authorization', Bearer ${token}) }); return next.handle(authReq); }

return next.handle(req); } } ```

Fix 2: Register the Interceptor in Providers

```typescript // app.module.ts (NgModule) @NgModule({ providers: [ { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ] }) export class AppModule {}

// Or in app.config.ts (standalone, Angular 14+) export const appConfig: ApplicationConfig = { providers: [ provideHttpClient(withInterceptorsFromDi()), { provide: HTTP_INTERCEPTORS, useClass: AuthInterceptor, multi: true } ] }; ```

Fix 3: Skip Interceptor for Certain URLs

```typescript intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const skipUrls = ['/api/public', '/assets']; if (skipUrls.some(url => req.url.includes(url))) { return next.handle(req); }

const token = localStorage.getItem('token'); const authReq = req.clone({ headers: req.headers.set('Authorization', Bearer ${token}) }); return next.handle(authReq); } ```

Fix 4: Handle Token Refresh

typescript
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
  return this.authService.getToken().pipe(
    switchMap(token => {
      if (!token) return next.handle(req);
      const authReq = req.clone({
        headers: req.headers.set('Authorization', `Bearer ${token}`)
      });
      return next.handle(authReq);
    })
  );
}