DEV Community

Fredy Daniel Flores Lemus
Fredy Daniel Flores Lemus

Posted on

Protect Your Routes in Angular with Guards: Control Access and Exit of Routes Efficiently!


Looking for a way to manage access to your routes in Angular? Guards are the perfect tool for this task. In this blog post, I'll break down how Guards operate and how you can implement them to enhance your application's security. With Guards, you'll be able to specify who can access which routes and redirect unauthorized users to different sections of your application!

Creating Access Guard

To create a Guard in Angular, the first step is to establish a new service that will house the code for your Guard. In my case, I will name the service "AuthGuard".

It's crucial to note that, in order to utilize Guards in your application, you need to import the CanActivate class from the @angular/router module and apply it as an interface to the service you have created.

import { Injectable } from "@angular/core";
import { CanActivate } from "@angular/router";

@Injectable({ provideIn: "root" })
export class AuthGuard implements CanActive {
  canActivate(): boolean {}
}
Enter fullscreen mode Exit fullscreen mode

When you create the Guard service in Angular, you must implement a method called canActivate() within it. This method is responsible for determining whether a user has access to a specific route or not. It should return a boolean value: true if the user can access the route and false otherwise.

Therefore, within the canActivate() method, you will need to write the necessary code to check if the user meets the access requirements for the particular route. For instance, you can check if the user is logged in, or if they have certain permissions or roles, etc.

If the user fulfills the access requirements, the canActivate() method should return true. Otherwise, you should redirect the user to another route and return false.

canActivate(route: ActivatedRouteSnapshot, state:
RouterStateSnapshot): Observable<boolean> | Promise<boolean> | boolean{
    return this.authService.isAuthenticated()
        .then(
            (authenticated: boolean) =>{
                if (authenticated){
                    return true;
                }else{
                    this.router.navigate(['/']);
                    return false;
                }
            }
        )
}
Enter fullscreen mode Exit fullscreen mode

Implementing Access Guard

Lastly, to use a Guard on a specific route in Angular, you need to add the canActivate property to the configuration of the respective route. This property is an array that should include the service you created to implement the Guard.

const appRoutes: Routes = [
  {
    path: "servers",
    canActivate: [AuthGuard],
    component: ServersComponent,
  },
];
Enter fullscreen mode Exit fullscreen mode

Exit Guard

With this, we will manage to have a protected route that executes a guard to confirm whether or not it is accessible, but often we also want to secure the exits of our routes.

Angular Guards also allow you to control whether a user can leave a route or not. This is useful, for instance, to prevent a user from closing a page in the middle of an important process without saving the changes.

To control the exit of a route in Angular, you need to create a Guard in a new service that implements the CanDeactivate interface. This interface is similar to CanActivate, but it triggers when a user attempts to leave a route instead of accessing it.

import { Injectable } from "@angular/core";
import {
  ActivatedRouteSnapshot,
  CanDeactivate,
  RouterStateSnapshot,
} from "@angular/router";
import { Observable } from "rxjs";

export interface CanComponentDeactivate {
  canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;
}

@Injectable({ provideIn: "root" })
export class CanDeactivateGuard
  implements CanDeactivate<CanComponentDeactivate>
{
  canDeactivate(component: CanComponentDeactivate) boolean{
    return component.canDeactivate();
  }
}
Enter fullscreen mode Exit fullscreen mode

As you can see, the CanDeactivate method receives the component that is being rendered on the route as a parameter, and within this component, adds a method called canDeactivate() that contains the necessary code to verify if the user can leave the route or not. This method should return a boolean value: true if the user can exit the route and false otherwise.

Important! When you use a Guard that implements the CanDeactivate interface to control the exit of a route in Angular, you have the option to execute the access verification code either in the service implementing the Guard or in the component being rendered on the route.

The advantage of executing the access verification code in the component is that you can use the component's attributes to define your verification logic. This allows you to have greater control over the verification process and make it more specific for each component.

On the other hand, if you execute the access verification code in the service implementing the Guard, you can reuse the same code for several different components. This can be more efficient and maintainable, especially if you have multiple components that share the same access verification requirements.

In summary, the choice of where to execute the access verification code depends on your needs and preferences. You can do it in the component to have greater control over the process or in the service to reuse the code across various components.

canDeactivate(): boolean | Observable<boolean> | Promise<boolean>{
    if(!this.allowEdit){
        return true;
    }
    if((this.serverName !== this.server.name || this.serverStatus !== this.server.status) && !this.changesSaved){
        return confirm('Do you want to discard the changes?')
    }else{
        return true;
    }
}
Enter fullscreen mode Exit fullscreen mode

Here you can see the canDeactivate method applied in the component that is rendered according to the route, which in my example returns true if the user has saved changes or, in the other case, returns a confirm dialog asking the user if they wish to leave the route without saving their changes.

Lastly, in the route configuration, add the canDeactivate property and pass the service you created to implement the Guard as an argument.

const appRoutes: Routes = [
  {
    path: "servers/edit",
    canDeactivate: [CanDeactivateGuard],
    component: EditServerComponent,
  },
];
Enter fullscreen mode Exit fullscreen mode

In this post, we have learned how to secure our routes in Angular using Guards. We've explored how to use the CanActivate and CanDeactivate Guards to control access to and exit from routes, respectively. Additionally, we've discussed how to implement these Guards and how to apply them in route configurations.

With this knowledge, you now know how to protect your routes in Angular and can employ this technique to ensure that a route is accessed or left only under specific conditions. This will grant you greater control over the flow of your application and guarantee that certain areas are accessed or certain actions are carried out only if predefined requirements are met. I hope you enjoyed learning about this topic!

Top comments (0)