Files

79 lines
3.4 KiB
JavaScript

'use strict'
const jwt = require('jsonwebtoken');
const JWT_SECRET = process.env.JWT_SECRET
const USER_SECRET = process.env.USER_SECRET
if (!JWT_SECRET || !USER_SECRET) throw new Error('JWT_SECRET e USER_SECRET devem estar definidos no .env')
function verifyToken(req, res, next) {
const token = req.cookies.cloud_token || req.headers['authorization']?.replace('Bearer ', '');
if (!token) {
if (DEBUG_AUTH) console.log('[auth] cloud_token ausente — cookies recebidos:', Object.keys(req.cookies), 'url:', req.url)
if (req.headers['accept']?.includes('application/json')) return res.status(401).json({ error: 'Não autorizado' });
return res.redirect('/admin');
}
try {
req.admin = jwt.verify(token, JWT_SECRET);
next();
} catch (err) {
if (DEBUG_AUTH) console.log('[auth] cloud_token inválido:', err.message, 'url:', req.url)
res.clearCookie('cloud_token');
if (req.headers['accept']?.includes('application/json')) return res.status(401).json({ error: 'Token inválido' });
return res.redirect('/admin');
}
}
const DEBUG_AUTH = process.env.DEBUG_AUTH === 'true'
function verifyUserToken(req, res, next) {
const token = req.cookies.user_token || req.headers['authorization']?.replace('Bearer ', '');
if (!token) {
if (DEBUG_AUTH) console.log('[auth] user_token ausente — cookies recebidos:', Object.keys(req.cookies))
if (req.headers['accept']?.includes('application/json')) return res.status(401).json({ error: 'Usuário não autenticado' });
return res.redirect('/login');
}
try {
const payload = jwt.verify(token, USER_SECRET);
// Valida que o token pertence ao tenant da request (compara como número)
const tokenTenant = Number(payload.tenant_id)
const requestTenant = Number(req.tenant?.id)
if (req.tenant?.id && payload.tenant_id && tokenTenant !== requestTenant) {
if (DEBUG_AUTH) console.log('[auth] tenant mismatch — token:', tokenTenant, 'request:', requestTenant)
return res.status(401).json({ error: 'Token inválido para este tenant' });
}
req.user = payload;
next();
} catch (err) {
if (DEBUG_AUTH) console.log('[auth] jwt.verify falhou:', err.message)
res.clearCookie('user_token');
res.clearCookie('_usr'); // limpa hint cookie — frontend parará de chamar /me
if (req.headers['accept']?.includes('application/json')) return res.status(401).json({ error: 'Sessão expirada' });
return res.redirect('/login');
}
}
// Gera token de usuário incluindo tenant_id
function signUserToken(user, tenantId) {
return jwt.sign(
{ id: user.id, nome: user.nome, cpf: user.cpf, email: user.email, tenant_id: tenantId },
USER_SECRET,
{ expiresIn: '1d' }
);
}
/**
* Middleware: verifica o header X-Portal-Key enviado pelo sistema-local (captive portal).
* Protege endpoints que só devem ser acessíveis pelo gateway, não por usuários comuns.
*/
function verifyPortalKey(req, res, next) {
const key = req.headers['x-portal-key'];
if (!key || key !== process.env.PORTAL_API_KEY) {
console.warn(`[auth] X-Portal-Key inválida — IP: ${req.ip}, URL: ${req.url}`);
return res.status(401).json({ error: 'Não autorizado' });
}
next();
}
module.exports = { verifyToken, verifyUserToken, signUserToken, verifyPortalKey, JWT_SECRET, USER_SECRET };