feat: add CSRF protection for admin API routes

Double-submit cookie pattern: login sets bh-csrf-token cookie,
proxy.ts validates X-CSRF-Token header on POST/PUT/DELETE to /api/admin/*.
New adminFetch() helper in src/lib/csrf.ts auto-includes the header.
All admin pages migrated from fetch() to adminFetch().

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-17 17:53:02 +03:00
parent 3ac6a4d840
commit 6cbdba2197
12 changed files with 161 additions and 53 deletions

View File

@@ -2,6 +2,7 @@
import { useState, useEffect, useRef, useCallback } from "react";
import { Loader2, Check, AlertCircle } from "lucide-react";
import { adminFetch } from "@/lib/csrf";
interface SectionEditorProps<T> {
sectionKey: string;
@@ -24,7 +25,7 @@ export function SectionEditor<T>({
const initialLoadRef = useRef(true);
useEffect(() => {
fetch(`/api/admin/sections/${sectionKey}`)
adminFetch(`/api/admin/sections/${sectionKey}`)
.then((r) => {
if (!r.ok) throw new Error("Failed to load");
return r.json();
@@ -39,7 +40,7 @@ export function SectionEditor<T>({
setError("");
try {
const res = await fetch(`/api/admin/sections/${sectionKey}`, {
const res = await adminFetch(`/api/admin/sections/${sectionKey}`, {
method: "PUT",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(dataToSave),