# RF-MGN-001-001: Autenticación de Usuarios **Módulo:** MGN-001 - Fundamentos **Prioridad:** P0 (MVP) **Story Points:** 8 **Estado:** Definido **Fecha:** 2025-11-23 ## Descripción El sistema debe permitir a los usuarios autenticarse de forma segura utilizando email y contraseña, con soporte para multi-tenancy (cada tenant tiene sus propios usuarios aislados). ## Actores - **Actor Principal:** Usuario (cualquier rol) - **Actores Secundarios:** Sistema de auditoría ## Precondiciones 1. El usuario debe tener una cuenta activa en el tenant 2. El tenant debe estar activo (status='active') 3. La base de datos debe estar disponible ## Flujo Principal 1. Usuario ingresa email y contraseña en formulario de login 2. Sistema valida formato de email 3. Sistema busca usuario por email dentro del tenant actual (subdomain) 4. Sistema verifica contraseña usando bcrypt 5. Sistema valida que usuario tenga status='active' 6. Sistema genera JWT token con claims: user_id, tenant_id, roles, permissions 7. Sistema registra evento de login en auth.login_history 8. Sistema retorna JWT token + refresh token 9. Usuario es redirigido a dashboard principal ## Flujos Alternativos ### FA-1: Credenciales Inválidas 1. Si email no existe o contraseña incorrecta 2. Sistema incrementa failed_login_attempts en auth.users 3. Sistema retorna error 401: "Credenciales inválidas" 4. Sistema registra intento fallido en auth.login_history 5. Si failed_attempts >= 5, sistema bloquea cuenta por 30 minutos ### FA-2: Usuario Inactivo 1. Si user.status != 'active' 2. Sistema retorna error 403: "Cuenta inactiva. Contacte al administrador" ### FA-3: Tenant Inactivo 1. Si tenant.status != 'active' 2. Sistema retorna error 403: "Tenant suspendido" ### FA-4: Cuenta Bloqueada Temporalmente 1. Si failed_login_attempts >= 5 y último intento < 30 minutos 2. Sistema retorna error 429: "Cuenta bloqueada temporalmente. Intente en X minutos" ## Reglas de Negocio - **RN-1:** Email debe ser único por tenant (no globalmente) - **RN-2:** Contraseña debe tener mínimo 8 caracteres, 1 mayúscula, 1 número, 1 símbolo - **RN-3:** JWT expira en 8 horas, refresh token en 30 días - **RN-4:** Máximo 5 intentos fallidos antes de bloqueo temporal de 30 minutos - **RN-5:** Contraseña debe hashearse con bcrypt (cost factor 12) - **RN-6:** Después de login exitoso, failed_login_attempts se resetea a 0 ## Criterios de Aceptación - [ ] Usuario con credenciales válidas puede autenticarse exitosamente - [ ] JWT token contiene user_id, tenant_id, roles, permissions - [ ] Sistema bloquea cuenta después de 5 intentos fallidos por 30 minutos - [ ] Usuarios de diferentes tenants están completamente aislados - [ ] Contraseñas se almacenan hasheadas (nunca plaintext) - [ ] Login queda registrado en auth.login_history con IP y user agent - [ ] Refresh token permite renovar JWT sin re-autenticación - [ ] Usuario inactivo no puede autenticarse - [ ] Tenant inactivo no permite login de usuarios ## Entidades Involucradas - **Principales:** - auth.users (email, password_hash, status, failed_login_attempts) - auth.tenants (subdomain, status) - **Relacionadas:** - auth.login_history (registro de auditoría) - auth.sessions (tokens activos) ## Referencias - [ALCANCE-POR-MODULO.md - MGN-001](../../01-definicion-modulos/ALCANCE-POR-MODULO.md#mgn-001-fundamentos) - [Auth Domain Model](../domain-models/auth-domain.md) - [Auth Schema DDL](../database-design/schemas/auth-schema-ddl.sql) - [Gap Analysis MGN-001](../../01-definicion-modulos/gaps/GAP-ANALYSIS-MGN-001.md) ## Notas Técnicas - **Patrón Odoo:** Similar a res.users authentication en odoo/base - **Patrón Gamilit:** JWT + refresh tokens, multi-tenancy con RLS - **Seguridad:** Implementar rate limiting (max 10 requests/min por IP) - **Backend:** NestJS AuthModule + PassportJS + JWT strategy - **Frontend:** React context + axios interceptors para auto-refresh ## Dependencias - **RF Dependientes:** Ninguno (es el RF base del sistema) - **Bloqueante para:** Todos los demás RF (autenticación es prerequisito)