const crypto = require("node:crypto"); function toBase64Url(value) { const source = typeof value === "string" ? value : JSON.stringify(value); return Buffer.from(source).toString("base64url"); } function fromBase64Url(value) { return Buffer.from(value, "base64url").toString("utf8"); } function signPayload(payload, secret) { const body = toBase64Url(payload); const signature = crypto.createHmac("sha256", secret).update(body).digest("base64url"); return `${body}.${signature}`; } function verifyToken(token, secret) { if (typeof token !== "string") { return { ok: false, reason: "invalid_format" }; } const segments = token.split("."); if (segments.length !== 2) { return { ok: false, reason: "invalid_format" }; } const [body, signature] = segments; const expected = crypto.createHmac("sha256", secret).update(body).digest("base64url"); if (signature !== expected) { return { ok: false, reason: "invalid_signature" }; } try { const payload = JSON.parse(fromBase64Url(body)); return { ok: true, payload }; } catch { return { ok: false, reason: "invalid_payload" }; } } module.exports = { signPayload, verifyToken, };