feat: implement user authentication and login modal, refactor backend
This commit is contained in:
65
web/backend/middlewares/auth.js
Normal file
65
web/backend/middlewares/auth.js
Normal file
@@ -0,0 +1,65 @@
|
||||
import bcrypt from 'bcrypt';
|
||||
import { getRedisClient } from '../services/redis.js';
|
||||
|
||||
// Autenticación básica Middleware
|
||||
export async function basicAuthMiddleware(req, res, next) {
|
||||
const redisClient = getRedisClient();
|
||||
|
||||
if (!redisClient) {
|
||||
return res.status(500).json({ error: 'Redis no está disponible. La autenticación requiere Redis.' });
|
||||
}
|
||||
|
||||
const authHeader = req.headers.authorization;
|
||||
|
||||
if (!authHeader) {
|
||||
// NO enviar WWW-Authenticate para evitar el diálogo nativo del navegador
|
||||
// En su lugar, devolveremos un 401 y el frontend manejará el modal personalizado
|
||||
return res.status(401).json({ error: 'Authentication required', message: 'Se requiere autenticación para esta operación' });
|
||||
}
|
||||
|
||||
const [scheme, encoded] = authHeader.split(' ');
|
||||
|
||||
if (scheme !== 'Basic') {
|
||||
return res.status(400).json({ error: 'Bad request', message: 'Solo se admite autenticación Basic' });
|
||||
}
|
||||
|
||||
try {
|
||||
const buffer = Buffer.from(encoded, 'base64');
|
||||
const [username, password] = buffer.toString().split(':');
|
||||
|
||||
if (!username || !password) {
|
||||
return res.status(401).json({ error: 'Invalid credentials', message: 'Usuario o contraseña no proporcionados' });
|
||||
}
|
||||
|
||||
// Buscar usuario en Redis
|
||||
const userKey = `user:${username}`;
|
||||
const userExists = await redisClient.exists(userKey);
|
||||
|
||||
if (!userExists) {
|
||||
return res.status(401).json({ error: 'Invalid credentials', message: 'Usuario o contraseña incorrectos' });
|
||||
}
|
||||
|
||||
// Obtener hash de la contraseña
|
||||
const userData = await redisClient.hGetAll(userKey);
|
||||
const passwordHash = userData.passwordHash;
|
||||
|
||||
if (!passwordHash) {
|
||||
return res.status(401).json({ error: 'Invalid credentials', message: 'Usuario o contraseña incorrectos' });
|
||||
}
|
||||
|
||||
// Verificar contraseña
|
||||
const match = await bcrypt.compare(password, passwordHash);
|
||||
|
||||
if (!match) {
|
||||
return res.status(401).json({ error: 'Invalid credentials', message: 'Usuario o contraseña incorrectos' });
|
||||
}
|
||||
|
||||
// Autenticación exitosa
|
||||
req.user = { username };
|
||||
next();
|
||||
} catch (error) {
|
||||
console.error('Error en autenticación:', error);
|
||||
res.status(500).json({ error: 'Internal server error', message: 'Error procesando autenticación' });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user