105 lines
3.3 KiB
JavaScript
105 lines
3.3 KiB
JavaScript
import crypto from 'crypto';
|
|
import { getDB, getSession, deleteSession as deleteSessionFromDB, deleteUserSessions as deleteUserSessionsFromDB, getUser } from '../services/mongodb.js';
|
|
|
|
// Duración de la sesión en milisegundos (24 horas)
|
|
const SESSION_DURATION = 24 * 60 * 60 * 1000;
|
|
|
|
// Generar token seguro
|
|
function generateToken() {
|
|
return crypto.randomBytes(32).toString('hex');
|
|
}
|
|
|
|
// Autenticación por token Middleware
|
|
export async function authMiddleware(req, res, next) {
|
|
const db = getDB();
|
|
|
|
if (!db) {
|
|
return res.status(500).json({ error: 'MongoDB no está disponible. La autenticación requiere MongoDB.' });
|
|
}
|
|
|
|
const authHeader = req.headers.authorization;
|
|
|
|
if (!authHeader) {
|
|
return res.status(401).json({ error: 'Authentication required', message: 'Se requiere autenticación para esta operación' });
|
|
}
|
|
|
|
const [scheme, token] = authHeader.split(' ');
|
|
|
|
if (scheme !== 'Bearer' || !token) {
|
|
return res.status(400).json({ error: 'Bad request', message: 'Se requiere un token Bearer' });
|
|
}
|
|
|
|
try {
|
|
// Verificar token en MongoDB
|
|
const session = await getSession(token);
|
|
|
|
if (!session) {
|
|
return res.status(401).json({ error: 'Invalid token', message: 'Token inválido o sesión expirada' });
|
|
}
|
|
|
|
// Verificar que la sesión no haya expirado
|
|
if (session.expiresAt && new Date(session.expiresAt) < new Date()) {
|
|
await deleteSessionFromDB(token);
|
|
return res.status(401).json({ error: 'Invalid token', message: 'Sesión expirada' });
|
|
}
|
|
|
|
// Verificar que el usuario aún existe
|
|
const user = await getUser(session.username);
|
|
|
|
if (!user) {
|
|
// Eliminar sesión si el usuario ya no existe
|
|
await deleteSessionFromDB(token);
|
|
return res.status(401).json({ error: 'Invalid token', message: 'Usuario no encontrado' });
|
|
}
|
|
|
|
// Actualizar expiración de la sesión (refresh)
|
|
const sessionsCollection = db.collection('sessions');
|
|
const newExpiresAt = new Date(Date.now() + SESSION_DURATION);
|
|
await sessionsCollection.updateOne(
|
|
{ token },
|
|
{ $set: { expiresAt: newExpiresAt } }
|
|
);
|
|
|
|
// Autenticación exitosa - incluir rol en req.user
|
|
req.user = {
|
|
username: session.username,
|
|
role: user.role || 'user' // Por defecto 'user' si no tiene rol
|
|
};
|
|
req.token = token;
|
|
next();
|
|
} catch (error) {
|
|
console.error('Error en autenticación:', error);
|
|
res.status(500).json({ error: 'Internal server error', message: 'Error procesando autenticación' });
|
|
}
|
|
}
|
|
|
|
// Alias para mantener compatibilidad
|
|
export const basicAuthMiddleware = authMiddleware;
|
|
|
|
// Función para crear sesión
|
|
export async function createSession(username) {
|
|
const { createSession: createSessionInDB } = await import('../services/mongodb.js');
|
|
return await createSessionInDB(username);
|
|
}
|
|
|
|
// Función para invalidar sesión
|
|
export async function invalidateSession(token) {
|
|
try {
|
|
return await deleteSessionFromDB(token);
|
|
} catch (error) {
|
|
console.error('Error invalidando sesión:', error);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
// Función para invalidar todas las sesiones de un usuario
|
|
export async function invalidateUserSessions(username) {
|
|
try {
|
|
return await deleteUserSessionsFromDB(username);
|
|
} catch (error) {
|
|
console.error('Error invalidando sesiones del usuario:', error);
|
|
return 0;
|
|
}
|
|
}
|
|
|