germansango01
Add logout flow in backend
4ec305b
Raw
History Blame Contribute Delete
2.09 kB
/**
* Helpers para firmar y verificar tokens JWT.
*
* Responsabilidades:
* - signToken(payload) β†’ firma un token HS256 con expiracion configurable.
* Incluye claim `jti` (UUID v4) para poder invalidarlo.
* - verifyToken(token) β†’ verifica firma, expiracion y algoritmo (solo HS256).
* - addToDenylist(jti, exp) β†’ anota el jti como invalidado hasta su expiracion.
* - isBlocked(jti) β†’ true si el jti esta en la denylist.
* - pruneExpiredDenylist() β†’ elimina entradas ya expiradas (llamado en cada logout).
*
* Denylist:
* - En memoria (Map<jti, expEpochMs>). Sin persistencia entre reinicios.
* - Aceptable porque el TTL del token es 1h; al reiniciar el servidor
* cualquier token antiguo expirara por si solo antes de que importe.
*
* Consumido por:
* - auth.service.js β†’ signToken al hacer login; addToDenylist al hacer logout.
* - requireAuth.js β†’ verifyToken + isBlocked en cada peticion protegida.
*
* Configuracion:
* - JWT_SECRET : minimo 32 chars (validado en config.js).
* - JWT_EXPIRES_IN: default '1h'.
*/
import { randomUUID } from 'node:crypto';
import jwt from 'jsonwebtoken';
import { config } from '../config.js';
/** @type {Map<string, number>} jti β†’ expiry timestamp (ms) */
const denylist = new Map();
export const signToken = (payload) =>
jwt.sign({ ...payload, jti: randomUUID() }, config.JWT_SECRET, {
algorithm: 'HS256',
expiresIn: config.JWT_EXPIRES_IN,
});
export const verifyToken = (token) =>
jwt.verify(token, config.JWT_SECRET, { algorithms: ['HS256'] });
export const addToDenylist = (jti, exp) => {
pruneExpiredDenylist();
denylist.set(jti, exp * 1000);
};
export const isBlocked = (jti) => {
const exp = denylist.get(jti);
if (exp === undefined) return false;
if (Date.now() > exp) { denylist.delete(jti); return false; }
return true;
};
export const pruneExpiredDenylist = () => {
const now = Date.now();
for (const [jti, exp] of denylist) {
if (now > exp) denylist.delete(jti);
}
};