diff options
| author | enkei64 <imenkei64@gmail.com> | 2025-07-16 19:07:33 +1000 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-16 19:07:33 +1000 |
| commit | 0cb26ef088d7b813bef4fd702ac26b813f1a9db1 (patch) | |
| tree | da9042be04762fda283df64a4684e1cf3644b301 /apps/web/src/app/api/waitlist/token/route.ts | |
| parent | 7c6b2e4f499a9878b641bac5692f5a2ee884d125 (diff) | |
| parent | 27731a270dec7f854876157fac790d998b3b6a8c (diff) | |
| download | opencut-0cb26ef088d7b813bef4fd702ac26b813f1a9db1.tar.gz | |
Merge branch 'OpenCut-app:main' into feat/display-all-contributors
Diffstat (limited to 'apps/web/src/app/api/waitlist/token/route.ts')
| -rw-r--r-- | apps/web/src/app/api/waitlist/token/route.ts | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/apps/web/src/app/api/waitlist/token/route.ts b/apps/web/src/app/api/waitlist/token/route.ts new file mode 100644 index 00000000..4c7695fa --- /dev/null +++ b/apps/web/src/app/api/waitlist/token/route.ts @@ -0,0 +1,46 @@ +import { NextRequest, NextResponse } from "next/server"; +import { cookies } from "next/headers"; +import crypto from "crypto"; +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"); + const host = request.headers.get("host"); + + if (referer) { + const refererUrl = new URL(referer); + + if (!allowedHosts.some((allowed) => refererUrl.host === allowed || refererUrl.host.endsWith(allowed))) { + return NextResponse.json({ error: "Forbidden" }, { status: 403 }); + } + } else if (host) { + if (!allowedHosts.some((allowed) => host === allowed || host.endsWith(allowed))) { + return NextResponse.json({ error: "Forbidden" }, { status: 403 }); + } + } else { + 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).update(`${token}:${timestamp}`).digest("hex"); + + const cookieStore = await cookies(); + cookieStore.set(CSRF_TOKEN_NAME, `${token}:${timestamp}:${signature}`, { + httpOnly: true, + secure: env.NODE_ENV === "production", + sameSite: "strict", + maxAge: TOKEN_EXPIRY / 1000, + path: "/", + }); + + return NextResponse.json({ token }); +} |
