US-MGN001-004: Recuperacion de Password
Identificacion
| Campo |
Valor |
| ID |
US-MGN001-004 |
| Modulo |
MGN-001 Auth |
| Sprint |
Sprint 2 |
| Prioridad |
P1 - Alta |
| Story Points |
8 |
| Estado |
Ready |
| Autor |
System |
| Fecha |
2025-12-05 |
Historia de Usuario
Como usuario que olvido su contraseña
Quiero poder recuperar el acceso a mi cuenta mediante un proceso seguro
Para no quedar bloqueado del sistema sin necesidad de contactar soporte
Descripcion
El usuario que olvido su contraseña debe poder solicitar un enlace de recuperacion por email. Este enlace le permitira establecer una nueva contraseña de forma segura, invalidando el acceso anterior.
Contexto
- Los usuarios olvidan contraseñas con frecuencia
- El proceso debe ser autoservicio
- Debe ser seguro contra ataques de enumeracion de emails
Criterios de Aceptacion
Escenario 1: Solicitud de recuperacion exitosa
Given un usuario registrado con email "user@example.com"
When solicita recuperacion de password en POST /api/v1/auth/password/request-reset
Then el sistema responde con status 200
And el mensaje es "Si el email esta registrado, recibiras instrucciones"
And se genera un token de recuperacion con expiracion de 1 hora
And se envia email con enlace de recuperacion
And tokens anteriores de ese usuario son invalidados
Escenario 2: Solicitud para email inexistente (seguridad)
Given un email "noexiste@example.com" que NO existe en el sistema
When solicita recuperacion de password
Then el sistema responde con status 200
And el mensaje es IDENTICO al caso exitoso
And NO se revela que el email no existe
And NO se envia ningun email
Escenario 3: Cambio de password exitoso
Given un usuario con token de recuperacion valido
And el token no ha expirado (<1 hora)
And el token no ha sido usado
When envia nuevo password cumpliendo requisitos
Then el sistema actualiza el password hasheado
And invalida el token de recuperacion
And cierra TODAS las sesiones activas del usuario
And envia email confirmando el cambio
And responde con status 200
Escenario 4: Token de recuperacion expirado
Given un token de recuperacion emitido hace mas de 1 hora
When el usuario intenta usarlo
Then el sistema responde con status 400
And el mensaje es "Token de recuperacion expirado"
Escenario 5: Token ya utilizado
Given un token de recuperacion que ya fue usado
When el usuario intenta usarlo nuevamente
Then el sistema responde con status 400
And el mensaje es "Token de recuperacion ya utilizado"
Escenario 6: Password no cumple requisitos
Given un token de recuperacion valido
When el usuario envia un password que no cumple requisitos
| Escenario | Password | Error |
| Muy corto | "abc123" | "Password debe tener minimo 8 caracteres" |
| Sin mayuscula | "password123!" | "Debe incluir una mayuscula" |
| Sin numero | "Password!!" | "Debe incluir un numero" |
| Sin especial | "Password123" | "Debe incluir caracter especial" |
Then el sistema responde con status 400
And el mensaje indica el requisito faltante
And se incrementa el contador de intentos del token
Escenario 7: Password igual a anterior
Given un token de recuperacion valido
And el usuario tiene historial de passwords
When envia un password igual a uno de los ultimos 5
Then el sistema responde con status 400
And el mensaje es "No puedes usar una contraseña anterior"
Escenario 8: Validacion de token
Given un token de recuperacion
When el usuario navega a la pagina de reset con ese token
Then el frontend valida el token GET /api/v1/auth/password/validate-token/:token
And si es valido muestra el formulario
And si no es valido muestra mensaje de error apropiado
Mockup / Wireframe
Pagina de Solicitud
+------------------------------------------------------------------+
| ERP SUITE |
+------------------------------------------------------------------+
| |
| ╔═══════════════════════════════════╗ |
| ║ RECUPERAR CONTRASEÑA ║ |
| ╚═══════════════════════════════════╝ |
| |
| Ingresa tu correo electronico y te enviaremos |
| instrucciones para restablecer tu contraseña. |
| |
| Correo electronico |
| +---------------------------+ |
| | user@example.com | |
| +---------------------------+ |
| |
| [===== ENVIAR INSTRUCCIONES =====] |
| |
| ← Volver al login |
| |
+------------------------------------------------------------------+
Confirmacion de Envio
+------------------------------------------------------------------+
| ERP SUITE |
+------------------------------------------------------------------+
| |
| ╔═══════════════════════════════════╗ |
| ║ EMAIL ENVIADO ✉️ ║ |
| ╚═══════════════════════════════════╝ |
| |
| Si el email esta registrado, recibiras |
| instrucciones en los proximos minutos. |
| |
| Revisa tu bandeja de entrada y la carpeta |
| de spam. |
| |
| [===== VOLVER AL LOGIN =====] |
| |
| ¿No recibiste el email? |
| Espera 5 minutos y vuelve a intentar. |
| |
+------------------------------------------------------------------+
Pagina de Reset
+------------------------------------------------------------------+
| ERP SUITE |
+------------------------------------------------------------------+
| |
| ╔═══════════════════════════════════╗ |
| ║ NUEVA CONTRASEÑA ║ |
| ╚═══════════════════════════════════╝ |
| |
| Nueva contraseña |
| +---------------------------+ |
| | •••••••••••• | [👁] |
| +---------------------------+ |
| [████████░░] Fuerte |
| |
| ✓ Minimo 8 caracteres |
| ✓ Al menos una mayuscula |
| ✗ Al menos un numero |
| ✗ Al menos un caracter especial |
| |
| Confirmar contraseña |
| +---------------------------+ |
| | •••••••••••• | [👁] |
| +---------------------------+ |
| |
| [===== CAMBIAR CONTRASEÑA =====] |
| |
+------------------------------------------------------------------+
Token Invalido
+------------------------------------------------------------------+
| ERP SUITE |
+------------------------------------------------------------------+
| |
| ╔═══════════════════════════════════╗ |
| ║ ⚠️ ENLACE INVALIDO ║ |
| ╚═══════════════════════════════════╝ |
| |
| El enlace de recuperacion ha expirado |
| o ya fue utilizado. |
| |
| [===== SOLICITAR NUEVO ENLACE =====] |
| |
+------------------------------------------------------------------+
Notas Tecnicas
API
// 1. Solicitar recuperacion
POST /api/v1/auth/password/request-reset
{
"email": "user@example.com"
}
// Response 200
{
"message": "Si el email esta registrado, recibiras instrucciones"
}
// 2. Validar token
GET /api/v1/auth/password/validate-token/a1b2c3d4e5f6...
// Response 200 (valido)
{
"valid": true,
"email": "u***@example.com"
}
// Response 200 (invalido)
{
"valid": false,
"reason": "expired" | "used" | "invalid"
}
// 3. Cambiar password
POST /api/v1/auth/password/reset
{
"token": "a1b2c3d4e5f6...",
"newPassword": "NewSecurePass123!",
"confirmPassword": "NewSecurePass123!"
}
// Response 200
{
"message": "Contraseña actualizada exitosamente"
}
Template de Email
Asunto: Recuperacion de contraseña - ERP Suite
<h2>Hola {{firstName}},</h2>
<p>Recibimos una solicitud para restablecer tu contraseña.</p>
<p>Haz clic en el siguiente enlace para crear una nueva contraseña:</p>
<a href="{{resetUrl}}" style="...">Restablecer Contraseña</a>
<p><strong>Este enlace expira en 1 hora.</strong></p>
<p>Si no solicitaste este cambio, ignora este email. Tu contraseña
permanecera sin cambios.</p>
<p>Por seguridad, nunca compartas este enlace con nadie.</p>
<hr>
<small>IP: {{ipAddress}} | Fecha: {{timestamp}}</small>
Validaciones de Password
const PASSWORD_RULES = {
minLength: 8,
maxLength: 128,
requireUppercase: true,
requireLowercase: true,
requireNumber: true,
requireSpecial: true,
specialChars: '!@#$%^&*()_+-=[]{}|;:,.<>?',
historyCount: 5, // No repetir ultimos 5
};
const PASSWORD_REGEX = /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$/;
Definicion de Done
Dependencias
Requiere
| Item |
Descripcion |
| EmailService |
Para enviar emails |
| Tabla password_reset_tokens |
Almacenar tokens |
| Tabla password_history |
Historial de passwords |
| US-MGN001-002 |
Logout-all functionality |
Bloquea
| Item |
Descripcion |
| - |
No bloquea otras historias |
Estimacion
| Tarea |
Horas |
| Backend: requestPasswordReset() |
3h |
| Backend: validateResetToken() |
2h |
| Backend: resetPassword() |
4h |
| Backend: Password validation |
2h |
| Backend: Email templates |
2h |
| Backend: Tests |
3h |
| Frontend: ForgotPasswordPage |
3h |
| Frontend: ResetPasswordPage |
4h |
| Frontend: Password strength |
2h |
| Frontend: Tests |
2h |
| Total |
27h |
Referencias
Historial
| Version |
Fecha |
Autor |
Cambios |
| 1.0 |
2025-12-05 |
System |
Creacion inicial |