34 lines
1.0 KiB
TypeScript
34 lines
1.0 KiB
TypeScript
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
|
|
function getSecret(): string {
|
|
return useRuntimeConfig().adminPassword || "changeme";
|
|
}
|
|
|
|
export function signToken(payload: string): string {
|
|
return createHmac("sha256", getSecret()).update(payload).digest("hex");
|
|
}
|
|
|
|
export function verifyToken(payload: string, signature: string): boolean {
|
|
const expected = signToken(payload);
|
|
try {
|
|
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
|
|
} catch {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
export default defineEventHandler((event) => {
|
|
const path = getRequestURL(event).pathname;
|
|
if (!path.startsWith("/api/admin/") || path === "/api/admin/login") return;
|
|
|
|
const cookie = getCookie(event, "admin-session");
|
|
if (!cookie) {
|
|
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
}
|
|
|
|
const [payload, signature] = cookie.split(".");
|
|
if (!payload || !signature || !verifyToken(payload, signature)) {
|
|
throw createError({ statusCode: 401, statusMessage: "Unauthorized" });
|
|
}
|
|
});
|