import { randomBytes, scrypt } from "node:crypto"; import { jwtVerify, SignJWT } from "@panva/jose"; import { type AuthPayload, isAuthPayload } from "../model/interfaces.ts"; const JWT_SECRET = "FIXME-gerbeur-dev-env"; const JWT_KEY = new TextEncoder().encode(JWT_SECRET); export async function createJWT( payload: Omit, ): Promise { return await new SignJWT(payload) .setProtectedHeader({ alg: "HS256" }) .setExpirationTime("24h") .sign(JWT_KEY); } export async function verifyJWT(token: string): Promise { try { const { payload } = await jwtVerify(token, JWT_KEY); if (!isAuthPayload(payload)) { return null; } return payload; } catch (err) { console.error("JWT verification failed:", err); return null; } } export function hashPassword(password: string): Promise { const salt = randomBytes(16).toString("hex"); return new Promise((resolve, reject) => { scrypt(password, salt, 64, (err, derivedKey) => { if (err) reject(err); else resolve(`${derivedKey.toString("hex")}.${salt}`); }); }); } export function verifyPassword( password: string, storedHash: string, ): Promise { const [hash, salt] = storedHash.split("."); return new Promise((resolve, reject) => { scrypt(password, salt, 64, (err, derivedKey) => { if (err) reject(err); else resolve(hash === derivedKey.toString("hex")); }); }); }