typescript
32 lines · 5 steps
How a functional route guard works in Angular
A CanActivateFn checks authentication and either allows navigation or redirects to the login page.
Explained by
highlit
1import { inject } from '@angular/core';
2import {
3 ActivatedRouteSnapshot,
4 CanActivateFn,
5 Router,
6 RouterStateSnapshot,
7 UrlTree,
8} from '@angular/router';
9import { map, take } from 'rxjs/operators';
10import { Observable } from 'rxjs';
11import { AuthService } from './auth.service';
12
13export const authGuard: CanActivateFn = (
14 route: ActivatedRouteSnapshot,
15 state: RouterStateSnapshot,
16): Observable<boolean | UrlTree> => {
17 const auth = inject(AuthService);
18 const router = inject(Router);
19
20 return auth.isAuthenticated$.pipe(
21 take(1),
22 map((isAuthenticated) => {
23 if (isAuthenticated) {
24 return true;
25 }
26
27 return router.createUrlTree(['/login'], {
28 queryParams: { returnUrl: state.url },
29 });
30 }),
31 );
32};
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Functional guards use inject() to grab services instead of a constructor, keeping them lightweight and tree-shakable.
- 2take(1) completes the stream after one emission so the guard resolves promptly instead of leaving navigation hanging.
- 3Returning a UrlTree from a guard is Angular's idiom for redirecting rather than manually calling navigate.
Related explainers
typescript
import { Injectable, UnauthorizedException } from '@nestjs/common'; import { PassportStrategy } from '@nestjs/passport'; import { ExtractJwt, Strategy } from 'passport-jwt'; import { ConfigService } from '@nestjs/config';
How a JWT strategy authenticates in NestJS
authentication
jwt
passport
Intermediate
7 steps
typescript
import { Injectable } from '@angular/core'; import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpErrorResponse } from '@angular/common/http'; import { BehaviorSubject, Observable, throwError } from 'rxjs'; import { catchError, filter, take, switchMap } from 'rxjs/operators';
Refreshing auth tokens in an Angular interceptor
http-interceptor
token-refresh
rxjs
Advanced
8 steps
go
package auth import ( "net/http"
Setting and reading secure session cookies in Go
cookies
session-management
security
Intermediate
6 steps
typescript
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common'; import { GqlExecutionContext } from '@nestjs/graphql'; import { Reflector } from '@nestjs/core'; import { JwtService } from '@nestjs/jwt';
How a GraphQL auth guard works in NestJS
authentication
authorization
jwt
Intermediate
7 steps
python
import os from datetime import timedelta
Class-based config in a Flask app factory
configuration
app-factory
inheritance
Intermediate
7 steps
typescript
type ResizeCallback = (size: { width: number; height: number }) => void; export function observeResize(callback: ResizeCallback, delay = 150) { let timeoutId: ReturnType<typeof setTimeout> | undefined;
Debouncing window resize in TypeScript
debounce
closures
event-listeners
Intermediate
6 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/how-a-functional-route-guard-works-in-angular-explained-typescript-7a02/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.