fg-portal-auth
v1.1.0
Published
Sistema de autenticación y guards para aplicaciones NestJS del Portal - Manejo de roles, permisos y apps mediante cookies
Downloads
4
Maintainers
Readme
fg-portal-auth
Sistema completo de autenticación y guards para aplicaciones NestJS del Portal. Maneja autenticación basada en JWT con soporte para cookies, roles de usuario, control de acceso por aplicaciones y sistema granular de permisos.
🚀 Características
- ✅ Autenticación JWT con soporte para cookies y headers
- ✅ Sistema de roles (ADMIN, GERENTE, LIDER, COLABORADOR)
- ✅ Control por aplicaciones - cada usuario puede tener acceso a múltiples apps
- ✅ Permisos granulares - control detallado de permisos por aplicación
- ✅ Guards listos para usar - SimpleAppGuard, UserRoleGuard
- ✅ Decoradores intuitivos - @Auth(), @AppAuth(), @User()
- ✅ TypeScript - Completamente tipado
- ✅ Estrategia JWT configurable - Extrae tokens de cookies y headers
📦 Instalación
npm install fg-portal-authDependencias requeridas
Este paquete requiere las siguientes dependencias en tu proyecto:
npm install @nestjs/common @nestjs/core @nestjs/passport passport passport-jwt reflect-metadata🔧 Configuración inicial
1. Crear tu JWT Strategy
En tu proyecto, extiende la BaseJwtStrategy:
// src/auth/strategy/jwt.strategy.ts
import { Injectable } from '@nestjs/common';
import { BaseJwtStrategy, JwtPayload, RequestUser } from 'fg-portal-auth';
import { UsersService } from '../../users/users.service';
@Injectable()
export class JwtStrategy extends BaseJwtStrategy {
constructor(private readonly usersService: UsersService) {
super('access_token'); // Nombre de la cookie (opcional)
}
async validate(payload: JwtPayload): Promise<RequestUser> {
return await this.usersService.findUserWithAppPermissions(
Number(payload.sub)
);
}
}2. Configurar tu AuthModule
// src/auth/auth.module.ts
import { Module } from '@nestjs/common';
import { PassportModule } from '@nestjs/passport';
import { JwtModule } from '@nestjs/jwt';
import { JwtStrategy } from './strategy/jwt.strategy';
import { UsersModule } from '../users/users.module';
@Module({
imports: [
PassportModule.register({ defaultStrategy: 'jwt' }),
JwtModule.register({
secret: process.env.JWT_SECRET,
signOptions: { expiresIn: '2h' },
}),
UsersModule,
],
providers: [JwtStrategy],
exports: [JwtStrategy, PassportModule],
})
export class AuthModule {}🛡️ Uso de los Guards
Autenticación básica con roles
import { Controller, Get, Delete } from '@nestjs/common';
import { Auth, ValidRoles, User, RequestUser } from 'fg-portal-auth';
@Controller('usuarios')
export class UsuariosController {
// Solo ADMIN y GERENTE pueden acceder
@Auth(ValidRoles.ADMIN, ValidRoles.GERENTE)
@Get()
findAll() {
return this.usuariosService.findAll();
}
// Solo ADMIN puede eliminar
@Auth(ValidRoles.ADMIN)
@Delete(':id')
remove(@User() user: RequestUser) {
console.log(`${user.name} está eliminando un usuario`);
return this.usuariosService.remove(id);
}
}Autenticación con aplicaciones y permisos
import { Controller, Get, Post, Put } from '@nestjs/common';
import { AppAuth, User, RequestUser } from 'fg-portal-auth';
@Controller('productos')
export class ProductosController {
// Requiere acceso a app "inventario"
@AppAuth('inventario')
@Get()
findAll() {
return this.productosService.findAll();
}
// Requiere acceso a app "inventario" + permiso "productos.read"
@AppAuth('inventario', ['productos.read'])
@Get(':id')
findOne() {
return this.productosService.findOne(id);
}
// Requiere múltiples permisos
@AppAuth('inventario', ['productos.write', 'productos.create'])
@Post()
create(@User() user: RequestUser, @Body() createDto: CreateProductoDto) {
console.log(`${user.name} está creando un producto`);
return this.productosService.create(createDto);
}
}Combinando diferentes validaciones
@Controller('reportes')
export class ReportesController {
// Primero valida roles, luego app y permisos
@Auth(ValidRoles.GERENTE, ValidRoles.ADMIN) // Solo gerentes o admin
@AppAuth('reportes', ['reportes.financieros.read']) // + app específica
@Get('financieros')
getReportesFinancieros(@User() user: RequestUser) {
return this.reportesService.getFinancieros(user);
}
}🎯 Decoradores disponibles
@Auth(...roles)
Autenticación básica con validación de roles.
@Auth(ValidRoles.ADMIN) // Solo admin
@Auth(ValidRoles.ADMIN, ValidRoles.GERENTE) // Admin o gerente@AppAuth(appName, permissions?)
Autenticación con validación de aplicación y permisos opcionales.
@AppAuth('inventario') // Solo acceso a app
@AppAuth('inventario', ['productos.read']) // App + permisos
@AppAuth('inventario', ['productos.read', 'productos.write'])@User()
Extrae el usuario autenticado del request.
@Get('profile')
getProfile(@User() user: RequestUser) {
return { message: `Hola ${user.name}` };
}Decoradores individuales
@UseGuards(AuthGuard(), SimpleAppGuard)
@RequireApp('inventario')
@RequirePermissions('productos.read', 'productos.write')
@Get()
findAll() { ... }
@UseGuards(AuthGuard(), UserRoleGuard)
@RoleProtected(ValidRoles.ADMIN)
@Delete(':id')
remove() { ... }🔍 Interfaces disponibles
RequestUser
Estructura del usuario en el request:
interface RequestUser {
id: number;
name: string;
lastName: string;
email: string;
role: ValidRoles;
apps: {
appId: number;
appName: string;
permissions: string[];
}[];
}ValidRoles
Enum con los roles del sistema:
enum ValidRoles {
ADMIN = 'ADMIN',
GERENTE = 'GERENTE',
LIDER = 'LIDER',
COLABORADOR = 'COLABORADOR'
}⚡ Guards incluidos
SimpleAppGuard
- ✅ Los ADMIN tienen acceso completo automáticamente
- ✅ Valida acceso a aplicaciones específicas
- ✅ Valida permisos granulares dentro de cada aplicación
- ✅ Requiere que el usuario tenga todos los permisos especificados
UserRoleGuard
- ✅ Valida que el usuario tenga uno de los roles especificados
- ✅ Permite acceso si no se especifican roles
- ✅ Mensajes de error informativos
🍪 Configuración de Cookies
El sistema extrae automáticamente el JWT de:
- Header Authorization (Bearer token)
- Cookie (por defecto:
access_token)
Para cambiar el nombre de la cookie:
@Injectable()
export class JwtStrategy extends BaseJwtStrategy {
constructor(private readonly usersService: UsersService) {
super('mi_token_custom'); // Cambia 'access_token' por 'mi_token_custom'
}
// ...
}🔐 Variables de entorno
# Requerida
JWT_SECRET=tu_secreto_super_seguro_aqui📝 Ejemplo completo
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import {
Auth,
AppAuth,
ValidRoles,
User,
RequestUser
} from 'fg-portal-auth';
@Controller()
export class AppController {
@Get('public')
getPublic() {
return { message: 'Esta ruta es pública' };
}
@Auth() // Cualquier usuario autenticado
@Get('protected')
getProtected(@User() user: RequestUser) {
return { message: `Hola ${user.name}, estás autenticado` };
}
@Auth(ValidRoles.ADMIN) // Solo admin
@Get('admin-only')
getAdminOnly() {
return { message: 'Solo para administradores' };
}
@AppAuth('inventario', ['productos.read']) // App específica + permisos
@Get('productos')
getProductos(@User() user: RequestUser) {
return {
message: `${user.name} tiene acceso a inventario/productos.read`
};
}
}🤝 Contribución
- Fork el proyecto
- Crea una feature branch (
git checkout -b feature/nueva-funcionalidad) - Commit tus cambios (
git commit -m 'Add: nueva funcionalidad') - Push a la branch (
git push origin feature/nueva-funcionalidad) - Abre un Pull Request
📄 Licencia
MIT © Portal Team
🆘 Soporte
Para problemas o preguntas:
- Revisa la documentación
- Busca en los issues existentes
- Crea un nuevo issue
Hecho con ❤️ por el equipo del Portal
