Skip to content

Plataforma técnica · Seguridad

Autenticación y Autorización

Seguridad

Orchestrator combina JWT firmado con una sesión persistida en auth.user_sessions. El JWT no basta por sí solo: cada solicitud protegida debe validar que el token existe, que la firma es válida, que contiene sessionId y que la sesión sigue vigente en la base central.

  1. Sevastopol envía username, password y opcionalmente rememberMe a POST /api/auth/login.
  2. loginRateLimiter limita intentos fallidos antes de ejecutar la validación de credenciales.
  3. Orchestrator valida el payload con express-validator y busca el usuario en auth.users.
  4. La contraseña se compara con bcryptjs.compare contra password_hash.
  5. Si el usuario tiene TOTP habilitado, la respuesta entrega requires_2fa y temp_token; no se emite sesión todavía.
  6. Si no requiere TOTP, o si POST /api/auth/2fa/verify confirma el desafío, Orchestrator inserta auth.user_sessions, firma el JWT y emite la cookie sid.
sequenceDiagram
  participant User as Usuario
  participant UI as Sevastopol
  participant API as Orchestrator
  participant Auth as auth.users
  participant Sessions as auth.user_sessions
  participant TOTP as TotpService

  User->>UI: Ingresa credenciales
  UI->>API: POST /api/auth/login
  API->>Auth: SELECT user por username
  API->>API: bcryptjs.compare(password, password_hash)

  alt TOTP habilitado
    API->>TOTP: Crear desafío temporal
    API-->>UI: requires_2fa + temp_token
    UI->>API: POST /api/auth/2fa/verify
    API->>TOTP: Verificar código o backup code
  end

  API->>Sessions: INSERT session_id, user_id, ip, user_agent, expires_at
  API-->>UI: Set-Cookie sid=JWT HttpOnly
  UI-->>User: Sesión iniciada

El payload contiene identidad y contexto mínimo de sesión. No debe contener secretos, permisos derivados ni datos personales innecesarios.

JWT payload
{
"userId": "$USER_ID",
"username": "$USERNAME",
"role": "ADMIN",
"sessionId": "$SESSION_ID",
"tenantId": "$TENANT_ID",
"iat": 1780000000,
"exp": 1780086400
}
CampoUso
userIdIdentificador del usuario autenticado
usernameNombre de usuario para contexto y respuesta
roleRol base para RBAC
sessionIdLlave de revocación contra auth.user_sessions
tenantIdTenant asignado al usuario, cuando aplica
iat / expEmisión y expiración del JWT

authenticateToken vive en orchestrator/src/middleware/auth.ts. Extrae el token desde Authorization: Bearer $TOKEN o desde la cookie sid, valida la firma con $JWT_SECRET, consulta auth.user_sessions y carga req.user.

middleware/auth.ts
export const authenticateToken = async (req, res, next) => {
const token = extractTokenFromRequest(req);
if (!token) {
return res.status(401).json({ success: false, error: 'No authorization token' });
}
const session = await validateSessionToken(token);
if (!session) {
clearSessionCookie(res);
return res.status(401).json({
success: false,
error: 'Invalid, expired, or revoked session',
});
}
req.user = session;
next();
};

La autenticación responde quién es el usuario. La autorización responde qué puede hacer. Orchestrator usa dos mecanismos complementarios:

MecanismoUbicaciónUso esperado
authorizeRoutemiddleware/auth.ts con lib/rbac.tsProteger rutas declaradas en el mapa RBAC por rol
requireRolemiddleware/auth.ts y lib/rbac.tsRestringir operaciones específicas a uno o más roles
Reglas de dominioServicios y repositoriosValidar condiciones funcionales que RBAC no puede expresar
RolAlcance documentadoEjemplos de acceso
SUPER_ADMINAdministración global y operaciones multi-tenant explícitasTenants, usuarios, sesiones, monitoreo, administración y reportes
ADMINAdministración del tenant asignadoContabilidad, operaciones, administración de empresa y reportes
USEROperación acotada y lecturaLectura contable, operaciones permitidas y reportes
routes/example.ts
router.post(
'/',
authenticateToken,
requireRole(['ADMIN', 'SUPER_ADMIN']),
async (req, res) => {
// Operación protegida por identidad y rol explícito.
},
);

TOTP se implementa en domain/auth/totp y se integra con routes/command/auth.ts.

EndpointProtecciónPropósito
POST /api/auth/2fa/setupauthenticateTokenIniciar configuración de TOTP para el usuario autenticado
POST /api/auth/2fa/enableauthenticateTokenConfirmar código TOTP y activar segundo factor
POST /api/auth/2fa/disableauthenticateTokenDesactivar TOTP con código actual o backup code
POST /api/auth/2fa/verifyDesafío temporalConvertir temp_token y código válido en sesión real

El flujo de autenticación registra eventos mediante auditLog:

EventoCuándo se emite
LOGINCredenciales válidas y sesión creada
LOGIN_FAILEDUsuario inexistente o contraseña inválida
LOGOUTSesión eliminada durante logout
API_ACCESSMutaciones o errores relevantes en rutas autenticadas

Los eventos incluyen IP, user agent y contexto de usuario cuando está disponible. Los campos sensibles se deben sanitizar antes de persistirse en auditoría.