Angular19 min read
JWT Authentication in Angular (Guard + Interceptor Pattern)
Put together the standard real-world auth flow: login, store token, intercept API calls, protect routes.
Ryan Hughes
September 9, 2025
10.4k275
A standard Angular JWT setup has 3 parts:
1) Auth service (login + token storage)
2) HTTP interceptor (attach token)
3) Route guard (block protected pages)
## 1) Auth service
```ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { tap } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class AuthService {
constructor(private http: HttpClient) {}
login(email: string, password: string) {
return this.http.post<{ token: string }>('/api/login', { email, password }).pipe(
tap(res => localStorage.setItem('token', res.token))
);
}
logout() {
localStorage.removeItem('token');
}
get token() {
return localStorage.getItem('token');
}
get isLoggedIn() {
return !!this.token;
}
}
```
## 2) Interceptor (attach token)
```ts
import { HttpInterceptorFn } from '@angular/common/http';
import { inject } from '@angular/core';
import { AuthService } from './auth.service';
export const authInterceptor: HttpInterceptorFn = (req, next) => {
const auth = inject(AuthService);
const token = auth.token;
if (!token) return next(req);
return next(
req.clone({
setHeaders: { Authorization: `Bearer ${token}` },
})
);
};
```
## 3) Guard (protect routes)
```ts
import { CanActivateFn, Router } from '@angular/router';
import { inject } from '@angular/core';
import { AuthService } from './auth.service';
export const authGuard: CanActivateFn = () => {
const auth = inject(AuthService);
const router = inject(Router);
if (auth.isLoggedIn) return true;
router.navigate(['/login']);
return false;
};
```
## Visual: request flow
```mermaid
flowchart LR
UI[Component] --> API[HttpClient Request]
API --> INT[Interceptor adds token]
INT --> BE[Backend]
BE --> INT
INT --> UI
```
> Next: Token refresh and handling 401 responses gracefully.
#Angular#Security#Architecture#Advanced