Implementing Route Resolver in Angular 6(Another way implementing AUTH GUARD)

0
4376
views

Implementing Route Resolver in Angular 6: Sometimes it is not only enough to validate the JWT token at the front end but you also want to send it to the back end to check its validity. But the thing here is, In Auth Guard it is not possible to make an API call to the back end and wait for the result. Auth guards are not meant for that purpose to make such validation.

So, Here Route resolvers will come in to the picture, If your application is demanding making an API call to the back end then you have to use resolver rather than auth-guard.

Let’s implement resolver in our application

Implementing Route Resolver in Angular 6

create a resolver.guard.ts file in your appliction

import { DataService } from './data.service';
import { LoginService } from './login.service';
import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, RouterStateSnapshot, Resolve } from '@angular/router';
import * as decode  from 'jwt-decode';

@Injectable()
export class ResolverGuard implements Resolve<any> {
  constructor(private dataService:DataService, private loginService:LoginService) {

   }

  resolve(
    route: ActivatedRouteSnapshot,
    state: RouterStateSnapshot): Promise<any> {
      let expectedRoleArray = route.data;
      expectedRoleArray = expectedRoleArray.expectedRole;

     const token = localStorage.getItem('jwt');

     // decode the token to get its payload
     const tokenPayload = decode(token);

     let  expectedRole = '';

     for(let i=0; i<expectedRoleArray.length; i++){
       if(expectedRoleArray[i]==tokenPayload.role){
         console.log("Roles Matched");
         expectedRole = tokenPayload.role;
       }
     }

    console.log(expectedRole, tokenPayload);
    if(expectedRole ==tokenPayload.role ){

      return this.dataService.verifyJWT().then(data => {
        console.log(data);
        if(data['success']){
          console.log("Token Validated");
            return true;
        }
        else{
          alert("Authentication Error Logging out");
          window.localStorage.clear();
          this.loginService.informLogout('sss');
          return null;
        }
      })
      .catch(e=>{
        console.log(e.status);

        if ((e.status === 401) || (e.status === 500)) {
          alert("Authentication Error Logging out");
          window.localStorage.clear();
          this.loginService.informLogout('sss');
          return false;

        }
        else{
            alert(e);
            return false;
        }
      });

    }
    else{

      let promise = new Promise((resolve, reject) => {
        reject({
          message: "Roles not matched"

        })
      });

      return promise.then(data =>{
        // console.log("The roles matched");
        return false;
      })
      .catch(err => {
        console.log(err);
        window.localStorage.clear();
        this.loginService.informLogout('sss');
        return false;
      })

    }

  }

}

As you can see in the code above our Resolve class implements resolve method whatever the data returned from resolve method is resolved data.

In the code I am also checking for expected user role. If the roles with logged in user role gets matched then I am making an API call to the back end to validate the existing token in the local storage.
If the token gets validated from the back end I am logging in the user or else user will be logged out.

If you want to implement Role Guards along with resolve you can checkout Role Based Access Control In Angular 4 Route Guards in Depth

Implementing Route Resolver in Angular 6

In app.routing.ts file mention the resolver guard. Whenever you navigate to that particular route resolver guard will be called.

import { ResolverGuard } from './resolver.guard';
import { RoleGuardService as RoleGuard } from './role-guard.service';
import { AddsubscriptionsComponent } from './addsubscriptions/addsubscriptions.component';

const MAINMENU_ROUTES: Routes = [

    {
        path: '',
        component: WelcomeComponent,
        resolve: {
            jwtDetails: ResolverGuard
        },
        data: {
            expectedRole: ['role1','role2', 'role3']
          }
    }

];
export const CONST_ROUTING = RouterModule.forRoot(MAINMENU_ROUTES, {onSameUrlNavigation: 'reload'});

As you can see I used the resolver guard particularly for welcome component because whenever user logs in by default he/she will be navigated to that route. If the token already exists in the browser local storage they will be automatically logged in.

To prevent any needless attempt of breaching I am simply validating token from back end one more time.

You can only use resolver for that particular route.

Implementing Route Resolver in Angular 6

Mention the Resolver Guard in the providers of app.module.ts file also

By now we have successfully implemented resolver in our application.

I hope this was helpful

Happy Coding..!