Angular Routing Guards: Let’s understand Route Guards (Part-1)

Reading Time: 6 minutes

If the user wants to open a certain page in a traditional server-side application, the application would first check permissions on the server and return a 403 error page. For eg., if the user didn’t have permissions then there will be no routing to the dashboard page and it will route them again to a login/register page if they were not signed up.

403 is an HTTP error code. Specifically, this one means Permission Denied.

We can implement the same functionality but not exactly the same in the client-side Single-Page Application(SPA) with the help of Routing Guards.

Client-side route guards like this are not meant to be as a complete security feature. They won’t prevent a clever user from figuring out a way to get to the protected routes. Such security should be implemented on the server. They are instead meant as a way to improve the user experience (UX) for the application.

In this part of the series, we’ll learn the following points:

1. What are Angular Route Guards?

2. Why Guards?

3. Uses of Angular Route Guards

4. Different types of Angular Route Guards

In the coming part of this series, we’ll learn how to implement the different types of guards one by one in our Angular Application. So, stay tuned!

Let’s start to learn.

What are Angular Router Guards?

Angular provides lots of features and ready-to-use services which permit consistent improvement of the amazing web applications. In which routing is one of the most important and beneficial features of Angular. But sometimes if you want to prevent a user from going to a particular page, or want to block a route based if not authenticated, or discourage them from leaving a page, at that time, the router guards help to do so. If you want to learn more about routing and navigations, you can refer here.

Angular router’s navigation guards allow to grant or remove access to certain parts of the navigation. It provides built-in interfaces that can be implemented to routes to control their navigation.

Why should use Angular Router Guards?

If the user has the access to navigate all the pages on the application, it will make an application less secure. For that, we need to restrict the user until the user performs specific actions like login. Angular provides the Route Guards for this purpose.

One of the common scenarios, where we use guards is authentication. We want our App to stop unauthorized users from accessing the protected route. 

Use cases of Angular Route Guards

Here, some of the use cases:

1. Allow access to certain parts of the application to specific users

2. Validating the route parameters before navigating to the route

3. To Confirm the navigational operation

4. Asking whether to save before moving away from a view

Different types of Angular Route Guards

There are five types of route guards which are provided by angular :

1. CanActivate

2. CanActivateChild

3. CanLoad

4. CanDeactivate

3. Resolve

Now let’s learn each route guard one by one.

1. canActivate:

It checks if the user can visit the specific route or we have to prevent access to the specific route. For this, we use the CanActivate interface.

We write the method signature as:

canActivate(route:ActivatedRouteSnapshot, state:RouterStateSnapshot):Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree

Here, the canActivate method has two arguments. First, as a ‘route’, which is to prevent a user from navigating to a given route. Second argument i.e., ‘state’ which is redirecting the user to some other route.

In the auth-guard.service.ts, we will create a class AuthGuard. The file will be looks like this:

