🔐 Servicio de Recuperación de Contraseña en Vertical
Estas APIs permiten a los usuarios recuperar y restablecer la contraseña asociada a una vertical específica. Están diseñadas para garantizar seguridad, anonimato en la validación y una experiencia clara para el usuario.
🔒 Autenticación
Estas APIs no requieren autenticación JWT, ya que se utilizan para el flujo de recuperación de acceso. Sin embargo, siguen estándares de validación estrictos para prevenir abusos y asegurar que la información no se exponga.
🧠 Controladores
Los siguientes controladores gestionan el flujo completo de recuperación de contraseña.
1. requestPasswordReset
Solicita el envío de un código de recuperación al correo del usuario si el correo y la vertical existen.
Ruta del archivo:
src/api/user-endpoints/controllers/request-password-reset.ts
2. passwordReset
Valida el código de recuperación y establece una nueva contraseña si todo es correcto.
Ruta del archivo:
src/api/user-endpoints/controllers/password-reset.ts
⚙️ Funcionamiento Interno
1. requestPasswordReset
Esta API realiza los siguientes pasos:
-
Validación de entrada:
validateKeys(ctx.request.body, requestValidKeys, FIELD_ROOT);validateRequiredFields(body, requestVerificationKeys);Se valida que los campos requeridos
emailyverticalexistan y que no haya campos adicionales. -
Búsqueda de usuario:
const strapiUser = await findOne(USER,null,{ email },COMPONENT_NAME_USER_PASSWORDS);Si no se encuentra, se retorna 200 igualmente (para evitar exponer si el correo está registrado o no).
-
Verificación de vertical:
const existingPassword = strapiUser.verticalsUserPasswords.find((pass) => pass.vertical === vertical);Si no tiene contraseña para esa vertical, se finaliza sin error visible.
-
Generación de código de recuperación:
const code = crypto.randomInt(100000, 999999).toString();const expiresAt = new Date(Date.now() + 15 * 60 * 1000); // 15 min
-
Actualización del documento del usuario:
await updateDocument(USER, strapiUser.documentId, {resetPasswordToken: code,resetPasswordTokenExpiration: expiresAt,}); -
Genera un codigo de 6 digitos y establece una expiración de 15 minutos.
-
Envío del correo de recuperación:
await sendEmail(email, subject, text(code, vertical), html(code));El idiomna en este API es un dato opcional, por defecto es
enEl idioma es validado con
validateLang(body.lang)para soportar diferentes lenguajes, para mas información vease Aquí.
2. passwordReset
Este controlador valida el código de recuperación y establece la nueva contraseña.
El idiomna en este API es un dato opcional, por defecto es en
-
Validación de entrada:
validateKeys(ctx.request.body, resetValidKeys, FIELD_ROOT);validateRequiredFields(body, resetVerificationKeys);validateFieldPatterns({ password },{ password: FIELD_VALIDATIONS.password }); -
Verificación de usuario y código:
const strapiUser = await findOne(USER,null,{ email },COMPONENT_NAME_USER_PASSWORDS);if (strapiUser.resetPasswordToken !== code ||new Date(strapiUser.resetPasswordTokenExpiration) < new Date())throw new Error(ERROR_INVALID_RESET_CODE); -
Actualización de contraseña:
await updateVerticalPassword(email, vertical, password); -
Limpieza de tokens de recuperación:
await updateDocument(USER, strapiUser.documentId, {resetPasswordToken: null,resetPasswordTokenExpiration: null,}); -
Envío de notificación de cambio:
await sendEmail(email, subject, text(vertical), html(vertical));
📤 Ejemplo de solicitud: requestPasswordReset
URL: /api/user-endpoints/request-password-reset
Método: POST
{ "email": "example@example.com", "vertical": "Finanzas", "lang": "es" //-> opcional default 'en'}📤 Ejemplo de solicitud: passwordReset
URL: /api/user-endpoints/password-reset
Método: POST
{ "email": "example@example.com", "vertical": "Inspiria", "password": "Newsecurepass123!", "code": "123456", "lang": "es" //-> opcional default 'en'}✅ Respuestas esperadas
✔️ Solicitud de código exitosa
{ "message": "If an account with this email exists, a recovery code has been sent."}✔️ Restablecimiento exitoso
{ "message": "Password updated succesfully."}❌ Código incorrecto o expirado
{ "data": null, "error": { "status": 400, "name": "Error", "message": "Invalid reset code", "details": {} }}📎 Notas adicionales
- El endpoint
requestPasswordResetresponde con éxito aunque el usuario no exista para evitar filtraciones. - Ambos controladores tienen validación estricta de estructura y contenido.
- La lógica está diseñada para ser segura, clara para el usuario final y resistente a ataques de enumeración de correos.
🔗 Funciones auxiliares
-
validateKeys,validateRequiredFields: validación de la estructura del body. -
validateFieldPatterns: asegura que contraseñas cumplan con las reglas.🐿️ -> Veanse aqui validaciones de campos.
-
findOne,updateDocument: funciones de acceso a la base de datos. -
sendEmail: abstracta el envío de correos con plantillas multilenguaje.🐿️ -> Veanse aqui strapi queries.
-
updateVerticalPassword: actualiza la contraseña cifrada de la vertical correspondiente.🐿️ -> Veanse aqui strapi passwords.
Documentación completa para desarrolladores backend que integren el flujo de recuperación y actualización de contraseña por vertical.