version2 version2 - 3 months ago 56
AngularJS Question

Angular 2 Authentication with child routes

I have an angular 2 application in which I need to be authenticated on every page. So I have implemented a custom RouterOutlet to confirm I am logged in on every page change.

@Directive({
selector: 'auth-outlet'
})
export class AuthOutlet extends RouterOutlet {
publicRoutes: any;
private parentRouter: Router;
private authService: AuthService;
constructor(_elementRef: ElementRef,
_loader: DynamicComponentLoader,
_parentRouter: Router,
@Attribute('name') nameAttr: string,
_authService: AuthService) {

super(_elementRef, _loader, _parentRouter, nameAttr);
this.parentRouter = _parentRouter;
this.authService = _authService;
this.publicRoutes = {
'Login': true
};
}

activate(oldInstruction: ComponentInstruction) {
var url = this.parentRouter.lastNavigationAttempt;
console.log('attemping to nav');
if (!this.publicRoutes[url] && !this.authService.loggedIn){
var newInstruction = new ComponentInstruction('Login', [], new RouteData(), Login, false, 1);
return super.activate(newInstruction);
} else {
return super.activate(oldInstruction);
}
}
}


Here is a working code:
http://plnkr.co/edit/YnQv7Mh9Lxc0l0dgAo7B?p=preview

Is there a better way to intercept route changes and redirect for login when the user is not authenticated?

Answer

For anyone that finds this, the answer now in Angular 2 is to use "Guards" as part of the new Router. See Angular 2 documentation:

https://angular.io/docs/ts/latest/guide/router.html#!#guards

A basic guard just implements "CanActivate", and could work as follows:

import {Injectable} from "@angular/core";
import {CanActivate, Router} from "@angular/router";
import {AuthService} from "../services/auth.service";

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(private authService:AuthService, private router:Router){}

    canActivate(){
        if(this.authService.isAuthenticated())
            return true;

        this.router.navigate(["/login"]);
        return false;
    }
}

As you can see in this example I have an AuthService running somewhere else (implementation isn't important) which can tell the guard if the user has been authenticated. If they have, return true and the navigation happens as usual. If they have not, we return false and redirect them to the login screen.

Comments