- Rate-limit /api/flows/start to 10 req/min per user (in-memory, matches login pattern) - Add middleware.ts: validates x-csrf-token header against csrf_token cookie on all API POST requests; issues the cookie on GET if missing; sets CSP, X-Frame-Options, X-Content-Type-Options, and Referrer-Policy on all responses - Add lib/csrf.ts: client-side apiFetch() wrapper that injects the CSRF header - Update all client components (login, useFlowRun, docker, caddy, git, systemd) to use apiFetch() for POST requests - Cookie config in login route already correct (NODE_ENV check, httpOnly, sameSite=strict) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
21 lines
635 B
TypeScript
21 lines
635 B
TypeScript
'use client'
|
|
|
|
function getCsrfToken(): string {
|
|
if (typeof document === 'undefined') return ''
|
|
return (
|
|
document.cookie
|
|
.split('; ')
|
|
.find((c) => c.startsWith('csrf_token='))
|
|
?.split('=')[1] ?? ''
|
|
)
|
|
}
|
|
|
|
/** Drop-in replacement for fetch() that automatically injects the CSRF token on POST requests. */
|
|
export function apiFetch(url: string, init: RequestInit = {}): Promise<Response> {
|
|
if ((init.method ?? 'GET').toUpperCase() !== 'POST') {
|
|
return fetch(url, init)
|
|
}
|
|
const headers = new Headers(init.headers)
|
|
headers.set('x-csrf-token', getCsrfToken())
|
|
return fetch(url, { ...init, headers })
|
|
}
|