Introduction

Route Guards in Angular are used to control access to routes based on certain conditions. They are essential for implementing authentication and authorization in your Angular applications. Route Guards can prevent users from navigating to certain routes or redirect them to other routes based on specific criteria.

Types of Route Guards

Angular provides several types of route guards:

  1. CanActivate: Determines if a route can be activated.
  2. CanActivateChild: Determines if a child route can be activated.
  3. CanDeactivate: Determines if a route can be deactivated.
  4. CanLoad: Determines if a module can be loaded.
  5. Resolve: Pre-fetches data before activating a route.

Implementing CanActivate Guard

Step-by-Step Guide

  1. Create a Guard Service: Use Angular CLI to generate a guard service.

    ng generate guard auth
    
  2. Implement CanActivate Interface: Modify the generated guard service to implement the CanActivate interface.

    import { Injectable } from '@angular/core';
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree } from '@angular/router';
    import { Observable } from 'rxjs';
    import { AuthService } from './auth.service'; // Assume you have an AuthService
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthGuard implements CanActivate {
    
      constructor(private authService: AuthService) {}
    
      canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        return this.authService.isLoggedIn(); // Replace with your actual authentication logic
      }
    }
    
  3. Update Routing Module: Apply the guard to the routes in your routing module.

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

Example: AuthService

Here is a simple example of an AuthService that the guard might use.

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

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

  constructor() { }

  isLoggedIn(): boolean {
    return this.loggedIn;
  }

  login(): void {
    this.loggedIn = true;
  }

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

Practical Exercise

Task

  1. Create a new Angular project.
  2. Implement an AuthGuard that prevents access to a DashboardComponent unless the user is logged in.
  3. Create a simple AuthService to manage login state.
  4. Add routes for LoginComponent and DashboardComponent.
  5. Apply the AuthGuard to the DashboardComponent route.

Solution

  1. Create a new Angular project:

    ng new route-guards-demo
    cd route-guards-demo
    
  2. Generate Components and Guard:

    ng generate component login
    ng generate component dashboard
    ng generate guard auth
    
  3. Implement AuthService:

    // src/app/auth.service.ts
    import { Injectable } from '@angular/core';
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthService {
      private loggedIn = false;
    
      isLoggedIn(): boolean {
        return this.loggedIn;
      }
    
      login(): void {
        this.loggedIn = true;
      }
    
      logout(): void {
        this.loggedIn = false;
      }
    }
    
  4. Implement AuthGuard:

    // src/app/auth.guard.ts
    import { Injectable } from '@angular/core';
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, UrlTree, Router } from '@angular/router';
    import { Observable } from 'rxjs';
    import { AuthService } from './auth.service';
    
    @Injectable({
      providedIn: 'root'
    })
    export class AuthGuard implements CanActivate {
    
      constructor(private authService: AuthService, private router: Router) {}
    
      canActivate(
        next: ActivatedRouteSnapshot,
        state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
        if (this.authService.isLoggedIn()) {
          return true;
        } else {
          this.router.navigate(['/login']);
          return false;
        }
      }
    }
    
  5. Update Routing Module:

    // src/app/app-routing.module.ts
    import { NgModule } from '@angular/core';
    import { RouterModule, Routes } from '@angular/router';
    import { LoginComponent } from './login/login.component';
    import { DashboardComponent } from './dashboard/dashboard.component';
    import { AuthGuard } from './auth.guard';
    
    const routes: Routes = [
      { path: 'login', component: LoginComponent },
      { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] },
      { path: '', redirectTo: '/login', pathMatch: 'full' }
    ];
    
    @NgModule({
      imports: [RouterModule.forRoot(routes)],
      exports: [RouterModule]
    })
    export class AppRoutingModule { }
    
  6. Add Login Logic:

    // src/app/login/login.component.ts
    import { Component } from '@angular/core';
    import { Router } from '@angular/router';
    import { AuthService } from '../auth.service';
    
    @Component({
      selector: 'app-login',
      templateUrl: './login.component.html',
      styleUrls: ['./login.component.css']
    })
    export class LoginComponent {
    
      constructor(private authService: AuthService, private router: Router) { }
    
      login() {
        this.authService.login();
        this.router.navigate(['/dashboard']);
      }
    }
    
    <!-- src/app/login/login.component.html -->
    <button (click)="login()">Login</button>
    

Conclusion

Route Guards are a powerful feature in Angular that help you control access to different parts of your application. By implementing guards like CanActivate, you can ensure that only authenticated users can access certain routes, enhancing the security and user experience of your application. In this section, you learned how to create and apply a simple AuthGuard to protect routes in your Angular application.

© Copyright 2024. All rights reserved