At Agira, Technology Simplified, Innovation Delivered, and Empowering Business is what we are passionate about. We always strive to build solutions that boost your productivity.

, ,

Angular Security – Authentication With JSON Web Tokens (JWT)

  • By Manigandan
  • December 27, 2018
  • 892 Views

We can preferably generate the tokens based on the backend service we require for an application but basically JWT token needs to be generated in back-end server of the application. So today, let’s focus on creating angular security with help of JSON Web Tokens (JWT). Will also see how we can automate the tokens and things up so you don’t have to necessarily bother about calling the authentication file for every time.
If you’re building an application with Node.js, you can also refer how I have secured NodeJS RESTful API with JSON web token here,

How To Secure Node.js RESTful APIs With JSON Web Tokens

Now, let’s see how we can use Auth Tokens In Angular Application,

Steps To Use Auth Tokens In Angular Application Using Request Params

 

Step 1: Get an auth token

Post this to get an auth token.

Request : POST
URL  http:/domain/login
Request Params:
{
"email":"mani@gmail.com",
"password":"password"
}

 
after posting this you will get the responce data which will get you a token like this,
Response data:

{
"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJlbWFpbCI6ImFkbWluQGFkbWluLmNvbSIsInVzZXJJZCI6IjViYWJjZjY0YzU1MTg3MmIyNTk5ZjJiZiIsImlhdCI6MTU0NTU3Mzg2NywiZXhwIjoxNTQ1NTc3NDY3fQ.9rLhFZ8BpCFst9ACnzbdf-Sju4RHtDgS_sKmcAwBEn4",
"expiresIn":3600,
"user":{"userId":"5babcf64c551872b2599f2bf","role":"admin","firstname":"admin","lastname":"admin"}
}

 
 

Step 2: Login Component

Prior to everything, we need to get user input email & password to get the auth token so here we’re going to get this details using post request to the login service.

Login.component.html

<form (submit)="onLogin(loginForm)" #loginForm="ngForm" *ngIf="!isLoading">
<mat-form-field>
  <mat-icon matPrefix class="color-s2" >email</mat-icon>
  <input matInput name="email" ngModel type="email" placeholder="E-Mail" #emailInput="ngModel" required email>
  <mat-error *ngIf="emailInput.invalid">Please enter a valid email.</mat-error>
</mat-form-field>
<mat-form-field>
  <mat-icon matPrefix class="color-s2" >lock</mat-icon>
  <input type="password" name="password" ngModel matInput placeholder="Password" #passwordInput="ngModel" required>
  <mat-error *ngIf="passwordInput.invalid">Please enter a valid password.</mat-error>
</mat-form-field>
<button mat-raised-button color="accent" type="submit" *ngIf="!isLoading" class="fullwith">Sign In</button>
</form>

 

Login.component.ts

