May 25, 2025

Securing Angular Apps with Route Guards and JWT Auth

Learn how to secure your Angular applications using route guards and JWT authentication. This article guides you through implementing authentication services, protecting routes, and attaching JWTs to API requests to ensure only authorized users can access sensitive areas of your app.

Route guards and JWT authentication allow you to secure Angular applications by controlling access to routes and verifying user identity. This combo ensures only authorized users can view sensitive parts of your app. Let’s dive into how you can implement this in Angular!


🛡️ Why Use JWT and Route Guards?

Securing your Angular app is crucial when it deals with user-specific content, administrative controls, or any protected data. Two core strategies to accomplish this are:

  • JWT (JSON Web Tokens) for stateless authentication.
  • Route guards to prevent unauthorized access to specific routes.

What is a JWT?

A JSON Web Token is a compact, URL-safe way to represent claims between two parties. When a user logs in, your backend generates a JWT and sends it to the client. The client then includes this token in subsequent requests, proving their identity.

Why Route Guards?

Route guards are Angular services that can block or allow navigation to routes based on conditions—such as whether a user is logged in. This means users without a valid JWT won’t even be able to reach the page (e.g., dashboard, admin, profile).

Together, JWT and route guards provide both identity verification and access control in the frontend.


🔧 Setting Up JWT Authentication in Angular

Start by creating an AuthService to manage the login state and store the JWT in localStorage.

import { Injectable } from '@angular/core'; @Injectable({ providedIn: 'root' }) export class AuthService { private readonly TOKEN_KEY = 'jwt_token'; login(token: string): void { localStorage.setItem(this.TOKEN_KEY, token); } logout(): void { localStorage.removeItem(this.TOKEN_KEY); } getToken(): string | null { return localStorage.getItem(this.TOKEN_KEY); } isAuthenticated(): boolean { // Optionally add token expiration check here return !!this.getToken(); } }

💡 Tip: For added security, consider using JWT expiration times and checking if the token is still valid using libraries like jwt-decode.


🚦 Creating an Auth Guard to Protect Routes

Now, let’s build a route guard (AuthGuard) that uses the AuthService to check login status.

import { Injectable } from '@angular/core'; import { CanActivate, Router } from '@angular/router'; import { AuthService } from './auth.service'; @Injectable({ providedIn: 'root' }) export class AuthGuard implements CanActivate { constructor(private auth: AuthService, private router: Router) {} canActivate(): boolean { if (this.auth.isAuthenticated()) { return true; } else { this.router.navigate(['/login']); return false; } } }

If the user is not authenticated, they’ll be redirected to the login page.


📍 Applying Guards to Your Routes

To protect a route, attach the AuthGuard to the route configuration in your AppRoutingModule.

import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { AuthGuard } from './auth.guard'; import { DashboardComponent } from './dashboard/dashboard.component'; import { LoginComponent } from './login/login.component'; const routes: Routes = [ { path: 'login', component: LoginComponent }, { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }, { path: '**', redirectTo: 'login' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule {}

Now, only users with a valid JWT token can access the dashboard route.


🔄 Attaching JWT to HTTP Requests

To authenticate API requests, add a JWT interceptor that appends the token to HTTP headers.

import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http'; import { Observable } from 'rxjs'; import { AuthService } from './auth.service'; @Injectable() export class JwtInterceptor implements HttpInterceptor { constructor(private auth: AuthService) {} intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> { const token = this.auth.getToken(); if (token) { const cloned = req.clone({ setHeaders: { Authorization: `Bearer ${token}` } }); return next.handle(cloned); } return next.handle(req); } }

Don’t forget to register the interceptor in your AppModule:

import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { JwtInterceptor } from './jwt.interceptor'; @NgModule({ // ... providers: [ { provide: HTTP_INTERCEPTORS, useClass: JwtInterceptor, multi: true } ] }) export class AppModule {}

✅ Final Thoughts

By combining JWT authentication and route guards, you significantly enhance the security of your Angular app:

  • 🧠 JWTs allow stateless user sessions.
  • 🛑 Route guards protect routes from unauthorized access.
  • 🔒 HTTP interceptors secure API communication.