2 September 2026
An Angular auth interceptor, the functional way
An Angular auth interceptor, the functional way
Most results for this still show a class implementing HttpInterceptor
with an @Injectable decorator and an entry in HTTP_INTERCEPTORS. That
works, and it is not how you would write it now. HttpInterceptorFn is a
plain function, uses inject(), and is registered in one line.
import { HttpInterceptorFn, HttpErrorResponse } from '@angular/common/http';
import { inject } from '@angular/core';
import { catchError, throwError } from 'rxjs';
import { AuthService } from './auth.service';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const auth = inject(AuthService);
const token = auth.token();
// Never attach the token to a third-party URL. An interceptor sees
// EVERY outgoing request, and this is how credentials end up in
// somebody else's logs.
const sameOrigin = req.url.startsWith('/') || req.url.startsWith(location.origin);
const request = token && sameOrigin
? req.clone({ setHeaders: { Authorization: `Bearer ${token}` } })
: req;
return next(request).pipe(
catchError((error: HttpErrorResponse) => {
if (error.status === 401) {
auth.signOut();
}
return throwError(() => error);
}),
);
};
Registering it:
import { provideHttpClient, withInterceptors } from '@angular/common/http';
bootstrapApplication(AppComponent, {
providers: [
provideHttpClient(withInterceptors([authInterceptor])),
],
});
Three things worth knowing
HttpRequest is immutable. req.headers.set(...) returns a new
headers object and changes nothing about the request. req.clone() is the
only way to alter one, and forgetting it produces an interceptor that runs
correctly and does nothing.
Check the origin before attaching a token. An interceptor sees every request the app makes, including ones to third-party APIs. Without the guard above, your bearer token goes to whoever you call.
Order matters and it is the array order. Interceptors run in the order
listed in withInterceptors, outermost first, and unwind in reverse on
the way back. Put logging first if you want it to see what the others did.