Ir al contenido

Seguridad

Ruta: /owner/settings/security Gestiona la seguridad de tu cuenta y revisa accesos.


La pantalla de Seguridad permite configurar opciones de protección de tu cuenta y revisar el historial de accesos.

Secciones principales:

SecciónDescripción
Correo de recuperaciónConfigura un email alternativo para recuperar tu cuenta
Registros de accesoHistorial de inicios y cierres de sesión

Acceso restringido: Solo propietarios del negocio tienen acceso a esta configuración.


FunciónDescripciónDocumentación
Configurar email de recuperaciónAñade un correo alternativo para recuperaciónVer
Recuperar contraseñaRestablece tu contraseña mediante emailVer
Ver registros de accesoConsulta historial de inicios de sesiónVer
Filtrar registrosFiltra accesos por tipo de evento o usuarioVer

Factux implementa múltiples capas de seguridad para proteger tu sesión:

CaracterísticaDescripción
Refresco automáticoLa sesión se refresca cada 30 minutos
Verificación al volverAl regresar a la pestaña se verifica la sesión
Detección de expiraciónRedirige automáticamente al login si expira
Limpieza seguraLos tokens se eliminan de forma segura al cerrar
  • Duración máxima: 1 hora sin actividad
  • Refresco preventivo: Cuando quedan menos de 5 minutos
  • Verificación mínima: No más frecuente que cada 5 segundos
  • Notificación: Toast informativo antes de redirigir

┌────────────────┐
│ Sin protección │ (sin email de recuperación)
└───────┬────────┘
│ Configurar
┌───────▼────────┐
│ Protegido │ (email de recuperación activo)
└───────┬────────┘
│ Necesita recuperación
┌───────▼────────┐
│ Recuperando │ (token enviado, válido 24h)
└───────┬────────┘
│ Cambiar contraseña
┌───────▼────────┐
│ Acceso OK │ (contraseña actualizada)
└────────────────┘

Detalles técnicos
Tablas principales
TablaColumnas principalesFK
profilesuser_id, recovery_emailauth.users
user_access_logsid, user_id, business_id, user_name, user_email, user_type, event_type, login_at, ip_address, user_agent, session_idauth.users, businesses
security_audit_logid, user_id, event_type, event_data, ip_address, user_agent, resource_type, resource_id, severity, timestampauth.users
password_reset_tokensid, user_id, email, token, expires_at, used_atauth.users

Tipos de datos:

interface UserAccessLog {
id: string;
user_id: string;
business_id?: string;
user_name: string;
user_email: string;
user_type: 'owner' | 'manager' | 'employee' | 'advisor' | 'admin' | 'support';
event_type: 'login' | 'logout';
login_at: string; // timestamp
ip_address?: string;
user_agent?: string;
session_id?: string;
}
interface SecurityAuditLog {
id: string;
user_id?: string;
event_type: string; // session_start, unauthorized_access_attempt, etc.
event_data: Record<string, any>;
ip_address?: string;
user_agent?: string;
resource_type?: string;
resource_id?: string;
severity: 'info' | 'warning' | 'critical';
timestamp: string;
}
interface PasswordResetToken {
id: string;
user_id: string;
email: string;
token: string;
expires_at: string;
used_at?: string;
created_at: string;
}
Políticas de seguridad
TablaPolíticaRegla
profilesprofiles_read_ownSolo lectura de perfil propio
profilesprofiles_update_ownSolo actualización de perfil propio
user_access_logsusers_view_own_access_logsSolo logs propios o de negocios asociados
security_audit_logusers_view_own_audit_logsSolo logs propios
Funciones de autenticación
FunciónTriggerDescripción
send-password-reset-emailRecuperación contraseñaEnvía email con token vía SendGrid
update-password-with-tokenCambio contraseñaValida token y actualiza contraseña
track-auth-eventsLogin/logoutRegistra eventos de autenticación

Detalles de send-password-reset-email:

// Parámetros
interface ResetPasswordRequest {
email: string;
sendToRecoveryEmail?: boolean; // enviar a email de recuperación
}
// Proceso
// 1. Busca usuario por email
// 2. Si sendToRecoveryEmail=true, obtiene recovery_email de profiles
// 3. Genera token UUID seguro
// 4. Guarda token en password_reset_tokens (válido 24h)
// 5. Envía email con enlace de reset
// 6. Retorna success con mensaje personalizado
// Template SendGrid: d-b937c4c6573a49c3bd745df56b5cb2e6

Detalles de track-auth-events:

// Parámetros
interface AuthEvent {
event: string; // user.login.failed
email: string;
ip_address?: string;
user_agent?: string;
error_message?: string;
}
// Registra intentos fallidos de login para seguridad
Componentes de seguridad
ComponenteRutaPropósito
RecoveryEmailSettings/src/features/settings/components/RecoveryEmailSettings.tsxGestión de email de recuperación
AccessLogsTable/src/panels/admin/components/AccessLogsTable.tsxTabla de registros de acceso
SessionRecovery/src/components/auth/SessionRecovery.tsxManejo de sesiones expiradas

