/** * JWT AUTH GUARD - REFERENCE IMPLEMENTATION * * @description Guard de autenticación JWT para proteger rutas. * Activa la estrategia JWT y maneja errores de autenticación. * * @usage * ```typescript * @Get('protected') * @UseGuards(JwtAuthGuard) * getProtectedData(@Request() req) { * return req.user; * } * ``` * * @origin gamilit/apps/backend/src/modules/auth/guards/jwt-auth.guard.ts */ import { Injectable, ExecutionContext, UnauthorizedException } from '@nestjs/common'; import { AuthGuard } from '@nestjs/passport'; import { Reflector } from '@nestjs/core'; /** * Metadata key para rutas públicas */ export const IS_PUBLIC_KEY = 'isPublic'; @Injectable() export class JwtAuthGuard extends AuthGuard('jwt') { constructor(private readonly reflector: Reflector) { super(); } /** * Determinar si la ruta requiere autenticación * * @description Verifica el decorador @Public() antes de activar el guard. * Si la ruta es pública, permite el acceso sin token. */ canActivate(context: ExecutionContext) { // Verificar si la ruta tiene @Public() const isPublic = this.reflector.getAllAndOverride(IS_PUBLIC_KEY, [ context.getHandler(), context.getClass(), ]); if (isPublic) { return true; } // Activar validación JWT normal return super.canActivate(context); } /** * Manejar resultado de autenticación * * @description Personaliza el mensaje de error cuando falla la autenticación. */ handleRequest(err: Error | null, user: any, info: Error | null) { if (err || !user) { if (info?.message === 'jwt expired') { throw new UnauthorizedException('Token expirado'); } if (info?.message === 'No auth token') { throw new UnauthorizedException('Token no proporcionado'); } throw new UnauthorizedException('No autorizado'); } return user; } } // ============ DECORADOR PUBLIC ============ import { SetMetadata } from '@nestjs/common'; /** * Decorador para marcar rutas como públicas * * @usage * ```typescript * @Public() * @Get('health') * healthCheck() { * return { status: 'ok' }; * } * ``` */ export const Public = () => SetMetadata(IS_PUBLIC_KEY, true);