Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameters into Guard Angular 2

I have an app that I have setup with an Authentication Guard to make sure users cannot access the app unless they have logged in, like so

import { Injectable } from '@angular/core';
import {
    CanActivate, Router,
    ActivatedRouteSnapshot,
    RouterStateSnapshot,
    CanActivateChild } from '@angular/router';
import { AuthContext } from './auth-context.service';

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

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        // Check to see if a user has a valid JWT
        if (this.authContext.userInfo !== undefined && this.authContext.userInfo.isAuthenticated) {
            // If they do, return true and allow the user to load the home component
            return true;
        }

        // If not, they redirect them to the login page
        this.router.navigate(['/login']);
        return false;
    }

    canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
        return this.canActivate(route, state);
    }
}

I want to add another guard for Authorization that will check if the user is in a certain role. Currently I am hiding the link in navigation based on this role.

 <div *ngIf="userInRole('Admin')">
             This is secret stuff
 </div>

But if a user knows a route, they can just plug it into the url. How would I add my "userInRole()" type functionality to a Guard? I would have to pass the role name and do the check in code. Do Guards support params?

like image 756
Isaac Levin Avatar asked Dec 27 '16 18:12

Isaac Levin


People also ask

Is it possible to pass data to an Angular guard through the routing module?

Angular allows us to pass data to the route. The route data can be either static or dynamic. The static data use the Angular route data property, where you can store arbitrary data associated with this specific route. For to pass dynamic data (or an object), we can make use of the history state object.

What is the difference between canLoad and CanActivate?

canActivate is used to prevent unauthorized users from accessing certain routes. See docs for more info. canLoad is used to prevent the application from loading entire modules lazily if the user is not authorized to do so. See docs and example below for more info.

What is CanActivate AuthGuard in Angular?

AuthGuard is used to protect the routes from unauthorized access in angular. How AuthGuard Works? Auth guard provide lifecycle event called canActivate. The canActivate is like a constructor. It will be called before accessing the routes.


2 Answers

I found solution this

    import { Injectable } from '@angular/core';
    import { CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
    import { Observable } from 'rxjs/Observable';
    import { AuthService } from './service/auth.service';

    @Injectable()
    export class IsInRoleGuard implements CanActivate {
        constructor(
            private _authService: AuthService
        ) { }

        async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
            const userRole = this._authService.getRole(); // Get role from service
            if (next.data['roles'].indexOf(userRole) !== -1) {
                return true;
            }
            return false;
        }
    }

and in your router-config

import { Routes, RouterModule } from '@angular/router';
import { ModuleWithProviders } from '@angular/core';
import { RootComponent } from './root/root.component';
import { DashboardComponent } from './dashboard/dashboard.component';
import { IsInRoleGuard } from '../../guards/is-in-role.guard';

const routes: Routes = [
    {
        path: '', component: RootComponent, children: [
            {
                path: '', pathMatch: 'full', canActivate: [IsInRoleGuard], component: DashboardComponent, data: {
                    roles: [
                        'admin',
                        'super-admin'
                    ]
                }
            }
        ]
    }
];

export const RouterConfig: ModuleWithProviders = RouterModule.forChild(routes);
like image 139
Omkar Yadav Avatar answered Nov 11 '22 09:11

Omkar Yadav


A guard is just a class that implements CanActivate or CanDeactivate. But nothing stops you from injecting a service (or a value) that would return you the role of the user. For example,

export class AuthGuard implements CanActivate {
        constructor(private router: Router, private authContext: AuthContext, 
             private user: MyUserService) { }

    canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean {
          if (!this.user.isAdmin()) return false;
          ...

    }
}
like image 35
Yakov Fain Avatar answered Nov 11 '22 08:11

Yakov Fain