235 lines
8.4 KiB
Markdown
235 lines
8.4 KiB
Markdown
# 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
|
|
|
|
- [x] **CA-001:** El sistema debe aceptar email y password como credenciales de login
|
|
- [x] **CA-002:** El sistema debe validar que el email exista en la base de datos
|
|
- [x] **CA-003:** El sistema debe verificar el password usando bcrypt
|
|
- [x] **CA-004:** El sistema debe generar un access token JWT con expiracion de 15 minutos
|
|
- [x] **CA-005:** El sistema debe generar un refresh token JWT con expiracion de 7 dias
|
|
- [x] **CA-006:** El sistema debe registrar el login en el historial de sesiones
|
|
- [x] **CA-007:** El sistema debe devolver error 401 si las credenciales son invalidas
|
|
- [x] **CA-008:** El sistema debe bloquear la cuenta despues de 5 intentos fallidos
|
|
|
|
### Ejemplos de Verificacion
|
|
|
|
```gherkin
|
|
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 | - | - | [ ] |
|