Tutorial hero image
Lesson icon

Prevent Access to Pages in Ionic with Angular Route Guards

2 min read

Originally published April 18, 2018

In this tutorial, we are going to cover how to use route guards with Angular routing to prevent access to certain routes if certain conditions have not been met. A common example of this is preventing access to certain pages if the user is not logged in, and that is what we will be focusing on.

Outline

Angular Route Guards

The basic idea behind a route guard is that you attach a service which acts as the "route guard" to a particular route. That service has a canActivate method which will return either true or false depending on whether the user should be allowed to go to that route or not. If the canActivate method returns false, then the user will not be able to access the route.

Route guards make the process of protecting certain routes and redirecting the user quite simple, and in my opinion, more manageable than using navigation guards like ionViewCanEnter on individual components. The end result looks something like this:

const routes: Routes = [
  { path: '', redirectTo: '/login', pathMatch: 'full' },
  { path: 'login', loadChildren: './login/login.module#LoginPageModule' },
  {
    path: 'home',
    loadChildren: './home/home.module#HomePageModule',
    canActivate: [AuthGuardService],
  },
];

All we need to do is add one additional property to the route definitions to determine if the route can be activated. Since the routes in the example above are lazy loaded, we could also use canLoad instead of canActivate to entirely prevent the loading of the children for that route (rather than just preventing access).

It is important to note that most things we implement on the client side (i.e. not on a server) are more for user experience than security. Client-side code is accessible/modifiable by the user, so you should never use route guards to protect information that you don't want the user to see (just as you shouldn't solely use client-side code to validate/sanitise user entered data). Think of your route guards as a friendly security guard directing traffic they can keep people away from where they are not supposed to be, and direct them to where they need to go, but anybody with malicious intent could easily run right by the guard. Anything in your application that needs to be kept secure should only be accessible through a server that your application communicates with.

Creating a Route Guard

Creating a route guard is as simple as creating a service that implements a canActivate method. For example, we could generate an AuthGuard service with the following command:

ionic g service services/AuthGuard

Then, all you need to do is have this canActivate method return true or false and you can do whatever you like to determine that value:

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

@Injectable({
  providedIn: 'root',
})
export class AuthGuardService implements CanActivate {
  constructor(private router: Router) {}

  canActivate(route: ActivatedRouteSnapshot): boolean {
    console.log(route);

    let authInfo = {
      authenticated: false,
    };

    if (!authInfo.authenticated) {
      this.router.navigate(['login']);
      return false;
    }

    return true;
  }
}

In this example, we have just set up a dummy object called authInfo that has an authenticated value of false. In a real-life situation, we would just pull this authenticaiton information from whatever is responsible for authenticating the user. We then check that value, and it the user is not authenticated we send them back to the login page and return false otherwise, we just return true which will allow the navigation to proceed.

Although we are not using it, we have also injected ActivatedRouteSnapshot which will allow you to access details about the route that the user is navigating to. You may need details about the route, like the parameters that were supplied, in order to determine whether or not to allow a user to proceed.

Attach the Route Guard to your Routes

All that is left to do once you create the route guard is to import it into the file that contains your routes, and attach it to any routes you want to protect with it:

import { NgModule } from '@angular/core';
import { PreloadAllModules, RouterModule, Routes } from '@angular/router';
import { AuthGuardService } from './services/auth-guard.service';

const routes: Routes = [
  { path: '', redirectTo: '/login', pathMatch: 'full' },
  { path: 'login', loadChildren: './login/login.module#LoginPageModule' },
  {
    path: 'home',
    loadChildren: './home/home.module#HomePageModule',
    canActivate: [AuthGuardService],
  },
];

@NgModule({
  imports: [
    RouterModule.forRoot(routes, { preloadingStrategy: PreloadAllModules }),
  ],
  exports: [RouterModule],
})
export class AppRoutingModule {}

You can use multiple different route guards if you like, and you can attach the same route guard to multiple different routes.

Summary

The approach that Angular routing uses for route/navigation guards is quite similar in the end to the way you would have done it with ionViewCanEnter ultimately, it is just a function returning true or false. However, I think the benefit of this approach is that it is a little more organised and it is easier to apply guards to multiple routes.

If you enjoyed this article, feel free to share it with others!