Guard System Deep Dive
NestJS guards used for authentication, authorization, and tenant isolation.
Guard Execution Order
Core Guards
TenantPermissionGuard
The most commonly used guard. Validates:
- User is authenticated (JWT valid)
- User belongs to the requested tenant
- User has required permissions
@UseGuards(TenantPermissionGuard)
@Permissions(PermissionsEnum.ORG_EMPLOYEES_VIEW)
@Get()
async findAll() {}
RoleGuard
Restricts access by user role:
@UseGuards(RoleGuard)
@Roles(RolesEnum.SUPER_ADMIN, RolesEnum.ADMIN)
@Delete(':id')
async delete(@Param('id') id: string) {}
PermissionGuard
Checks specific permissions:
@UseGuards(PermissionGuard)
@Permissions(PermissionsEnum.INVOICES_EDIT)
@Put(':id')
async update() {}
OrganizationPermissionGuard
Validates organization-level access:
@UseGuards(OrganizationPermissionGuard)
@Get()
async findByOrg() {}
Guard Hierarchy
| Guard | Validates | Usage |
|---|---|---|
AuthGuard('jwt') | JWT token valid | All endpoints |
TenantBaseGuard | Tenant exists in request | Most endpoints |
TenantPermissionGuard | Tenant + permissions | CRUD operations |
RoleGuard | User role matches | Admin endpoints |
PermissionGuard | Specific permission | Feature access |
OrganizationPermissionGuard | Org membership | Org endpoints |
Creating Custom Guards
@Injectable()
export class ProjectMemberGuard implements CanActivate {
async canActivate(context: ExecutionContext): Promise<boolean> {
const request = context.switchToHttp().getRequest();
const projectId = request.params.projectId;
const userId = request.user.id;
return this.projectService.isMember(projectId, userId);
}
}
Related Pages
- Request Lifecycle — full request flow
- Interceptor Patterns — interceptors
- Testing Guards — guard testing