Skip to content

🔐 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:

  1. Validación de entrada:

    validateKeys(ctx.request.body, requestValidKeys, FIELD_ROOT);
    validateRequiredFields(body, requestVerificationKeys);

    Se valida que los campos requeridos email y vertical existan y que no haya campos adicionales.

  2. 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).

  3. 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.

  4. 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.

  1. 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 en

    El 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

  1. Validación de entrada:

    validateKeys(ctx.request.body, resetValidKeys, FIELD_ROOT);
    validateRequiredFields(body, resetVerificationKeys);
    validateFieldPatterns(
    { password },
    { password: FIELD_VALIDATIONS.password }
    );
  2. 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);
  3. Actualización de contraseña:

    await updateVerticalPassword(email, vertical, password);
  4. Limpieza de tokens de recuperación:

    await updateDocument(USER, strapiUser.documentId, {
    resetPasswordToken: null,
    resetPasswordTokenExpiration: null,
    });
  5. 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 requestPasswordReset responde 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.