refactor: implement centralized auth middleware and standardize cross-subdomain session management

This commit is contained in:
Giuseppe Raffa
2026-04-21 22:17:48 +02:00
parent 69012029ad
commit 924c2b5367
22 changed files with 670 additions and 530 deletions

View File

@@ -1,69 +1,52 @@
const jwt = require('jsonwebtoken');
const secret = process.env.JWT_SECRET;
const expires_in = process.env.JWT_EXPIRES_IN;
const SECRET = process.env.JWT_SECRET;
const EXPIRES_IN = process.env.JWT_EXPIRES_IN || '7d';
/**
* Genera un JWT Token a partire dall'utente e crea una nuova sessione
*
* Uso dell'algoritmo HS256 per firmare il token con JWT_SECRET
*
* @param {Object} user - Utente
* @param {string} sessionID - ID della sessione
* @returns {string} - JWT Token
* Firma un JWT per l'utente e la sessione.
* Payload: { sub: userId, username, session_id }
*/
function generateToken(user, sessionID) {
const payload = {
sub: user.id,
username: user.username,
session_id: sessionID,
iat: Math.floor(Date.now() / 1000)
};
return jwt.sign(payload, secret, { expiresIn: expires_in, algorithm: 'HS256' });
function sign(user, sessionId) {
return jwt.sign(
{ sub: user.id, username: user.username, session_id: sessionId },
SECRET,
{ algorithm: 'HS256', expiresIn: EXPIRES_IN }
);
}
/**
* Verifica e decodifica il token
* @param {string} token - JWT Token
* @returns {{valid: boolean, payload?: Object, error?: string, reason?: string}} - Il risultato della verifica. Se fallisce restituisce errore e motivo, altrimenti restituisce una conferma e il payload completo
* Verifica e decodifica un token.
* @returns {{ valid: boolean, payload?: Object, reason?: string }}
*/
function verifyToken(token) {
function verify(token) {
try {
const payload = jwt.verify(token, secret, {
algorithms: ['HS256']
});
const p = jwt.verify(token, SECRET, { algorithms: ['HS256'] });
return {
valid: true,
payload: {
user_id: payload.sub,
username: payload.username,
session_id: payload.session_id,
iat: payload.iat,
exp: payload.exp
user_id: p.sub,
username: p.username,
session_id: p.session_id,
iat: p.iat,
exp: p.exp
}
};
} catch (err) {
const reason = err.name === 'TokenExpiredError' ? 'expired' : 'invalid';
return {
valid: false,
error: err.message,
reason: `token ${reason}`
reason: err.name === 'TokenExpiredError' ? 'expired' : 'invalid'
};
}
}
function getToken(header) {
if (!header) return null;
const parts = header.split(' ');
if (parts.length === 2 && parts[0].toLowerCase() === 'bearer') {
return parts[1];
}
return null;
/**
* Estrae il token da un header Authorization: Bearer <token>.
*/
function bearer(header) {
if (!header || typeof header !== 'string') return null;
const [scheme, token] = header.split(' ');
return scheme && scheme.toLowerCase() === 'bearer' && token ? token : null;
}
module.exports = { generateToken, verifyToken, getToken };
module.exports = { sign, verify, bearer };