refactor: implement centralized auth middleware and standardize cross-subdomain session management
This commit is contained in:
70
api/src/middlewares/auth.js
Normal file
70
api/src/middlewares/auth.js
Normal file
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* Middleware di autenticazione per API REST.
|
||||
* Supporta tre modalità:
|
||||
* - x-api-key (service-to-service, INTERNAL_API_KEY)
|
||||
* - cookie auth_token (utenti loggati dal browser, SSO via .mebboat.it)
|
||||
* - Authorization: Bearer <jwt>
|
||||
*
|
||||
* Il JWT viene firmato da auth.mebboat.it con JWT_SECRET e verificato localmente.
|
||||
* Il cookie è condiviso tra i sottodomini grazie a domain=.mebboat.it
|
||||
*/
|
||||
|
||||
const jwt = require('jsonwebtoken');
|
||||
|
||||
const SECRET = process.env.JWT_SECRET;
|
||||
const INTERNAL_KEY = process.env.INTERNAL_API_KEY;
|
||||
|
||||
function extractToken(req) {
|
||||
const header = req.headers.authorization;
|
||||
const bearer = header && header.startsWith('Bearer ') ? header.slice(7) : null;
|
||||
return (req.cookies && req.cookies.auth_token) || bearer || null;
|
||||
}
|
||||
|
||||
function verifyToken(token) {
|
||||
if (!token || typeof token !== 'string' || token.length > 2048) return null;
|
||||
try {
|
||||
const p = jwt.verify(token, SECRET, { algorithms: ['HS256'] });
|
||||
return {
|
||||
user_id: p.sub,
|
||||
username: p.username,
|
||||
session_id: p.session_id,
|
||||
iat: p.iat,
|
||||
exp: p.exp
|
||||
};
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Accetta utente loggato (cookie/bearer) o chiamata interna (x-api-key).
|
||||
* Imposta req.user con i dati dell'utente, oppure req.internal = true.
|
||||
*/
|
||||
function requireAuth(req, res, next) {
|
||||
// 1. Service-to-service
|
||||
const apiKey = req.headers['x-api-key'];
|
||||
if (apiKey && INTERNAL_KEY && apiKey === INTERNAL_KEY) {
|
||||
req.internal = true;
|
||||
return next();
|
||||
}
|
||||
|
||||
// 2. User auth (cookie o Bearer)
|
||||
const user = verifyToken(extractToken(req));
|
||||
if (!user) return res.status(401).json({ error: 'unauthorized' });
|
||||
req.user = user;
|
||||
next();
|
||||
}
|
||||
|
||||
/**
|
||||
* Solo service-to-service (x-api-key).
|
||||
*/
|
||||
function requireInternal(req, res, next) {
|
||||
const apiKey = req.headers['x-api-key'];
|
||||
if (!INTERNAL_KEY || !apiKey || apiKey !== INTERNAL_KEY) {
|
||||
return res.status(403).json({ error: 'forbidden' });
|
||||
}
|
||||
req.internal = true;
|
||||
next();
|
||||
}
|
||||
|
||||
module.exports = { requireAuth, requireInternal, verifyToken, extractToken };
|
||||
Reference in New Issue
Block a user