1

I have created a Auth Manager in Angular2 to restrict Component access directly . I am still new to angular and learning the concepts.

I was able to restrict the user if the user name is not correct. But i am not able to use the value returned by the canActivate Method in my component to display a message in my front end.

My AuthManager class

import { Injectable } from '@angular/core';
import { CanActivate,Router,ActivatedRouteSnapshot,RouterStateSnapshot } from '@angular/router';

@Injectable()

export class AuthManager implements CanActivate{

    user = "user";

    constructor(private router:Router){

    }

    canActivate(route:ActivatedRouteSnapshot,state:RouterStateSnapshot){
        console.log("Comes Here");
            if(this.user == "user"){
                return true;
            }else{
                console.log("YOur are not authorized");
                this.router.navigate(['/persons']);
                return false;
            }
    }
}

I am able to see YOur are not authorized in log but how to use the value in a component.

My app.router.ts

{
    path: 'persons/:id',
    component: PersonDetailComponent,
    canActivate:[AuthManager]       
    }
  • i think you need to return not a true/false but the value instead – federico scamuzzi Jan 04 '17 at 12:09
  • subscribe to the event that returns a message – Roman C Jan 04 '17 at 12:26
  • Has @RomanC can you please describe how –  Jan 04 '17 at 12:28
  • Why not just navigate to a dedicated "NotAuthorised" page on failure rather than to "/persons"? e.g. this.router.navigate(['/notAuthorised']); and create that route/component – Quails4Eva Jan 04 '17 at 16:22
  • but that will not be good in modern day application people get a message saying either their username or password is incorrect. –  Jan 05 '17 at 07:11
  • @INFOSYS The 'notAuthorised' component could say that message. I think you could even have a parameter on the route that lets you pass the message to display – Quails4Eva Jan 06 '17 at 17:21

3 Answers3

2

What i understood by the Question is that you want to display Some kind of Error Message to the User if the Auth Fails. @PierreDuc is correct.But i have a different approach to this.

what you can do is create a service class

authenticate.service.ts

import {Injectable} from '@angular/core'

@Injectable()

export class AuthenticateService

    isAuthenticated(//take the user credentials here):boolean{
        return true // if the credentials are correct 

     or retun false // if the credentials donot match.    

    }

make use of this class in your component and AuthManager

import { Injectable } from '@angular/core';
import { CanActivate,Router,ActivatedRouteSnapshot,RouterStateSnapshot } from '@angular/router';
import {AuthenticateService} from './authenticate.service'

@Injectable()

export class AuthManager implements CanActivate{

    user = "user";

    constructor(private router:Router,private authenticateService:AuthenticateService){

    }

    canActivate(route:ActivatedRouteSnapshot,state:RouterStateSnapshot){
        console.log("Comes Here");
           return  this.authenticateService.isAuthenticated();
    }
}

and in the component check the same

this.authenticateService.isAuthenticated()== false
*ngIf and then display an error message to the user.

Hope this is what you where looking at . it not exactly the answer of the question but a way to solve your problem.

Rahul Singh
  • 19,030
  • 11
  • 64
  • 86
1

You can use service and set the value you want to display in component inside the AuthManager.

Sudheer KB
  • 1,596
  • 14
  • 28
1

That's quite an uncommon thing to do, but I understand why you would want something like that. It is however not possible to capture the result returned from CanActivate.

However you could make an ErrorService and subscribe a component to an triggered event to show a toast message or something like that.

untested code ahead

@Injectable()
export class AuthManager implements CanActivate{

    user = "user";

    constructor(private router:Router, private errorService: ErrorService){}

    canActivate(route:ActivatedRouteSnapshot,state:RouterStateSnapshot){
       if(this.user == "user"){
            return true;
       } else{
           this.errorService.toastError("You are not authorized");
           this.router.navigate(['/persons']);
           return false;
       }
    }
}

Your error service would in basic look something like this, you should add this service to your root providers:

export class ErrorService {

   public readonly error: Subject<string> = new Subject<string>(); 

   public toastError(error: string): void {
     this.error.next(error);
   }

}

After that place a component inside your AppComponent (or whatever you deem fit) and make it something like this:

@Component({
   selector : 'error-toast',
   template : `<div [innerHtml]="error" *ngIf="error"></div>`
})
export class ErrorToastComponent implements OnInit, OnDestroy { 

   public error: string = "";  

   private timeout: number = 0;

   private errorSub: Subscription;

   private readonly timer: number = 5000;

   constructor(private errorService: ErrorService) {}

   ngOnInit(): void {
      this.errorSub = this.errorService.subscribe((error: string) => {
          this.toastError(error);
      });
   }

   ngOnDestroy(): void {
      this.errorSub.unsubscribe();
      this.cancelTimer();
   }

   private toastError(error): void {
      this.cancelTimer();
      this.error = error;
      this.timeout = window.setTimeout(() => {
         this.error = "";
      }, this.timer);
   }

   private cancelTimer(): void {
      if(this.timeout !== 0) {
         clearTimeout(this.timeout);
         this.timeout = 0;
      }
   }

}
Poul Kruijt
  • 69,713
  • 12
  • 145
  • 149
  • if you say that its uncommon how does a application display an error message if the user is not authenticated .Like we need somevalue inorder to check what to display the error mesage or route to the next page –  Jan 04 '17 at 12:31
  • Yes, but I don't think this should be handled inside an AuthGuard. The guard is really there just to let the router know if he can navigate or not. But nevertheless, I can see why you want to do something like that, and I guess my solution will fulfil your needs ;) – Poul Kruijt Jan 04 '17 at 12:32
  • what is the proper way actually can you please brief that it would be great –  Jan 04 '17 at 12:36
  • 1
    the more i think about it, it seems quite intuitive to handle it inside the AuthGuard. I'm trying to think of reasons to oppose against it, or other ways to do it, but can't think of any. Guess you are on the right path :) – Poul Kruijt Jan 04 '17 at 12:40
  • Is there any Simpler way to this –  Jan 04 '17 at 14:07
  • The only non simple thing is the ToastComponent, and i was a bit bored when i wrote that just now :D. You can however subscribe to the event in any way you want to process the error. As I said before, it is not possible to directly interact on a return value from the `AuthGuard` inside a component, which means the use of a service is necessary – Poul Kruijt Jan 04 '17 at 14:09