import { Component, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
 
import { AuthService } from '../auth.service';
import { Router } from '@angular/router';
 
@Component({
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  isLoading = false;
  constructor(public authService: AuthService, private router: Router) { }
  ngOnInit() {
      if (this.authService.getIsAuth()) {
          this.router.navigate(['/']);
      }
 
onLogin(form: NgForm) {
  if (form.invalid) {
      return;
  }
  this.authService.login(form.value.email, form.value.password);
}
}

 
In our case used to onLogin function to collect the user input email & password and to call the authService followed by login function.
Note: The AuthService is a service component, which is used to write a common function and to access all component. Here main purpose for call the login service and get the JWT token and am going to keep it for further request till user logout or time expires. Also explained functions for Logout, SetAuthTime, SaveAuthData, ClearAuthData

Step 3: auth.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Router } from '@angular/router';
import { Subject } from 'rxjs';
@Injectable({ providedIn: 'root' })
export class AuthService {
private isAuthenticated = false;
private token: string;
private tokenTimer: any;
private authStatusListener = new Subject<boolean>();
private apiURL = 'http://localhost/';
constructor(private http: HttpClient, private router: Router) {}
 
getToken() {
  return this.token;
}
 
getIsAuth() {
  return this.isAuthenticated;
}
 
getAuthStatusListener() {
  return this.authStatusListener.asObservable();
}
 
getusersById(userId) {
  return this.http.get(this.apiURL + '/user/' + userId);
}
getusers() {
  return this.http.get(this.apiURL + '/user/users');
}
 
login(email: string, password: string) {
  const authData: AuthData = { email: email, password: password };
  this.http
    .post<{ token: string; expiresIn: number }>(
      this.apiURL + '/user/login',
      authData
    )
    .subscribe(response => {
      const token = response.token;
      this.token = token;
      if (token) {
        const expiresInDuration = response.expiresIn;
        this.setAuthTimer(expiresInDuration);
        this.isAuthenticated = true;         
        this.authStatusListener.next(true);
        const now = new Date();
        const expirationDate = new Date(now.getTime() + expiresInDuration * 1000);
        this.saveAuthData(token, expirationDate, response['user']);
        this.router.navigate(['/']);
      }
    },
    error => {
      console.log('error',error.error.message)
    });
}
 
autoAuthUser() {
  const authInformation = this.getAuthData();
  if (!authInformation) {
    return;
  }
  const now = new Date();
  const expiresIn = authInformation.expirationDate.getTime() - now.getTime();
  if (expiresIn > 0) {
    this.token = authInformation.token;
    this.isAuthenticated = true;
    const user = JSON.parse(authInformation.user);
    this.setAuthTimer(expiresIn / 1000);
    this.authStatusListener.next(true);
  }
}
 
logout() {
  this.token = null;
  this.isAuthenticated = false;
  this.authStatusListener.next(false);
  clearTimeout(this.tokenTimer);
  this.clearAuthData();
  this.router.navigate(['/login']);
}
 
private setAuthTimer(duration: number) {
  console.log('Setting timer: ' + duration);
  this.tokenTimer = setTimeout(() => {
    this.logout();
  }, duration * 1000);
}
 
private saveAuthData(token: string, expirationDate: Date, user) {
  localStorage.setItem('token', token);
  localStorage.setItem('expiration', expirationDate.toISOString());
  localStorage.setItem('user', JSON.stringify(user));
}
 
private clearAuthData() {
  localStorage.removeItem('token');
  localStorage.removeItem('expiration');
  localStorage.removeItem('user');
}
 
private getAuthData() {
  const token = localStorage.getItem('token');
  const expirationDate = localStorage.getItem('expiration');
  const user = localStorage.getItem('user');
  if (!token || !expirationDate) {
    return;
  }
  return {
    token: token,
    expirationDate: new Date(expirationDate),
    user: user
  };
}
}

 
The following code used to request the user login params and to get the login response with help of JWT token.

login(email: string, password: string) {
  const authData: AuthData = { email: email, password: password };
  this.http
    .post<{ token: string; expiresIn: number }>(
      this.apiURL + '/user/login',
      authData
    )
    .subscribe(response => {
      const token = response.token;
      this.token = token;
      if (token) {
        const expiresInDuration = response.expiresIn;
        this.setAuthTimer(expiresInDuration);
        this.isAuthenticated = true;         
        this.authStatusListener.next(true);
        const now = new Date();
        const expirationDate = new Date(now.getTime() + expiresInDuration * 1000);
        this.saveAuthData(token, expirationDate, response['user']);
        this.router.navigate(['/']);
      }
    },
    error => {
      console.log('error',error.error.message)
    });
}

 
Store the response JTW token to local storage.

localStorage.setItem('token', token);
localStorage.setItem('expiration', expirationDate.toISOString());

 
Now its time to know how to get the JWT token and will also see how we can store it in local storage so we can access it later whenever you want. Eventually, you can do this using Interceptor but in our case, am writing auth.interceptor.ts file to achieve this,
[contact-form-7 404 "Not Found"]

Step 4: Writing auth.interceptor.ts

import {
HttpInterceptor,
HttpRequest,
HttpHandler
} from "@angular/common/http";
import { Injectable } from "@angular/core";
import { AuthService } from "./auth.service";
 
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
constructor(private authService: AuthService) {}
 
intercept(req: HttpRequest<any>, next: HttpHandler) {
const authToken = this.authService.getToken();
const authRequest = req.clone({
headers: req.headers.set("Authorization", "Bearer " + authToken)
});
return next.handle(authRequest);
}
}

 
That’s all guys! its simple as like that. Please clearly follow these crisp steps to add more security to your angular application using JWT Tokens. Post us your queries in comment section, would like to hear from you!
Building an angular application? Like to hear more from Angular experts? Don’t miss out to read more from the great minds in the industry!

Contact us today to get free 20 hrs of consulting & proof of concept from experts”

 

Manigandan

An ideal Full Stack Developer, having around 5+ years of experience in web development arena, expertise in AngularJS, Nodejs, PHP and also scoring 6 years of experience in Networking & Window servers. A perfect all-rounder has fondness to play diverse role. he always strives to match perfection and likely remains the best in whatever role he takes.