Skip to content

06. Authentication & Security

1. The Vanilla Mechanics

Security in a web application involves verifying the identity of a user (Authentication) and checking their permissions (Authorization). In Express, this is usually implemented as custom middleware.

Concept: Request Interception

  • Identity Verification: Checking for a JWT or session cookie in the headers.
  • Permission Checks: Ensuring the user has the required roles for a specific route.

The β€œRaw” Implementation (Example)

const authGuard = (req, res, next) => {
  const token = req.headers.authorization;
  if (token === 'valid-token') {
    req.user = { id: 1, role: 'admin' };
    next();
  } else {
    res.status(401).send('Unauthorized');
  }
};

const roleGuard = (role) => (req, res, next) => {
  if (req.user && req.user.role === role) {
    next();
  } else {
    res.status(403).send('Forbidden');
  }
};

app.get('/admin', authGuard, roleGuard('admin'), (req, res) => {
  res.send('Admin area');
});

Challenges:

  • Tightly Coupled: Security logic is mixed into the route definitions.
  • Inconsistency: Different developers may implement security differently across the app.
  • Complexity: Managing nested permissions can become complicated with plain middleware.

2. The NestJS Abstraction

NestJS uses Guards to handle authentication and authorization.

Key Advantages:

  • CanActivate: Guards implement the CanActivate interface, making the return value (true/false) the decision maker for the request.
  • Metadata Access: Guards can access metadata (like required roles) defined on the route using decorators.
  • DI Support: Inject other services directly into your Guards.

The NestJS Implementation:

import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';

@Injectable()
export class RolesGuard implements CanActivate {
  canActivate(context: ExecutionContext): boolean {
    const request = context.switchToHttp().getRequest();
    const user = request.user;
    return user && user.role === 'admin';
  }
}

// In the controller:
@UseGuards(RolesGuard)
@Get('admin')
findAll() {
  return 'Admin area';
}

3. Engineering Labs

  • Lab 6.1: Build an Express app with a custom auth middleware that validates a fake token and attaches a user object to the request.
  • Lab 6.2: Re-implement the security layer in NestJS using a Guard. Use the Reflector to read custom metadata (roles) from the route.