RF-AUTH-001: Login con Email y Password
Identificacion
| Campo |
Valor |
| ID |
RF-AUTH-001 |
| Modulo |
MGN-001 |
| Nombre Modulo |
Auth - Autenticacion |
| Prioridad |
P0 |
| Complejidad |
Media |
| Estado |
Aprobado |
| Autor |
System |
| Fecha |
2025-12-05 |
Descripcion
El sistema debe permitir a los usuarios autenticarse utilizando su correo electronico y contraseña. Al autenticarse exitosamente, el sistema debe generar tokens JWT (access token y refresh token) que permitan al usuario acceder a los recursos protegidos del sistema.
Contexto de Negocio
La autenticacion es la puerta de entrada al sistema ERP. Sin un mecanismo robusto de login, no es posible garantizar la seguridad de los datos ni el aislamiento multi-tenant. Este requerimiento es la base de toda la seguridad del sistema.
Criterios de Aceptacion
Ejemplos de Verificacion
Scenario: Login exitoso
Given un usuario registrado con email "user@example.com" y password "SecurePass123!"
When el usuario envia credenciales correctas al endpoint /api/v1/auth/login
Then el sistema responde con status 200
And el body contiene accessToken y refreshToken
And se registra el login en session_history
Scenario: Login fallido por password incorrecto
Given un usuario registrado con email "user@example.com"
When el usuario envia password incorrecto
Then el sistema responde con status 401
And el mensaje es "Credenciales invalidas"
And se incrementa el contador de intentos fallidos
Scenario: Cuenta bloqueada por intentos fallidos
Given un usuario con 5 intentos fallidos de login
When el usuario intenta hacer login nuevamente
Then el sistema responde con status 423
And el mensaje indica que la cuenta esta bloqueada
Reglas de Negocio
| ID |
Regla |
Validacion |
| RN-001 |
El email debe ser unico por tenant |
Constraint UNIQUE(tenant_id, email) |
| RN-002 |
El password debe tener minimo 8 caracteres |
Validacion en DTO |
| RN-003 |
El password debe incluir mayuscula, minuscula, numero |
Regex validation |
| RN-004 |
Maximo 5 intentos fallidos antes de bloqueo |
Contador en BD |
| RN-005 |
El bloqueo dura 30 minutos |
Campo locked_until en users |
| RN-006 |
Los tokens deben incluir tenant_id en el payload |
JWT payload |
| RN-007 |
El access token expira en 15 minutos |
JWT exp claim |
| RN-008 |
El refresh token expira en 7 dias |
JWT exp claim |
Excepciones
- Si el usuario tiene 2FA habilitado, el login genera un token temporal y requiere verificacion adicional
- Los superadmins pueden acceder a multiples tenants (tenant_id opcional en su caso)
Impacto en Capas
Database
| Elemento |
Accion |
Descripcion |
| Schema |
usar |
core_auth |
| Tabla |
usar |
users - verificar credenciales |
| Tabla |
usar |
sessions - registrar login |
| Tabla |
crear |
login_attempts - control de intentos |
| Columna |
agregar |
users.failed_login_attempts |
| Columna |
agregar |
users.locked_until |
| Indice |
crear |
idx_users_email_tenant |
Backend
| Elemento |
Accion |
Descripcion |
| Service |
crear |
AuthService.login() |
| Service |
crear |
TokenService.generateTokens() |
| Controller |
crear |
AuthController.login() |
| DTO |
crear |
LoginDto |
| DTO |
crear |
LoginResponseDto |
| Endpoints |
crear |
POST /api/v1/auth/login |
| Guard |
crear |
ThrottlerGuard para rate limiting |
Frontend
| Elemento |
Accion |
Descripcion |
| Pagina |
crear |
LoginPage |
| Componente |
crear |
LoginForm |
| Store |
crear |
authStore |
| Service |
crear |
authService.login() |
| Hook |
crear |
useAuth |
Dependencias
Depende de (Bloqueantes)
| ID |
Requerimiento |
Estado |
| - |
Ninguna (es el primer RF) |
- |
Dependencias Relacionadas (No bloqueantes)
| ID |
Requerimiento |
Relacion |
| RF-AUTH-002 |
JWT Tokens |
Genera tokens |
| RF-AUTH-003 |
Refresh Token |
Genera refresh token |
| RF-AUTH-004 |
Logout |
Usa misma sesion |
Mockups / Wireframes
Pantalla de Login
+------------------------------------------------------------------+
| ERP SUITE |
+------------------------------------------------------------------+
| |
| +-------------------------+ |
| | INICIAR SESION | |
| +-------------------------+ |
| |
| Email: |
| +-------------------------+ |
| | user@example.com | |
| +-------------------------+ |
| |
| Password: |
| +-------------------------+ |
| | •••••••••••• | |
| +-------------------------+ |
| |
| [ ] Recordarme |
| |
| [ INICIAR SESION ] |
| |
| Olvidaste tu password? |
| |
+------------------------------------------------------------------+
Estados de UI
| Estado |
Comportamiento |
| Loading |
Boton deshabilitado, spinner visible |
| Error |
Toast rojo con mensaje de error |
| Success |
Redirect a dashboard |
| Blocked |
Mensaje de cuenta bloqueada con tiempo restante |
Datos de Prueba
Escenarios
| Escenario |
Datos Entrada |
Resultado Esperado |
| Happy path |
email: "test@erp.com", password: "Test123!" |
200, tokens generados |
| Email no existe |
email: "noexiste@erp.com" |
401, "Credenciales invalidas" |
| Password incorrecto |
password: "wrongpass" |
401, "Credenciales invalidas" |
| Cuenta bloqueada |
5+ intentos fallidos |
423, "Cuenta bloqueada" |
| Email vacio |
email: "" |
400, "Email es requerido" |
| Password muy corto |
password: "123" |
400, "Password minimo 8 caracteres" |
Estimacion
| Capa |
Story Points |
Notas |
| Database |
2 |
Tablas ya existen, solo columnas nuevas |
| Backend |
5 |
Service, Controller, DTOs, Guards |
| Frontend |
3 |
LoginPage, Form, Store |
| Total |
10 |
|
Notas Adicionales
- Usar bcrypt con salt rounds = 12 para hash de passwords
- Los tokens JWT deben firmarse con algoritmo RS256 (asymmetric)
- Implementar rate limiting: max 10 requests/minuto por IP
- Loguear todos los intentos de login (exitosos y fallidos) para auditoria
- Considerar implementar CAPTCHA despues de 3 intentos fallidos
Historial de Cambios
| Version |
Fecha |
Autor |
Cambios |
| 1.0 |
2025-12-05 |
System |
Creacion inicial |
Aprobaciones
| Rol |
Nombre |
Fecha |
Firma |
| Analista |
System |
2025-12-05 |
[x] |
| Tech Lead |
- |
- |
[ ] |
| Product Owner |
- |
- |
[ ] |