Harden request origin checks and configure allowed hosts
This commit is contained in:
32
lib/api.ts
32
lib/api.ts
@@ -5,6 +5,7 @@ import { z } from "zod";
|
||||
import { admin, required, user } from "./supabase";
|
||||
import { datasetSchema, faces, difficulties } from "../shared/protocol";
|
||||
import { mediaUrl } from "./catalog";
|
||||
import { requestOrigin, verifyOrigin } from "./request-origin";
|
||||
const hash = (value: string) =>
|
||||
createHash("sha256").update(value).digest("hex");
|
||||
const idSchema = z.string().uuid();
|
||||
@@ -91,21 +92,6 @@ async function jsonBody(request: NextRequest) {
|
||||
}
|
||||
return JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
||||
}
|
||||
function verifyOrigin(request: NextRequest) {
|
||||
if (request.method === "GET" || request.method === "HEAD") return;
|
||||
const origin = request.headers.get("origin");
|
||||
const allowed = new Set([
|
||||
new URL(request.url).origin,
|
||||
process.env.MINEGEO_URL || "http://localhost:3000",
|
||||
]);
|
||||
if (origin && !allowed.has(origin)) throw new Error("Invalid request origin");
|
||||
if (
|
||||
!origin &&
|
||||
!request.headers.get("authorization") &&
|
||||
!request.headers.get("content-type")?.includes("application/json")
|
||||
)
|
||||
throw new Error("JSON request required");
|
||||
}
|
||||
export async function handle(request: NextRequest, path: string[]) {
|
||||
try {
|
||||
verifyOrigin(request);
|
||||
@@ -537,7 +523,7 @@ export async function handle(request: NextRequest, path: string[]) {
|
||||
return NextResponse.json({
|
||||
deviceCode,
|
||||
userCode: code,
|
||||
verificationUri: `${process.env.MINEGEO_URL || new URL(request.url).origin}/pair?code=${code}`,
|
||||
verificationUri: `${process.env.MINEGEO_URL ? new URL(process.env.MINEGEO_URL).origin : requestOrigin(request)}/pair?code=${code}`,
|
||||
interval: 5,
|
||||
});
|
||||
}
|
||||
@@ -622,13 +608,13 @@ export async function handle(request: NextRequest, path: string[]) {
|
||||
.parse(await jsonBody(request));
|
||||
if (b.decision === "reject" && !b.reason?.trim())
|
||||
throw new Error("Provide a rejection reason");
|
||||
const {error}=await client.rpc("publish_dataset", {
|
||||
p_dataset: b.datasetId,
|
||||
p_reviewer: reviewer,
|
||||
p_decision: b.decision,
|
||||
p_reason: b.reason ?? null,
|
||||
});
|
||||
if(error)throw new Error(error.message);
|
||||
const { error } = await client.rpc("publish_dataset", {
|
||||
p_dataset: b.datasetId,
|
||||
p_reviewer: reviewer,
|
||||
p_decision: b.decision,
|
||||
p_reason: b.reason ?? null,
|
||||
});
|
||||
if (error) throw new Error(error.message);
|
||||
return NextResponse.json({ ok: true });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user