Using CanActivateFn in Angular 17

Angular development demands security and control over navigation activity. This article goes into two critical Angular Guards enhancements: the switch from implementing the CanActivate interface to using CanActivateFn. These enhancements provide developers with a simpler, more effective method to protect routes while imposing role-based access control.

Guards act as guardians in Angular apps, limiting accessibility to specific routes based on defined constraints. They play an important role in implementing authentication, authorization, and other navigation rules. Their utility is in protecting routes from unwanted access or improper navigation.

Route guards are used in Angular for authorizing or denying access to specific routes. The CanActivateFn function provides a functional alternative to building route guards that allow or deny access to specified routes based on certain conditions. In this post, we will look at how to work with CanActivateFn in Angular and provide practical examples of how to use it to protect routes or parts of our Angular application.

Topics:

  1. What is Angular CanActivateFn?
  2. Signature of CanActivateFn
  3. CanActivate in Route Configuration
  4. Using mapToCanActivate for Class-Based Guards
  5. Using CanActivateFn in Angular 17 Applications
  6. Add a CanActivateFn Function
  7. Use canActivate in Route Configuration
  8. Using mapToCanActivate for Old Class Guards
  9. Conclusion

Previously, guards were interfaces that had to be implemented and registered in your modules.

However, in the most recent versions of Angular, class-based guards have been deprecated in favor of functional guards.

To achieve the same result as implementing an interface, a function can now be used instead.

What is Angular CanActivateFn?

CanActivateFn is a function that acts as a route guard that is passed to the canActivate property in Angular's routing setup. It allows developers to specify the requirements that must be fulfilled before going to a specific route.

Signature of CanActivateFn

The CanActivateFn function accepts the following parameters.

  • route: An activated Route object that contains information about the current route.
  • state: The current RouterStateSnapshot, which contains information about the router's current state, including the URL and other metadata.

The function can return a Observable, a Promise, or a boolean value that determines if the route can be accessed or activated.

CanActivate in Route Configuration

The canActivate attribute of the Route interface defines an array of CanActivateFn functions to be used as route guards. If any of these functions return false, access to the route is denied.

Using mapToCanActivate for Class-Based Guards

Angular offers the mapToCanActivate function, which allows you to convert classes with a canActivate method into an array of corresponding CanActivateFn functions. This helps to incorporate the previous class-based route guards and facilitates switching to the new functional model.

Using CanActivateFn in Angular 17 Applications

To see an example of CanActivateFn in an Angular 17 application, let us take these steps.:

1. Add a CanActivateFn Function

Write a function that returns a boolean, Observable<boolean>, or Promise<boolean>. It will be used to check whether a route can be accessed. This is the code example:

import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from './auth.service';



export const authGuard: CanActivateFn = (route, state) => {

  const authService = inject(AuthService);
  const router = inject(Router);

  if (authService.isLoggedIn()) {
    return true;
  }
  router.navigate(['/login']);
  return false;
};

We define an authGuard function of type CanActivateFn which takes the route and state as parameters. In the body of the guard, we inject the router and authentication service and check if the user is logged in. In this case we return true otherwise we use the navigate() method of the router to navigate to the login URL and we return false from the CanActivateFn function.

2. Use canActivate in Route Configuration

After writing the CanActivateFn function, we need to add it to the route configuration to protect routes. Here is an example routes file

import { Routes } from '@angular/router';
import { LoginComponent } from './pages/login/login.component';
import { SignupComponent } from './pages/signup/signup.component';
import { AdminComponent } from './pages/admin/admin.component';
import { authGuard } from './auth/auth.guard';

export const routes: Routes = [
    {
        path: '', redirectTo: '/login', pathMatch: 'full'
    },
    {
        path: 'login', component: LoginComponent
    },
    {
        path: 'signup', component: SignupComponent
    },

    {
        path: 'admin', component: AdminComponent, canActivate: [authGuard]
    }
];

Notice that the admin component is protected by the authGuard function. If the function returns false, navigation to the AdminComponent is denied.

Using mapToCanActivate for Old Class Guards

If you have class-based guards with a canActivate method, you have to use mapToCanActivate to convert them into CanActivateFn functions. For example:

import { mapToCanActivate } from '@angular/router';
import { AuthGuard } from './guards/authguard.guard';

const authGuard = mapToCanActivate([AuthGuard]);

const routes: Routes = [
  { path: 'admin', component: AdminComponent, canActivate: authGuard },
];

Here, mapToCanActivate converts AuthGuard into a CanActivateFn function that can be used in the functional approach.

Conclusion

When developing a web application, it is likely that you will use routing at some time.

However, lost often not all routes may be accessed by everyone. For example, you might not allow an anonymous user to access the admin page of the application. Angular, like many other frameworks, has addressed this issue.

In this article, we've looked at what guards are, how to utilize them, and some specific use cases in various settings where route guards shine.

To summarize, CanActivateFn is a versatile and modern way to build route guards in Angular 17. It provides a straightforward functional way, with the flexibility to inject services and add complex conditional logic. The canActivate attribute in route configurations enables you to add arrays of CanActivateFn functions, giving you powerful ways in protecting your components. The mapToCanActivate function is handy for migrating from old class-based guards to the new functional approach while maintaining backward compatibility.