Blog

You are here: Blog / How to Implement JWT Authentication using Asp.net Core and Angular 8 – Part 2

  • How to Implement JWT Authentication using Asp.net Core and Angular 8 – PART 2

    This part 2 is continues of PART 1 where we covered the JWT authentication API code.

    You will start by installing the all the Pre-requisition to create Angular project if you have not created you can CLICK HERE to follow the steps and create new Angular project to start with JWT Authentication.

    Before we start actual implementation, let’s briefly understand what JWT is.

    JWT stands for JSON Web Token and it's an open source standard that states how to securely exchange information between client and server.

    You can install JWT Authentication in your Angular 8 application and where you can use like sessions and cookies.

    Before we start JWT Authentication we require to install the below package.

    npm install @auth0/angular-jwt

    In this Post we will cover following topics.

    • Step 1: Login Component
    • Step 2: Storing JWT token to client-Side and it used
    • Step 3: Sending JWT token on each API request.
    • Step 4: Validating each request on client-side


    Step 1: Login Component

    We require to create new component for login and below is code for HTML and Typescript code.

    Add below code in login.component.html

     
    <form (ngSubmit)="onLogin()" [formGroup]="loginForm" novalidate>
      <div class="form-width">
        <div class="form-label">
          <span>Email</span>
        </div>
        <div  class="form-control">
          <input type="email" formControlName="email" placeholder="Email" required  spellcheck="false"
          autocapitalize="off" name="email" autocomplete="off"><br/>
          <div class="validationError"  *ngIf="isSubmitted && formControls.email.errors">
            <div *ngIf="formControls.email.errors.required">Email is required</div>
          </div>
        </div>
         <div  class="form-label">
            <span>Password</span>
          </div>
          <div  class="form-control">
            <input type="password" formControlName="password" placeholder="Password" required autocomplete="off"><br/>
            <div class="validationError" *ngIf="isSubmitted && formControls.password.errors">
               <div *ngIf="formControls.password.errors.required">Password is required</div>
            </div>
          </div>
          <div class="submit-button">
              <button color="primary" type="submit">
                  Login
                </button>
          </div>
        </div>
        <div class="errorMessage">
          {{errorMessage}}
        </div>
    </form>
    

    Add below code in login.component.ts file

     
    import { Component, EventEmitter, OnInit, Output } from '@angular/core';
    import { Router } from '@angular/router';
    import { FormBuilder, FormGroup, Validators } from '@angular/forms';
    import { HttpClient, HttpHeaders } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import 'rxjs';
    import { Observable } from 'rxjs';
    
     
    @Component({
      selector: 'app-login',
      templateUrl: './login.component.html',
      styleUrls: ['./login.component.scss']
    })
    export class LoginComponent implements OnInit {
      errorMessage = '';
      loginForm: FormGroup;
      isSubmitted = false;
     
      @Output() loggedIn: EventEmitter = new EventEmitter();
      @Output() logInFailure: EventEmitter = new EventEmitter();
     
      constructor(
        private router: Router,
        private formBuilder: FormBuilder
      ) {
        this.loginForm = this.formBuilder.group({
          email: ['', Validators.required],
          password: ['', Validators.required]
        });
      }
      ngOnInit(): void { 
      }
     
      get formControls(): any {
        return this.loginForm.controls;
      }
     
      onLogin(): void {
        this.isSubmitted = true;
        if (this.loginForm.invalid) {
          return;
        }
        const httpOptions = {
            headers: new HttpHeaders({
              'Content-Type':  'application/json'
            })
          };
        const loginModel = {
          this.loginForm.value.email,
          this.loginForm.value.password
        };
    
        this.http.post(‘api/login’, loginModel, httpOptions) 
        .subscribe(
          (data: any) => {
            if (data.success) {
        localStorage.setItem('LoggedInUser', JSON.stringify(data));
              this.router.navigate(['/home]);
            } else {
              this.errorMessage = data.errorMessage;
              this.logInFailure.emit(true);
            }
          },
          (error: any) => {
           this.errorMessage = 'API is unreachable. Please check your internet connection.';
           this.logInFailure.emit(true);
          }
        );
      }
    }
    
    

    Step 2: Storing JWT token to client-Side and it used

    Add below code in login.component.ts file

     
    ….
        this.http.post(‘api/login’, loginModel, httpOptions) 
        .subscribe(
          (data: any) => {
            if (data.success) {
        localStorage.setItem('LoggedInUser', JSON.stringify(data));
              localStorage.setItem(‘token’, data.access_token); 
              this.router.navigate(['/home]);
            } else {
              this.errorMessage = data.errorMessage;
              this.logInFailure.emit(true);
            }
          },
          (error: any) => {
           this.errorMessage = 'API is unreachable. Please check your internet connection.';
           this.logInFailure.emit(true);
          }
        );
    
    ….
    

    Step 3: Sending JWT token on each API request.

    To sending each request to JWT token while call API need to override the http request and for that require to create http Interceptor.

    Add below code in toke.interceptor.ts

    
    import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
    import { Injectable } from '@angular/core';
    import { Observable } from 'rxjs';
    import { AuthenticationService } from '../services/authentication.service';
     
    @Injectable()
    export class TokenInterceptor implements HttpInterceptor {
       constructor(public authenticationService: AuthenticationService) {
     
       }
       intercept(request: HttpRequest, newRequest: HttpHandler): Observable> {
          const authtoken = this.authenticationService.authenticationToken.value;
          if (authtoken !== '') {
            request = request.clone({
                setHeaders: {
                    Authorization: `Bearer ${authtoken}`
                }
            });
        }
     
          return newRequest.handle(request);
        }
    }
    
    

    Step 4: Validating each request on client-side

    To validate each request on the client side on each routing of the page require to create the common auth.gurd service and which we can add in routing module.

    Add below code in auth-guard.service.ts file.

     
    import { Injectable } from '@angular/core';
    import { CanActivate, Router } from '@angular/router';
    import { AuthenticationService } from '../services/authentication.service';
    import { JwtHelperService } from '@auth0/angular-jwt';
    import { Observable } from 'rxjs';
     
    @Injectable({
      providedIn: 'root'
    })
    export class AuthGuardService implements CanActivate {
      constructor(public authService: AuthenticationService,
                  private router: Router) {}
     
      canActivate(): Observable<boolean> |Promise<boolean> | boolean {
        const userData = this.authService.getLoggedInUserData();
        if (userData === undefined) {
          this.router.navigate(['/']);
           
          return false;
        } else {
         const token = userData.access_token;
         const helper = new JwtHelperService();
         const isExpired = helper.isTokenExpired(token);
     
         if (isExpired) {
           this.router.navigate(['/']);
     
           return false;
         }
        }
        return true;
      }
    }
    

    Add below code in app.routing.ts

    
    import { Routes, RouterModule } from '@angular/router';
    
    import { HomeComponent } from './home';
    import { LoginComponent } from './login';
    import { AuthGuard } from './AuthGuardService ;
    
    const appRoutes: Routes = [
        {
            path: '',
            component: HomeComponent,
            canActivate: [AuthGuard]
        },
        {
            path: 'login',
            component: LoginComponent
        },
    
        // otherwise redirect to home
        { path: '**', redirectTo: '' }
    ];
    
    export const routing = RouterModule.forRoot(appRoutes);
    

    I hope that this post helps with that and that you enjoyed it!