← back to Designer Portfolio Pages

src/auth.ts

34 lines

import crypto from "node:crypto";
import bcrypt from "bcryptjs";

export async function hashPasswordIfProvided(password?: string): Promise<string | null> {
  const trimmed = (password ?? "").trim();
  if (!trimmed) return null;
  const saltRounds = 12;
  return bcrypt.hash(trimmed, saltRounds);
}

export async function verifyPassword(password: string, hash: string): Promise<boolean> {
  return bcrypt.compare(password, hash);
}

function hmac(secret: string, value: string): string {
  return crypto.createHmac("sha256", secret).update(value).digest("base64url");
}

export function makePortfolioAuthCookieValue(cookieSecret: string, slug: string): string {
  return `${slug}.${hmac(cookieSecret, slug)}`;
}

export function isValidPortfolioAuthCookieValue(cookieSecret: string, slug: string, cookieValue?: string): boolean {
  if (!cookieValue) return false;
  const [cookieSlug, sig] = cookieValue.split(".");
  if (!cookieSlug || !sig) return false;
  if (cookieSlug !== slug) return false;
  return sig === hmac(cookieSecret, slug);
}

export function createSlug(bytes: number = 9): string {
  return crypto.randomBytes(bytes).toString("base64url");
}