diff options
| author | Maze <167211895+mazeincoding@users.noreply.github.com> | 2025-07-16 10:54:38 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-16 10:54:38 +0200 |
| commit | 27731a270dec7f854876157fac790d998b3b6a8c (patch) | |
| tree | 039276169065a6aa254f4e30730e014e34936bd8 /apps/web/src/app/api/waitlist/token | |
| parent | d5c52557df6063cf856015b958f1c08c3b9de3de (diff) | |
| parent | 79f6c680f394ec4a9970124cfe915b05c1b969df (diff) | |
| download | opencut-27731a270dec7f854876157fac790d998b3b6a8c.tar.gz | |
Merge pull request #291 from ahmetskilinc/better-rate-limiting
feat: better-rate-limiting
Diffstat (limited to 'apps/web/src/app/api/waitlist/token')
| -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 }); +} |
