Security & Navigation
Guards
Guards are the gatekeepers of your app. They decide based on logic (login status, roles) whether a user can access a route or is redirected.
In the past, I often made the mistake: "If the user is not an admin, I'll just hide the button in the menu."
The problem? A clever user simply types /admin in the address bar – and gets in.
This is a security vulnerability. A Guard solves this. It intercepts before navigation. Before Angular even loads the component code (Lazy Loading), the guard checks the credentials. If they don't match: Access denied.
1. The Simulation
Try to access the Admin Dashboard. Without login, the guard will immediately bounce you back to the login page. Only when the switch is active will the gatekeeper let you pass.
2. Implementation
Since Angular 15+, we use Functional Guards. Forget the old Classes with boilerplate. A guard is now just a simple arrow function.
import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService);
const router = inject(Router);
// 1. Check: Is the user logged in?
if (authService.isLoggedIn()) {
return true; // Gate opens
}
// 2. Access denied -> Redirect to login
// PRO TIP: We pass the target URL (state.url) as a query param.
// This allows us to redirect the user back to the admin page
// immediately after they log in.
return router.createUrlTree(['/login'], {
queryParams: { returnUrl: state.url }
});
};💡 Why Functional?
- Less Code: No Classes, no Decorators.
- Inject(): You can use
inject()directly inside the function. - Flexible: Easier to pass parameters to guards.
Step 2: Protect the Route
In the routing configuration, we simply attach the function. Angular handles the rest.
export const routes: Routes = [
{
path: 'admin',
loadComponent: () => import('./admin/admin.component').then(m => m.Admin),
// The guard is placed here.
// You can add multiple guards: [AuthGuard, RoleGuard]
canActivate: [authGuard]
}
];Data Protection (CanDeactivate): There is also the opposite guard. canDeactivate checks if a user is allowed to LEAVE. I use this for forms: If the user tries to close the tab with unsaved data, the guard blocks the exit and asks for confirmation.