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.
Paso a paso
- 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). - 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.
- API¿Menos de 5 intentos en el minuto?
Límite
login, 5 por minuto por correo + IP. Si se pasa, responde 429 conRetry-After. - 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.
- 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.
- API¿Coincide y la cuenta está activa?
- 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. - RedisPone en cero el contador de fallos
- API¿La cuenta tiene MFA activo?
MfaGatedecide el siguiente paso: con MFA, verificar el código; sin MFA, configurarlo (sugerido mientras quede el ingreso de gracia, obligatorio después). - NavegadorSigue en Configurar el MFA
Respuesta
setup_suggested(sesión completa y se sugiere configurarlo) omfa_setup(token a medias; debe configurarlo para entrar). - 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. - 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. - 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.
- 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. - 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. - 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. Guardalast_login_at. - 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ódigo | HTTP | Cuándo | Mensaje en pantalla |
|---|---|---|---|
TOO_MANY_REQUESTS | 429 | Más de 5 intentos en un minuto con el mismo correo e IP | Hiciste demasiados intentos seguidos. Espera {wait} y vuelve a intentarlo. |
ACCOUNT_LOCKED | 423 | El 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_CREDENTIALS | 401 | El 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_INVALID | 422 | El código no corresponde; trae attempts_left | El código no es correcto. Escribe el que muestra ahora tu aplicación de autenticación. Te quedan N intentos. |
MFA_CODE_ALREADY_USED | 422 | El código ya se usó en esa ventana de 30 s | Ese código ya se usó. Espera a que tu aplicación muestre uno nuevo (cambia cada 30 segundos) y escríbelo. |
MFA_RECOVERY_CODE_INVALID | 422 | El 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_ATTEMPTS | 401 | Quinto código fallido en el mismo ingreso | Por seguridad cerramos este ingreso después de varios códigos incorrectos. Vuelve a ingresar con tu correo y contraseña. |
MFA_CHALLENGE_EXPIRED | 401 | Pasaron 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
LoginUser: límite de fallos, contraseña y paso siguiente.LockoutPolicyy los escalones enconfig/trazo.php.MfaGateyLoginStep: qué sigue después de la contraseña.VerifyMfayTotpCheck: segundo paso y protección contra repetición.AuthServiceProvider: límitesloginymfa, y la regla del token a medias.useSessionStore,LoginPageyMfaVerifyPage: pantallas y token a medias en memoria.- Mensajes:
errors.ts. - Explicación del módulo: Módulo Auth.