Buscar en la documentación

Ingreso con verificación en dos pasos

Desde que la persona escribe su correo hasta que entra, con el límite de intentos, el bloqueo progresivo, la contraseña y el código de la aplicación autenticadora.

Módulo auth2 min de lecturaVer en GitHub

El ingreso tiene dos pasos. Primero el correo y la contraseña. Si la cuenta tiene la verificación en dos pasos (MFA) activa, la API entrega un token a medias que solo sirve para enviar el código de la aplicación. Si no la tiene, el ingreso sigue en Configurar el MFA, porque todos los roles la exigen tras un ingreso de gracia.

Diagrama5 carriles · 17 pasos · 6 salidas de error
SíNoSíNoSíNoSíNoSíNoSíNoSíNoEscribe correo ycontraseña1Envía POST/auth/login2¿Menos de 5intentos en elminuto?3Responde 429¿Correo enpausa?4Responde 423Compara lacontraseña conArgon2id5¿Coincide y lacuenta estáactiva?6Suma un fallo.¿Llegó a 5,10, 15 o 20+?7Pausa y responde423Responde 401Pone en cero elcontador de fallos8¿La cuentatiene MFAactivo?9Sigue en Configurarel MFA10Token a medias de 5min, solo para elcódigo11Pide el código en/ingresar/verificar12Escribe el códigode su aplicación13¿Código válidoy sin usar?14¿Quinto códigofallido eneste ingreso?15Cierra el ingresoy responde 401Responde 422 conlo que quedaRevoca el token amedias y crea lasesión16Entra a la páginade origen o alinicio17
Los números coinciden con el paso a paso. En pantallas pequeñas el diagrama se desliza de lado.

Paso a paso

  1. PersonaEscribe correo y contraseña

    En /ingresar. Si llegó desde una página interna, la dirección queda en ?volver= para regresar a ella al final (solo rutas internas, safeRedirect).

  2. NavegadorEnvía POST /auth/login

    El navegador solo revisa que los campos no estén vacíos y que el correo tenga forma de correo; las reglas de verdad están en la API.

  3. API¿Menos de 5 intentos en el minuto?

    Límite login, 5 por minuto por correo + IP. Si se pasa, responde 429 con Retry-After.

  4. Redis¿Correo en pausa?

    Los fallos se cuentan por la huella SHA-256 del correo normalizado, exista o no la cuenta, para no revelar qué correos están registrados.

  5. Base de datosCompara la contraseña con Argon2id

    Si el correo no existe, compara contra un hash de relleno para que la respuesta tarde lo mismo y no delate nada.

  6. API¿Coincide y la cuenta está activa?
  7. RedisSuma un fallo. ¿Llegó a 5, 10, 15 o 20+?

    Al llegar a 5, 10, 15 y 20 fallos seguidos, el correo queda en pausa 1 min, 5 min, 15 min y 1 h; desde ahí, cada fallo vuelve a pausar 1 h. El contador se borra con un ingreso correcto o 24 h después del primer fallo. Solo las pausas quedan en el registro y en los eventos del sistema (LoginLocked); un fallo aislado no.

  8. RedisPone en cero el contador de fallos
  9. API¿La cuenta tiene MFA activo?

    MfaGate decide el siguiente paso: con MFA, verificar el código; sin MFA, configurarlo (sugerido mientras quede el ingreso de gracia, obligatorio después).

  10. NavegadorSigue en Configurar el MFA

    Respuesta setup_suggested (sesión completa y se sugiere configurarlo) o mfa_setup (token a medias; debe configurarlo para entrar).

  11. Base de datosToken a medias de 5 min, solo para el código

    Token de Sanctum con la habilidad mfa. Fuera de las rutas del segundo paso y del cierre de sesión, la API lo rechaza.

  12. NavegadorPide el código en /ingresar/verificar

    El token a medias vive solo en memoria, nunca en sessionStorage. Si se recarga la página, hay que volver a ingresar.

  13. PersonaEscribe el código de su aplicación

    También puede usar uno de sus 8 códigos de recuperación; usarlo le envía un aviso por correo.

  14. API¿Código válido y sin usar?

    Límite mfa: 5 por minuto por persona. Acepta el código de la ventana actual y de las vecinas (±30 s) y no acepta uno ya usado: guarda el último paso de tiempo usado con una actualización condicional.

  15. API¿Quinto código fallido en este ingreso?

    Los fallos se cuentan por ingreso (por token a medias). Al quinto, revoca el token y registra el evento MfaAttemptsExceeded.

  16. Base de datosRevoca el token a medias y crea la sesión

    Token de sesión con prefijo trazo_: dura como máximo 8 h y se cierra tras 1 h sin uso o si desactivan la cuenta. Guarda last_login_at.

  17. NavegadorEntra a la página de origen o al inicio

    Vuelve a ?volver= si era una ruta interna; si no, al inicio.

Qué ve la persona en cada error

CódigoHTTPCuándoMensaje en pantalla
TOO_MANY_REQUESTS429Más de 5 intentos en un minuto con el mismo correo e IPHiciste demasiados intentos seguidos. Espera {wait} y vuelve a intentarlo.
ACCOUNT_LOCKED423El correo está en pausa, o este fallo llegó a un escalón (5, 10, 15 o 20+)Por seguridad, pausamos el ingreso con este correo después de varios intentos fallidos. Vuelve a intentarlo en {wait}.
INVALID_CREDENTIALS401El correo no existe, la contraseña no coincide o la cuenta está desactivada (no dice cuál)El correo o la contraseña no son correctos. Revísalos e inténtalo de nuevo.
MFA_CODE_INVALID422El código no corresponde; trae attempts_leftEl código no es correcto. Escribe el que muestra ahora tu aplicación de autenticación. Te quedan N intentos.
MFA_CODE_ALREADY_USED422El código ya se usó en esa ventana de 30 sEse código ya se usó. Espera a que tu aplicación muestre uno nuevo (cambia cada 30 segundos) y escríbelo.
MFA_RECOVERY_CODE_INVALID422El código de recuperación no existe o ya se usóEse código de recuperación no es válido o ya se usó. Revisa que lo hayas escrito completo, con sus 10 caracteres.
MFA_TOO_MANY_ATTEMPTS401Quinto código fallido en el mismo ingresoPor seguridad cerramos este ingreso después de varios códigos incorrectos. Vuelve a ingresar con tu correo y contraseña.
MFA_CHALLENGE_EXPIRED401Pasaron más de 5 minutos desde la contraseña (la API responde UNAUTHENTICATED)Pasó demasiado tiempo desde que escribiste tu contraseña. Vuelve a ingresar para continuar.

El mensaje de datos incorrectos es el mismo para un correo que no existe y para una contraseña equivocada: es una excepción aprobada a la regla de errores específicos, para no revelar qué correos están registrados.

Dónde está en el código