Schema de validación:

src/features/settings/components/RecoveryEmailSettings.tsx
const recoveryEmailSchema = z.object({
recovery_email: z
.string()
.email("Introduce un correo electrónico válido")
.or(z.literal("")),
});
Hook de sesión

useSessionKeepAlive/src/hooks/useSessionKeepAlive.ts

Mantiene la sesión activa y detecta sesiones expiradas.

Funcionalidades:

  • Refresca la sesión cada 30 minutos
  • Verifica la sesión cuando el usuario regresa a la pestaña
  • Verifica al recuperar conexión a internet
  • Refresca preventivo cuando quedan menos de 5 min de expiración
  • Limita verificaciones a 1 cada 5 segundos mínimo
  • Redirige al login con toast informativo si expira

Triggers de verificación:

  • initial_mount — Al montar el componente
  • periodic_refresh — Cada 30 minutos
  • visibility_change — Al volver a la pestaña
  • window_focus — Al enfocar la ventana
  • online — Al recuperar conexión
Consultas útiles

Accesos recientes de un usuario:

SELECT * FROM user_access_logs
WHERE user_id = '<user_id>'
ORDER BY login_at DESC
LIMIT 50;

Accesos por negocio:

SELECT ual.*, b.name as business_name
FROM user_access_logs ual
LEFT JOIN businesses b ON ual.business_id = b.id
WHERE ual.business_id = '<business_id>'
ORDER BY ual.login_at DESC;

Accesos sospechosos (múltiples IPs):

SELECT user_email, COUNT(DISTINCT ip_address) as different_ips,
COUNT(*) as total_logins
FROM user_access_logs
WHERE login_at >= NOW() - INTERVAL '24 hours'
AND event_type = 'login'
GROUP BY user_email
HAVING COUNT(DISTINCT ip_address) > 3
ORDER BY different_ips DESC;

Eventos de seguridad críticos:

SELECT * FROM security_audit_log
WHERE severity = 'critical'
AND timestamp >= NOW() - INTERVAL '7 days'
ORDER BY timestamp DESC;

Tokens de recuperación activos:

SELECT prt.*, p.first_name, p.last_name
FROM password_reset_tokens prt
JOIN profiles p ON prt.user_id = p.user_id
WHERE prt.expires_at > NOW()
AND prt.used_at IS NULL
ORDER BY prt.created_at DESC;

Email de recuperación configurados:

SELECT user_id, recovery_email, created_at
FROM profiles
WHERE recovery_email IS NOT NULL
ORDER BY created_at DESC;
Funciones de seguridad

log_security_event — Registra eventos de seguridad en audit log

-- Parámetros
p_event_type TEXT, -- Tipo de evento
p_resource_type TEXT, -- Tipo de recurso afectado
p_resource_id TEXT, -- ID del recurso
p_event_data JSONB, -- Datos adicionales
p_severity TEXT DEFAULT 'info', -- info, warning, critical
p_ip_address TEXT, -- IP del evento
p_user_agent TEXT -- User agent
-- Uso
SELECT log_security_event(
'unauthorized_access_attempt',
'invoice',
'invoice-id-123',
'{"attempted_action": "delete"}'::jsonb,
'warning',
'192.168.1.1',
'Mozilla/5.0...'
);

cleanup_expired_password_tokens — Limpia tokens expirados

-- Elimina tokens expirados o usados hace más de 7 días
-- Ejecuta automáticamente vía cron
SELECT cleanup_expired_password_tokens();

get_user_by_email — Busca usuario por email (SECURITY DEFINER)

-- Solo accesible por service_role para password reset
SELECT * FROM get_user_by_email('usuario@ejemplo.com');

  1. Configura un email de recuperación diferente al principal
  2. Revisa periódicamente los registros de acceso
  3. Notifica accesos sospechosos si ves IPs desconocidas
  4. Usa contraseñas robustas con mayúsculas, números y símbolos
  5. Cierra sesión en dispositivos compartidos
  1. Monitorea eventos críticos en security_audit_log
  2. Verifica intentos fallidos repetidos de login
  3. Revisa tokens activos antes de depurar problemas de recuperación
  4. Audita accesos desde múltiples IPs en corto tiempo
  5. Mantén logs de eventos de seguridad para análisis

Factux incluye un tour interactivo que se activa automáticamente la primera vez que visitas la pantalla de Seguridad.

Pasos del tour:

  1. Cabecera — Introducción a la gestión de seguridad
  2. Email de recuperación — Cómo configurar un email alternativo
  3. Registros de acceso — Detectar accesos sospechosos

Archivo de configuración: /src/features/tours/config/settings-security.tour.ts