nova-store/app/lib/auth.js

40 lines
1.5 KiB
JavaScript

import crypto from "node:crypto";
const SECRET = process.env.AUTH_SECRET || "nova-store-dev-secret-change-me";
// --- Contraseñas: scrypt (nativo de Node, sin dependencias) ---
export function hashPassword(password) {
const salt = crypto.randomBytes(16).toString("hex");
const hash = crypto.scryptSync(password, salt, 64).toString("hex");
return `${salt}:${hash}`;
}
export function verifyPassword(password, stored) {
const [salt, hash] = String(stored).split(":");
if (!salt || !hash) return false;
const test = crypto.scryptSync(password, salt, 64).toString("hex");
const a = Buffer.from(hash, "hex");
const b = Buffer.from(test, "hex");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}
// --- Sesión: cookie firmada con HMAC (sin dependencias) ---
export function signSession(userId) {
const value = String(userId);
const sig = crypto.createHmac("sha256", SECRET).update(value).digest("hex");
return `${value}.${sig}`;
}
export function readSession(cookieValue) {
if (!cookieValue) return null;
const i = cookieValue.lastIndexOf(".");
if (i < 0) return null;
const value = cookieValue.slice(0, i);
const sig = cookieValue.slice(i + 1);
const expected = crypto.createHmac("sha256", SECRET).update(value).digest("hex");
const a = Buffer.from(sig);
const b = Buffer.from(expected);
if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) return null;
const id = Number(value);
return Number.isFinite(id) ? id : null;
}