4.0 KiB
4.0 KiB
RF-MGN-001-001: Autenticación de Usuarios
Módulo: MGN-001 - Fundamentos Prioridad: P0 (MVP) Story Points: 8 Estado: Definido Fecha: 2025-11-23
Descripción
El sistema debe permitir a los usuarios autenticarse de forma segura utilizando email y contraseña, con soporte para multi-tenancy (cada tenant tiene sus propios usuarios aislados).
Actores
- Actor Principal: Usuario (cualquier rol)
- Actores Secundarios: Sistema de auditoría
Precondiciones
- El usuario debe tener una cuenta activa en el tenant
- El tenant debe estar activo (status='active')
- La base de datos debe estar disponible
Flujo Principal
- Usuario ingresa email y contraseña en formulario de login
- Sistema valida formato de email
- Sistema busca usuario por email dentro del tenant actual (subdomain)
- Sistema verifica contraseña usando bcrypt
- Sistema valida que usuario tenga status='active'
- Sistema genera JWT token con claims: user_id, tenant_id, roles, permissions
- Sistema registra evento de login en auth.login_history
- Sistema retorna JWT token + refresh token
- Usuario es redirigido a dashboard principal
Flujos Alternativos
FA-1: Credenciales Inválidas
- Si email no existe o contraseña incorrecta
- Sistema incrementa failed_login_attempts en auth.users
- Sistema retorna error 401: "Credenciales inválidas"
- Sistema registra intento fallido en auth.login_history
- Si failed_attempts >= 5, sistema bloquea cuenta por 30 minutos
FA-2: Usuario Inactivo
- Si user.status != 'active'
- Sistema retorna error 403: "Cuenta inactiva. Contacte al administrador"
FA-3: Tenant Inactivo
- Si tenant.status != 'active'
- Sistema retorna error 403: "Tenant suspendido"
FA-4: Cuenta Bloqueada Temporalmente
- Si failed_login_attempts >= 5 y último intento < 30 minutos
- Sistema retorna error 429: "Cuenta bloqueada temporalmente. Intente en X minutos"
Reglas de Negocio
- RN-1: Email debe ser único por tenant (no globalmente)
- RN-2: Contraseña debe tener mínimo 8 caracteres, 1 mayúscula, 1 número, 1 símbolo
- RN-3: JWT expira en 8 horas, refresh token en 30 días
- RN-4: Máximo 5 intentos fallidos antes de bloqueo temporal de 30 minutos
- RN-5: Contraseña debe hashearse con bcrypt (cost factor 12)
- RN-6: Después de login exitoso, failed_login_attempts se resetea a 0
Criterios de Aceptación
- Usuario con credenciales válidas puede autenticarse exitosamente
- JWT token contiene user_id, tenant_id, roles, permissions
- Sistema bloquea cuenta después de 5 intentos fallidos por 30 minutos
- Usuarios de diferentes tenants están completamente aislados
- Contraseñas se almacenan hasheadas (nunca plaintext)
- Login queda registrado en auth.login_history con IP y user agent
- Refresh token permite renovar JWT sin re-autenticación
- Usuario inactivo no puede autenticarse
- Tenant inactivo no permite login de usuarios
Entidades Involucradas
- Principales:
- auth.users (email, password_hash, status, failed_login_attempts)
- auth.tenants (subdomain, status)
- Relacionadas:
- auth.login_history (registro de auditoría)
- auth.sessions (tokens activos)
Referencias
Notas Técnicas
- Patrón Odoo: Similar a res.users authentication en odoo/base
- Patrón Gamilit: JWT + refresh tokens, multi-tenancy con RLS
- Seguridad: Implementar rate limiting (max 10 requests/min por IP)
- Backend: NestJS AuthModule + PassportJS + JWT strategy
- Frontend: React context + axios interceptors para auto-refresh
Dependencias
- RF Dependientes: Ninguno (es el RF base del sistema)
- Bloqueante para: Todos los demás RF (autenticación es prerequisito)