import {CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot, Router} from '@angular/router';
import { Observable } from 'rxjs/Observable';
export class AuthGuard implements CanActivate {
constructor(private authService: AuthService, private router: Router) {}
canActivate(route: ActivatedRouteSnapshot, state:RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean {
  // return true if you want to navigate, otherwise return false
 }
}

Now in the app-routing.module.ts, we have to use this service like this:

{ path: 'p/:id', component: DashboardComponent, canActivate : [AuthGuard] }

Also, don’t forget to add the created service to the providers array in the app.module.ts file e.g.

providers: [ AuthGuard]

We’ll see the implementation of the canActivate guard in Part-2 of this series of Angular Routing Guards.

2. canActivateChild:

canActivateChild is almost the same as the canActivate guard. The only difference between them is that canActivate guard checks if the user can visit the specific route or we have to prevent access to the specific route while the canActivateChild is used to prevent access to child routes of a given route, so by using this you don’t need to add canActivate on each child route.

In other words, you just need to add canActivateChild to the parent route and it will work for child routes as well.

In the app-routing.module.ts, we have to use this service like this:

{
   path: 'dashboard',
   canActivate: [AuthGuard],
   canActivateChild: [AuthGuard],
   component: DashboardComponent,
   children: [
    { path: ':id', component: HomeComponent},
    { path: ':id/name', component: UserComponent}
]}

We’ll see the implementation of the canActivateChild guard in Part-3 of this series of Angular Routing Guards.

3. canLoad:

It checks if a user can route to a module that lazy-loaded. To implement lazy-loading, we use the loadChildern in the route definition. As we know, the main advantage of lazy-loading is it reduces the loading time of the application.

If you want to learn in-depth about lazy-loading, you can check out here.

So, here if we want to restrict the navigation to the specific route we use the canActivate guard, this will surely restrict that but in addition to that, it also downloads the modules. Now to control both i.e., unauthorized access and downloaded modules, you have to use the canLoad guard.

We write the method signature as:

canLoad(route:Route,segments:UrlSegment[]):Observable<boolean>|Promise<boolean>|boolean;

To implement this in the file, first, we have to define the service for eg., AuthGuardLazyLoad, and implements the canLoad guard. Thus the auth-guard-lazy-load.service.ts file looks like this:

import { CanLoad, Route, Router } from '@angular/router';
export class AuthGuardLazyLoad implements CanLoad {
constructor(private router: Router) {
}
 canLoad(route:Route,segments:UrlSegment[]):Observable<boolean>|Promise<boolean>|boolean {
 /* return true or false depending on whether you want to load that module or not */
 }
}

And after that, just add this service to this app-routing.module.ts to the canLoad as shown below:

{path: "home", loadChildren:'./home/home.module#HomeModule', canLoad:[AuthGuardLazyLoad]}

Also, don’t forget to add the created service to the providers array in the app.module.ts file e.g.

providers: [AuthGuardLazyLoad]

We’ll see the implementation of the canLoad guard in Part-4 of this series of Angular Routing Guards.

4. canDeactivate:

This guard decides if the user can leave the component i.e, drive away from the current route. This guard plays an important role if the user has some pending changes which are not saved, so canDeactivate, guard allows us to ask for user confirmation before leaving the component.

This route guard is a little bit different in implementation from the above-mentioned routes as it involves defining a method in the component class itself. Let’s see the method signature.

We write the method signature as:

canDeactivate(component: T, currentRoute: ActivatedRouteSnapshot, currentState: RouterStateSnapshot,nextState?: RouterStateSnapshot): Observable<boolean|UrlTree>|Promise<boolean|UrlTree>|boolea|UrlTree;

Here, T is the interface that we will be using in the component and in the guard services.

We’ll see the implementation of the canDeactivate guard in Part-5 of this series of Angular Routing Guards.

5. Resolve Guard:

Resolve guards, sets the data communication between the components. This delays the activation of some specific routes until some tasks are completed.

Sometimes, the data is so heavy and because of that, it is not possible to pass it to them in the query params. So, to handle this type of situation angular provides us the Resolve Guard.

Now, let’s see its method signature:

resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<T> | Promise<T> | T

Here, T is the datatype that resolve will pass to the component after resolving data.

Conclusion:

So, in this blog, we’ve learned about five route guards provided by angular that allow us to protect access to client-side routes but as said nothing, on client-side is completely protected. Any asset or data delivered to the client is completely accessible by them. Hence, always be sure to protect sensitive data on the server.

Hey there, I am glad you have reached the end of this post. If you liked this post or have some questions or want to discuss something let me know in the comment section. And stay tuned for the implementation of Angular Router Guards one by one in the coming part of the series.

For more info you can check:

https://angular.io/guide/router-reference

knoldus-advt-sticker

Written by 

Alka Vats is a Software Consultant at Knoldus. She is passionate about web development. She is recognized as a good team player, a dedicated and responsible professional, and a technology enthusiast. She is a quick learner & curious to learn new technologies. Her hobbies include reading books, watching movies, and traveling.