79 lines
3.4 KiB
JavaScript
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 };
|