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

Walkthrough

Space play step click any line
Three takeaways
  1. 1Functional guards use inject() to grab services instead of a constructor, keeping them lightweight and tree-shakable.
  2. 2take(1) completes the stream after one emission so the guard resolves promptly instead of leaving navigation hanging.
  3. 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.

How a functional route guard works in Angular — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code