14th June 2024

Auth Guard in Angular: Implementing Authentication in Angular using Guards

Auth-Guard-In-Angular-VS-Online-img

Introduction

Authentication is a crucial part of web applications to secure resources and restrict unauthorized access. Angular provides a robust framework for implementing authentication, with Auth Guards playing a central role. This article explores how authentication is done in Angular, focusing on Auth Guards, and provides an example project to illustrate the concepts.

Understanding Angular Authentication

Angular authentication typically involves the following components:

  • Auth Service: Manages authentication logic like login, logout, and checking the authentication state.
  • Auth Guard: Protects routes by allowing access only to authenticated users.
  • Interceptor: Intercepts HTTP requests to add authentication tokens.
Setting Up the Example Project
1. Create a New Angular Project
                                
                                    
    ng new angular-auth-example
    cd angular-auth-example

                                
                            
2. Install Dependencies
                                
                                    
  npm install @angular/material @angular/cdk @angular/animations
  npm install @auth0/angular-jwt

                                
                            
Step-by-Step Implementation
1. Create Auth Service

The Auth Service will handle login, logout, and check authentication status.

                                
                                    
  // src/app/services/auth.service.ts
  import { Injectable } from '@angular/core';
  import { Router } from '@angular/router';
  import { BehaviorSubject, Observable } from 'rxjs';

  @Injectable({
    providedIn: 'root'
  })
  export class AuthService {
    private loggedIn = new BehaviorSubject<boolean>(false);

    constructor(private router: Router) { }

    login(username: string, password: string): boolean {
      if (username === 'user' && password === 'password') {
        localStorage.setItem('token', 'fake-jwt-token');
        this.loggedIn.next(true);
        return true;
      }
      return false;
    }

    logout(): void {
      localStorage.removeItem('token');
      this.loggedIn.next(false);
      this.router.navigate(['/login']);
    }

    isLoggedIn(): Observable<boolean> {
      return this.loggedIn.asObservable();
    }
  }

                                
                            
2. Create Auth Guard

The Auth Guard will protect routes by checking the user's authentication status

                                
                                    
  // src/app/guards/auth.guard.ts
  import { Injectable } from '@angular/core';
  import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router } from '@angular/router';
  import { Observable } from 'rxjs';
  import { AuthService } from '../services/auth.service';
  import { map, take } from 'rxjs/operators';

  @Injectable({
    providedIn: 'root'
  })
  export class AuthGuard implements CanActivate {

    constructor(private authService: AuthService, private router: Router) { }

    canActivate(
      route: ActivatedRouteSnapshot,
      state: RouterStateSnapshot
    ): Observable<boolean> {
      return this.authService.isLoggedIn().pipe(
        take(1),
        map((isLoggedIn: boolean) => {
          if (!isLoggedIn) {
            this.router.navigate(['/login']);
            return false;
          }
          return true;
        })
      );
    }
  }

                                
                            
3. Configure Routes

Define routes and apply the Auth Guard to protected routes.

                                
                                    
  // src/app/app-routing.module.ts
  import { NgModule } from '@angular/core';
  import { RouterModule, Routes } from '@angular/router';
  import { HomeComponent } from './components/home/home.component';
  import { LoginComponent } from './components/login/login.component';
  import { AuthGuard } from './guards/auth.guard';

  const routes: Routes = [
    { path: 'home', component: HomeComponent, canActivate: [AuthGuard] },
    { path: 'login', component: LoginComponent },
    { path: '**', redirectTo: 'login' }
  ];

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

                                
                            
4. Create Login and Home Components

Generate components and implement basic templates and logic.

                                
                                    
  ng generate component components/login
  ng generate component components/home

                                
                            
Login Component
                                
                                    
  // src/app/components/login/login.component.ts
  import { Component } from '@angular/core';
  import { Router } from '@angular/router';
  import { AuthService } from '../../services/auth.service';

  @Component({
    selector: 'app-login',
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.css']
  })
  export class LoginComponent {
    username: string;
    password: string;
    error: string;

    constructor(private authService: AuthService, private router: Router) { }

    login(): void {
      if (this.authService.login(this.username, this.password)) {
        this.router.navigate(['/home']);
      } else {
        this.error = 'Invalid credentials';
      }
    }
  }

                                
                            
Login Template
                                
                                    
  <!-- src/app/components/login/login.component.html -->
  <div>
    <h2>Login</h2>
    <form (ngSubmit)="login()">
      <label for="username">Username:</label>
      <input type="text" id="username" [(ngModel)]="username" name="username">
      <br>
      <label for="password">Password:</label>
      <input type="password" id="password" [(ngModel)]="password" name="password">
      <br>
      <button type="submit">Login</button>
      <p *ngIf="error">{{ error }}</p>
    </form>
  </div>

                                
                            
Home Component
                                
                                    
  // src/app/components/home/home.component.ts
  import { Component } from '@angular/core';
  import { AuthService } from '../../services/auth.service';

  @Component({
    selector: 'app-home',
    templateUrl: './home.component.html',
    styleUrls: ['./home.component.css']
  })
  export class HomeComponent {

    constructor(private authService: AuthService) { }

    logout(): void {
      this.authService.logout();
    }
  }

                                
                            
Home Template
                                
                                    
  <!-- src/app/components/home/home.component.html -->
  <div>
    <h2>Home</h2>
    <button (click)="logout()">Logout</button>
  </div>

                                
                            
5. Update App Module

Import necessary modules and declare components.

                                
                                    
  // src/app/app.module.ts
  import { NgModule } from '@angular/core';
  import { BrowserModule } from '@angular/platform-browser';
  import { FormsModule } from '@angular/forms';
  import { AppRoutingModule } from './app-routing.module';
  import { AppComponent } from './app.component';
  import { LoginComponent } from './components/login/login.component';
  import { HomeComponent } from './components/home/home.component';
  import { AuthService } from './services/auth.service';
  import { AuthGuard } from './guards/auth.guard';

  @NgModule({
    declarations: [
      AppComponent,
      LoginComponent,
      HomeComponent
    ],
    imports: [
      BrowserModule,
      FormsModule,
      AppRoutingModule
    ],
    providers: [AuthService, AuthGuard],
    bootstrap: [AppComponent]
  })
  export class AppModule { }

                                
                            

Conclusion

In this article, we have explored how to implement authentication in Angular using Auth Guards. We created an example project to demonstrate the key concepts, including the Auth Service, Auth Guard, and basic routing for protected and public routes. This approach provides a robust foundation for securing Angular applications and can be extended to include more advanced features like role-based access control and token-based authentication.

Let's develop your ideas into reality