From ece9c78b16acd683f09b0fcd7c7b515c64da52f9 Mon Sep 17 00:00:00 2001 From: Ahmet Kilinc Date: Wed, 16 Jul 2025 01:05:42 +0100 Subject: [PATCH] coderabbit comments --- apps/web/src/app/api/waitlist/route.ts | 5 +---- apps/web/src/app/api/waitlist/token/route.ts | 13 ++++++------- apps/web/src/components/landing/hero.tsx | 15 +++++++++++++-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/apps/web/src/app/api/waitlist/route.ts b/apps/web/src/app/api/waitlist/route.ts index 031ebd5a..076dd228 100644 --- a/apps/web/src/app/api/waitlist/route.ts +++ b/apps/web/src/app/api/waitlist/route.ts @@ -135,10 +135,7 @@ async function validateCSRFToken(request: NextRequest): Promise { const tokenTime = parseInt(timestamp); if (now - tokenTime > TOKEN_EXPIRY) return false; - const expectedSignature = crypto - .createHmac("sha256", env.BETTER_AUTH_SECRET || "fallback-secret") - .update(`${token}:${timestamp}`) - .digest("hex"); + const expectedSignature = crypto.createHmac("sha256", env.BETTER_AUTH_SECRET).update(`${token}:${timestamp}`).digest("hex"); return signature === expectedSignature; } diff --git a/apps/web/src/app/api/waitlist/token/route.ts b/apps/web/src/app/api/waitlist/token/route.ts index 76622fc5..4c7695fa 100644 --- a/apps/web/src/app/api/waitlist/token/route.ts +++ b/apps/web/src/app/api/waitlist/token/route.ts @@ -5,6 +5,7 @@ import { env } from "@/env"; const CSRF_TOKEN_NAME = "waitlist-csrf"; const TOKEN_EXPIRY = 60 * 60 * 1000; +const allowedHosts = env.NODE_ENV === "development" ? ["localhost:3000", "127.0.0.1:3000"] : ["opencut.app", "www.opencut.app"]; export async function GET(request: NextRequest) { const referer = request.headers.get("referer"); @@ -12,14 +13,11 @@ export async function GET(request: NextRequest) { if (referer) { const refererUrl = new URL(referer); - const allowedHosts = env.NODE_ENV === "development" ? ["localhost:3000", "127.0.0.1:3000"] : ["opencut.app", "www.opencut.app"]; if (!allowedHosts.some((allowed) => refererUrl.host === allowed || refererUrl.host.endsWith(allowed))) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } } else if (host) { - const allowedHosts = env.NODE_ENV === "development" ? ["localhost:3000", "127.0.0.1:3000"] : ["opencut.app", "www.opencut.app"]; - if (!allowedHosts.some((allowed) => host === allowed || host.endsWith(allowed))) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } @@ -27,12 +25,13 @@ export async function GET(request: NextRequest) { return NextResponse.json({ error: "Forbidden" }, { status: 403 }); } + if (!env.BETTER_AUTH_SECRET) { + throw new Error("BETTER_AUTH_SECRET must be configured"); + } + const token = crypto.randomBytes(32).toString("hex"); const timestamp = Date.now(); - const signature = crypto - .createHmac("sha256", env.BETTER_AUTH_SECRET || "fallback-secret") - .update(`${token}:${timestamp}`) - .digest("hex"); + const signature = crypto.createHmac("sha256", env.BETTER_AUTH_SECRET).update(`${token}:${timestamp}`).digest("hex"); const cookieStore = await cookies(); cookieStore.set(CSRF_TOKEN_NAME, `${token}:${timestamp}:${signature}`, { diff --git a/apps/web/src/components/landing/hero.tsx b/apps/web/src/components/landing/hero.tsx index 54aba300..b1910dc5 100644 --- a/apps/web/src/components/landing/hero.tsx +++ b/apps/web/src/components/landing/hero.tsx @@ -16,16 +16,24 @@ export function Hero() { const [csrfToken, setCsrfToken] = useState(null); useEffect(() => { + let isMounted = true; fetch("/api/waitlist/token", { credentials: "include", }) .then((res) => res.json()) .then((data) => { - if (data.token) { + if (isMounted && data.token) { setCsrfToken(data.token); } }) - .catch((err) => console.error("Failed to fetch CSRF token:", err)); + .catch((err) => { + console.error("Failed to fetch CSRF token:", err); + if (isMounted) { + toast.error("Security initialization failed", { + description: "Please refresh the page to continue.", + }); + } + }); }, []); const handleSubmit = async (e: React.FormEvent) => { @@ -70,6 +78,9 @@ export function Hero() { .then((res) => res.json()) .then((data) => { if (data.token) setCsrfToken(data.token); + }) + .catch((err) => { + console.error("Failed to refresh CSRF token:", err); }); } else { toast.error("Oops!", {