From harness-claude
Protects NestJS routes with @UseGuards for JWT authentication, CanActivate checks, role-based access control, and public route bypassing. Centralizes auth logic across controllers.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Protect routes with @UseGuards, CanActivate, JWT guards, and role-based access control
Implements NestJS guards and interceptors for authentication, authorization, logging, and request/response transformation. Covers CanActivate, ExecutionContext, and JWT patterns for cross-cutting concerns.
Provides NestJS patterns for modules, controllers, providers, DTO validation, guards, interceptors, config, and production TypeScript backends. Useful for structuring APIs, adding validation, and database integrations.
Guides NestJS API development with architecture, modules, DI, guards, interceptors, pipes, MongoDB/Mongoose integration, auth, DTOs, error handling, and production patterns.
Share bugs, ideas, or general feedback.
Protect routes with @UseGuards, CanActivate, JWT guards, and role-based access control
CanActivate and return true (allow) or false/throw (deny):@Injectable()
export class JwtAuthGuard implements CanActivate {
constructor(private jwtService: JwtService) {}
canActivate(context: ExecutionContext): boolean {
const request = context.switchToHttp().getRequest<Request>();
const token = this.extractToken(request);
if (!token) throw new UnauthorizedException();
try {
request['user'] = this.jwtService.verify(token, { secret: process.env.JWT_SECRET });
return true;
} catch {
throw new UnauthorizedException();
}
}
private extractToken(req: Request): string | undefined {
const [type, token] = req.headers.authorization?.split(' ') ?? [];
return type === 'Bearer' ? token : undefined;
}
}
@UseGuards(GuardClass) at the controller or handler level. Handler-level overrides controller-level.main.ts for app-wide auth: app.useGlobalGuards(new JwtAuthGuard(jwtService)). For DI in global guards, use APP_GUARD provider instead:providers: [{ provide: APP_GUARD, useClass: JwtAuthGuard }];
Reflector and custom decorators to build a roles guard:export const Roles = (...roles: string[]) => SetMetadata('roles', roles);
@Injectable()
export class RolesGuard implements CanActivate {
constructor(private reflector: Reflector) {}
canActivate(context: ExecutionContext): boolean {
const required = this.reflector.getAllAndOverride<string[]>('roles', [
context.getHandler(),
context.getClass(),
]);
if (!required) return true; // no roles required
const { user } = context.switchToHttp().getRequest();
return required.some((role) => user?.roles?.includes(role));
}
}
@Public() with a SetMetadata('isPublic', true) decorator to bypass global auth guards on specific routes.ExecutionContext is transport-agnostic — use context.switchToWs() for WebSockets and context.switchToRpc() for microservices.Guards run after middleware but before interceptors and pipes in the NestJS request lifecycle. They are the correct place for authorization decisions because they have access to ExecutionContext, which provides the handler and class metadata.
Guard vs Middleware: Middleware runs before routing and has no knowledge of which handler will process the request. Guards run after routing with full handler context, making them the right tool for authorization logic that depends on route metadata (roles, permissions).
Throwing vs returning false: Throwing UnauthorizedException (or any HttpException) is preferred over returning false. Returning false causes NestJS to throw a generic ForbiddenException (403), which may not communicate the correct HTTP status.
Multiple guards: @UseGuards(AuthGuard, RolesGuard) applies guards in order. If AuthGuard throws, RolesGuard never runs. Compose authentication and authorization as separate guards for clean separation of concerns.
Passport integration: @nestjs/passport provides AuthGuard('jwt'), AuthGuard('local'), etc. that wrap Passport strategies. Use it when you need OAuth2, SAML, or complex multi-strategy auth flows.
https://docs.nestjs.com/guards