workspace-v1/shared/libs/auth/_reference/jwt.strategy.reference.ts
Adrian Flores Cortes 967ab360bb Initial commit: Workspace v1 with 3-layer architecture
Structure:
- control-plane/: Registries, SIMCO directives, CI/CD templates
- projects/: Gamilit, ERP-Suite, Trading-Platform, Betting-Analytics
- shared/: Libs catalog, knowledge-base

Key features:
- Centralized port, domain, database, and service registries
- 23 SIMCO directives + 6 fundamental principles
- NEXUS agent profiles with delegation rules
- Validation scripts for workspace integrity
- Dockerfiles for all services
- Path aliases for quick reference

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-23 00:35:19 -06:00

97 lines
2.8 KiB
TypeScript

/**
* JWT STRATEGY - REFERENCE IMPLEMENTATION
*
* @description Estrategia de autenticación JWT para NestJS/Passport.
* Valida tokens JWT y extrae payload del usuario.
*
* @usage Copiar y adaptar según necesidades del proyecto.
* @origin gamilit/apps/backend/src/modules/auth/strategies/jwt.strategy.ts
*/
import { Injectable, UnauthorizedException } from '@nestjs/common';
import { PassportStrategy } from '@nestjs/passport';
import { ExtractJwt, Strategy } from 'passport-jwt';
import { ConfigService } from '@nestjs/config';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
// Adaptar import según proyecto
// import { User } from '../entities';
/**
* Payload del JWT
*
* @property sub - ID del usuario (auth.users.id)
* @property email - Email del usuario
* @property role - Rol del usuario
* @property iat - Issued at (timestamp)
* @property exp - Expiration (timestamp)
*/
interface JwtPayload {
sub: string;
email: string;
role: string;
iat: number;
exp: number;
}
/**
* Usuario validado que se inyecta en req.user
*/
interface ValidatedUser {
id: string;
email: string;
role: string;
}
@Injectable()
export class JwtStrategy extends PassportStrategy(Strategy, 'jwt') {
constructor(
private readonly configService: ConfigService,
@InjectRepository(User, 'auth')
private readonly userRepository: Repository<User>,
) {
super({
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
ignoreExpiration: false,
secretOrKey: configService.get<string>('JWT_SECRET'),
});
}
/**
* Validar payload del JWT
*
* @description Este método es llamado por Passport después de verificar
* la firma y expiración del token. El valor retornado se asigna a req.user.
*
* @param payload - Payload decodificado del JWT
* @returns Usuario validado para inyectar en request
* @throws UnauthorizedException si el usuario no existe o está inactivo
*/
async validate(payload: JwtPayload): Promise<ValidatedUser> {
// Opción 1: Solo validar que el payload es válido (más rápido)
// return { id: payload.sub, email: payload.email, role: payload.role };
// Opción 2: Verificar que el usuario existe en BD (más seguro)
const user = await this.userRepository.findOne({
where: { id: payload.sub },
select: ['id', 'email', 'role'],
});
if (!user) {
throw new UnauthorizedException('Usuario no encontrado');
}
// Opción 3: También verificar status (si aplica)
// if (user.status !== 'active') {
// throw new UnauthorizedException('Usuario inactivo');
// }
return {
id: user.id,
email: user.email,
role: user.role,
};
}
}