Angular: route authentication with functional guards

Angular is a robust framework for developing web applications, and one of the key features is route management. Implementing an effective authentication system is essential to protect the sensitive resources of our applications. Functional guards are a powerful tool in Angular to achieve this, allowing you to control access to routes dynamically.

What is a functional guard?

A functional guard in Angular is a function that can be used to control access to a route. When a route is protected by a functional guard, the guard function is called before the route is activated. If the guard returns true, navigation continues as expected; otherwise, if it returns false, navigation is blocked.

Implementing authentication with functional guards

Start by creating an authentication service that handles the authentication logic. This service should contain methods for logging in, logging out, and checking authentication status.


// auth.service.ts

import { Injectable } from '@angular/core';

@Injectable({
   providedIn: 'root',
})
export class AuthService {
   private isAuthenticated: boolean = false;

   login(username: string, password: string): boolean {
     // Implement authentication logic here
     // Return true if authentication succeeds, false otherwise
     // For example, you could make a call to a backend to verify credentials
     this.isAuthenticated = true;
     return this.isAuthenticated;
   }

   logout(): void {
     this.isAuthenticated = false;
   }

   isAuthenticatedUser(): boolean {
     return this.isAuthenticated;
   }
}

Now, create a functional guard that uses the authentication service to control access to routes.


// auth.guard.ts

import { CanActivateFn } from '@angular/router';
import { AuthService } from '../services/auth.service';
import { inject } from "@angular/core";

export const authGuard: CanActivateFn = (route, state) => {
   const auth = inject(AuthService);
   if(!auth.isAuthenticatedUser()) {
     return false;
   }
   return true;
};

In order to use the authentication service within the function, we must use the core inject() function to perform dependency injection outside a class.

Now that you have created the functional guard, you can apply it to the routes you want to protect.


// app-routing.module.ts

import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { ProfileComponent } from './profile/profile.component';
import { LoginComponent } from './login/login.component';
import { authGuard } from './auth.guard';

const routes: Routes = [
   { path: 'profile', component: ProfileComponent, canActivate: [authGuard] },
   { path: 'login', component: LoginComponent },
   // More routes...
   { path: '', redirectTo: '/', pathMatch: 'full' },
];

@NgModule({
   imports: [RouterModule.forRoot(routes)],
   exports: [RouterModule],
})
export class AppRoutingModule {}

With these steps, you have implemented authentication on routes in Angular using functional guards. Protected routes will only be accessible to authenticated users, and navigation will be managed securely by the functional guard system.

Back to top