81 lines
2.6 KiB
JavaScript
81 lines
2.6 KiB
JavaScript
'use strict'
|
|
|
|
/**
|
|
* teamAuth.js — Autenticação para contas de equipe (tabela accounts)
|
|
* Separado do auth.js que cuida dos admins (tabela admins)
|
|
*
|
|
* Cookie: team_token (JWT)
|
|
* Payload: { accountId, tenantId, role, name }
|
|
*/
|
|
|
|
const jwt = require('jsonwebtoken')
|
|
|
|
// Secret compartilhado (mesmo process.env.JWT_SECRET) — fallbacks distintos por tipo
|
|
const TEAM_SECRET = process.env.JWT_SECRET || 'alemao-secret-2024'
|
|
// Admin usa o mesmo JWT_SECRET mas com fallback diferente se não configurado — importa de auth.js
|
|
const { JWT_SECRET: ADMIN_SECRET } = require('./auth')
|
|
|
|
/**
|
|
* verifyTeamToken — middleware que exige cookie team_token válido
|
|
* Injeta req.teamAccount = { accountId, tenantId, role, name }
|
|
*/
|
|
function verifyTeamToken(req, res, next) {
|
|
const token = req.cookies?.team_token
|
|
if (!token) return res.status(401).json({ error: 'Não autenticado' })
|
|
try {
|
|
const payload = jwt.verify(token, TEAM_SECRET)
|
|
req.teamAccount = payload
|
|
if (!req.tenantId) req.tenantId = payload.tenantId
|
|
next()
|
|
} catch {
|
|
return res.status(401).json({ error: 'Sessão expirada' })
|
|
}
|
|
}
|
|
|
|
/**
|
|
* verifyAnyToken — aceita admin (cloud_token) OU equipe (team_token)
|
|
* SEGURANÇA:
|
|
* - Admin: verifica com ADMIN_SECRET e popula req.admin
|
|
* - Equipe: verifica com TEAM_SECRET e popula req.teamAccount
|
|
* - Nunca aceita team_token quando cloud_token está presente e válido
|
|
*/
|
|
function verifyAnyToken(req, res, next) {
|
|
const adminToken = req.cookies?.cloud_token
|
|
const teamToken = req.cookies?.team_token
|
|
|
|
// Tenta admin primeiro — usa o secret correto e popula req.admin
|
|
if (adminToken) {
|
|
try {
|
|
const payload = jwt.verify(adminToken, ADMIN_SECRET)
|
|
req.admin = payload
|
|
if (!req.tenantId && payload.tenant_id) req.tenantId = payload.tenant_id
|
|
return next()
|
|
} catch {
|
|
// cloud_token presente mas inválido — rejeita imediatamente (evita escalada de privilégio)
|
|
return res.status(401).json({ error: 'Token inválido ou expirado' })
|
|
}
|
|
}
|
|
|
|
// Tenta equipe apenas se não havia cloud_token
|
|
if (teamToken) {
|
|
try {
|
|
const payload = jwt.verify(teamToken, TEAM_SECRET)
|
|
req.teamAccount = payload
|
|
if (!req.tenantId) req.tenantId = payload.tenantId
|
|
return next()
|
|
} catch {}
|
|
}
|
|
|
|
return res.status(401).json({ error: 'Não autenticado' })
|
|
}
|
|
|
|
function signTeamToken(account) {
|
|
return jwt.sign(
|
|
{ accountId: account.id, tenantId: account.tenant_id, role: account.role, name: account.name },
|
|
TEAM_SECRET,
|
|
{ expiresIn: '7d' }
|
|
)
|
|
}
|
|
|
|
module.exports = { verifyTeamToken, verifyAnyToken, signTeamToken }
|