Saltar al contenido principal

RF02: Usuario inicia sesión con correo y contraseña

Descripción

Como usuario registrado, quiero iniciar sesión con mi correo y contraseña para acceder a mis datos financieros de forma segura.

El login verifica las credenciales contra el hash Argon2id almacenado y, si son válidas, crea una nueva sesión ligada al dispositivo emitiendo el par access token (JWT 15 min) + refresh token (opaco 30 días), conforme al Control de Sesiones.

CampoValor
MóduloAuth Module
ActorUsuario registrado
EndpointPOST /auth/login
PrecondicionesExiste una cuenta con credenciales de correo/contraseña
PrioridadAlta (MVP)
EtapaMVP
Requisitos relacionadosRF01, RF03, RF04, RF11

Reglas de negocio

  • RN-02.1 — La verificación usa argon2.verify(hash, password); nunca se compara la contraseña en claro.
  • RN-02.2 — Un login exitoso crea una sesión nueva. Si se supera el límite del plan (2 gratuito / 5 premium), se revoca automáticamente la sesión más antigua por last_used_at (ver Control de Sesiones §4.2).
  • RN-02.3 — Las cuentas creadas solo con login social (sin password_hash) no pueden usar este flujo; deben usar su proveedor.
  • RN-02.4 — Login desde un dispositivo nuevo dispara notificación de seguridad (push + email).
  • RN-02.5 — Mensaje de error genérico ante credenciales inválidas para no revelar si el correo existe.

Validaciones de entrada

CampoReglasMensaje de error
emailObligatorio. Formato válido. Normalizado a minúsculas."Ingresa un correo electrónico válido."
passwordObligatorio. No vacío."Ingresa tu contraseña."
deviceInfoObligatorio (device_name, device_os, device_id).— (uso interno)

Las consultas son parametrizadas; no se aceptan inyecciones SQL. Se aplica rate limiting por IP y por cuenta (ver Escenario 4).

Criterios de aceptación

Escenario 1: Login exitoso (happy path)

Dado que tengo una cuenta con correo y contraseña válidos, Cuando ingreso credenciales correctas, Entonces el sistema verifica el hash Argon2id, Y crea una sesión asociada a mi dispositivo, Y recibo access_token (15 min) y refresh_token (30 días) con 200 OK.

Escenario 2: Credenciales incorrectas

Dado que ingreso un correo inexistente o una contraseña incorrecta, Cuando intento iniciar sesión, Entonces el sistema responde 401 Unauthorized, Y muestra el mensaje genérico "Correo o contraseña incorrectos", Y no se crea ninguna sesión.

Escenario 3: Cuenta solo-social sin contraseña

Dado que mi cuenta fue creada con Google/Apple y no tiene contraseña, Cuando intento iniciar sesión con correo y contraseña, Entonces el sistema responde 401 con el mensaje "Inicia sesión con el método que usaste para registrarte".

Escenario 4: Bloqueo por intentos fallidos (seguridad)

Dado que se registran 5 intentos fallidos en 10 minutos desde la misma IP o cuenta, Cuando intento nuevamente, Entonces el sistema bloquea temporalmente (15 min) y responde 429 Too Many Requests, Y muestra "Demasiados intentos. Intenta de nuevo en unos minutos".

Escenario 5: Login desde dispositivo nuevo

Dado que inicio sesión correctamente desde un dispositivo nunca antes usado, Cuando se crea la sesión, Entonces el sistema envía una notificación push + email indicando dispositivo, OS, hora e IP aproximada.

Escenario 6: Validación de campos y seguridad

Dado que envío campos vacíos, con formato inválido o intentos de inyección SQL, Cuando el backend procesa la solicitud, Entonces responde 400 Bad Request por validación, Y la inyección no se ejecuta gracias a consultas parametrizadas.

Criterios no funcionales

  • Respuesta < 1.5 s (incluye verificación Argon2id).
  • Comunicación sobre TLS 1.2+.
  • El refresh_token se guarda en SecureStore; el access_token solo en memoria.
  • La contraseña nunca se registra en logs.

Diagrama de secuencia