Munchkin
Munchkin

Reputation: 1085

Errors while implementing Angular 8 Route (Auth) Guards

So I was trying to implement Route Guards for my webapp but came into a lot of errors. What did I do wrong?

My webapp consists of multiple routes, one of which is dashboard, which needs to be protected by a login component. That's exactly what I tried implemented but failed at it. My login component generates a JWT Token from the BackEnd and adds it into LocalStorage (in format of an object "token": "").

My dashboard.component.ts:

import { Component, OnInit } from '@angular/core';
import { User } from '../models/user.model';

@Component({
  selector: 'app-dashboard',
  templateUrl: './dashboard.component.html',
  styleUrls: ['./dashboard.component.css']
})
export class DashboardComponent implements OnInit {
  user: User;

  constructor() { }

  ngOnInit() {
  }

  canDeactivate(): Promise<any> | boolean {
    if (localStorage.getItem('currentUserToken') === 'token') {
            return (true);
          } else {
            return (false);
          }

}
}

My auth.guard.ts:

import {Injectable} from '@angular/core';
import {ActivatedRoute, ActivatedRouteSnapshot, CanActivate, CanLoad, Route, Router, RouterStateSnapshot} from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate, CanLoad {
    constructor(private router: Router) {
    }
    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        return this.checkToken();
    }
    canLoad(route: Route): boolean {
        return this.checkToken();
    }
    checkToken() {
        if (localStorage.getItem('currentUserToken')) {
            return true;
        } else {
            this.router.navigateByUrl('/avior/login');
            return false;
        }
    }
}

My can-exit.guard.ts:

import {Injectable} from '@angular/core';
import {CanDeactivate} from '@angular/router';
import {CanExit} from './canExit';
@Injectable()
export class CanExitGuard implements CanDeactivate<CanExit> {
 canDeactivate(component: CanExit) {
   if (component.canDeactivate) {
     return component.canDeactivate();
   }
   return true;
 }
}

My canExit.ts:

import {Observable} from 'rxjs';
export interface CanExit {
 canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

The errors in the browser are:

DashboardComponent.ngfactory.js? [sm]:1 ERROR TypeError: Cannot read property 'id' of undefined
DashboardComponent.ngfactory.js? [sm]:1 ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 1, nodeDef: {…}, elDef: {…}, elView: {…}}
ERROR TypeError: Cannot read property 'id' of undefined
ERROR CONTEXT DebugContext_ {view: {…}, nodeIndex: 1, nodeDef: {…}, elDef: {…}, elView: {…}}

UPDATE: StackBlitz: https://stackblitz.com/edit/angular-v9u7nw?file=src%2Fapp%2Fapp.routing.ts

Upvotes: 0

Views: 709

Answers (1)

Gaurang Dhorda
Gaurang Dhorda

Reputation: 3387

for redirecting user to login component you need router guard in routing path defined. I am here not setting token part for this use-case. you can find complete working StackBlitz Link here. if You directly redirect to /dashboard, auth-guard redirect to /login if user has not logged in.

your auth-guard is..

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot):Observable<boolean> | Promise<boolean> | boolean {

   if(this.authService.isUserLoggedIn()){
       return true;
   }else{
      this.router.navigate(['/login'],{relativeTo: this.activatedRouter});
        return false;
    }
}

Your Authentication service looks like this..

 isAuthenticated(username: string, password: string): Observable <boolean>{
return this.getAllUsers().pipe(
  map(users => {
    let user = users.find( user => (user.username === username) && (user.password === password) );
        console.log(user)
        if (user) {
          this.isLoggedin = true;
          this.loggedInUser = user;
        } else {
          this.isLoggedin = false;
        }
        return this.isLoggedin;
  })
)
}

Your app-routing module is..

const routes: Routes = [{path: 'login', component: LoginComponent},
                    {path: '', redirectTo: 'login',  pathMatch: 'full'},
                    {path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard]}
                    ];

Your Login submit method..

this.authService.isAuthenticated(this.loginForm.get('username').value,this.loginForm.get('password').value).subscribe(authenticated =>{
    if (authenticated){
      let url = this.authService.getRedirectUrl();
       this.router.navigate([url]);
    }
});

Upvotes: 1

Related Questions