nestjssecuritytypescriptapi-design

Layered Security in NestJS: Composing Guards for Real-World APIs

Building secure APIs requires more than JWT validation. This article walks through composing multiple NestJS guards for authentication, email verification, role-based access, and resource ownership—patterns from a production academic project API.

ZakariaPublié 15 avril 202510 min de lecture
Layered Security in NestJS: Composing Guards for Real-World APIs — 1

Why Layered Guards?

A single auth middleware can't express the nuanced access rules real APIs need: verified email, specific roles, and resource ownership all vary by endpoint.

NestJS guards are the right abstraction—they compose cleanly and run in declaration order.

The Guard Stack

A typical protected endpoint uses four guards in sequence: AuthGuard validates JWT, VerifiedGuard checks email verification, RolesGuard checks role membership, and OwnershipGuard verifies resource ownership.

@UseGuards(AuthGuard, VerifiedGuard, RolesGuard, OwnershipGuard)
@Roles(Role.OWNER)
@Patch('projects/:id')
updateProject(@Param('id') id: string, @Body() dto: UpdateProjectDto) {
  return this.projectService.update(id, dto);
}

Ownership Guard Pattern

OwnershipGuard extracts the resource ID from route params, loads the entity from the database, and compares its ownerId field to the authenticated user's ID. This prevents users from modifying resources they don't own, even if they have the correct role.

Articles connexes

Envie de discuter de ce sujet ou de collaborer sur un projet ?