From f1d2b11c0f7aedfede2f92852552ba8e94994e92 Mon Sep 17 00:00:00 2001 From: Madhura68 Date: Wed, 29 Apr 2026 18:17:45 +0200 Subject: [PATCH] feat(ST-1110.3): add proxy.ts demo-guard for non-GET API routes --- proxy.ts | 37 ++++++++++++++++++++++++++++++------- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/proxy.ts b/proxy.ts index 0a4e228..53ae423 100644 --- a/proxy.ts +++ b/proxy.ts @@ -1,17 +1,40 @@ import { NextResponse } from 'next/server' import type { NextRequest } from 'next/server' -import { sessionOptions } from '@/lib/session' +import { getIronSession } from 'iron-session' +import { sessionOptions, type SessionData } from '@/lib/session' const protectedRoutes = ['/dashboard', '/products', '/todos', '/settings', '/solo'] const authRoutes = ['/login', '/register'] -export function proxy(request: NextRequest) { - const path = request.nextUrl.pathname - const isProtected = protectedRoutes.some(r => path.startsWith(r)) - const isAuthRoute = authRoutes.some(r => path.startsWith(r)) +const SAFE_METHODS = new Set(['GET', 'HEAD', 'OPTIONS']) - // Check cookie existence only — full session validation happens in layout.tsx +// Paden die demo MAY aanroepen ook al zijn het non-GET — worden ingevuld na ST-1110.4 +const DEMO_WRITE_ALLOWLIST = [ + '/api/cron/', // machine-auth, irrelevant for demo +] + +export async function proxy(request: NextRequest) { + const { pathname, method } = { pathname: request.nextUrl.pathname, method: request.method } + + // Demo-guard: block non-GET API writes for demo users (defense in depth) + if ( + pathname.startsWith('/api/') && + !SAFE_METHODS.has(method) && + !DEMO_WRITE_ALLOWLIST.some(p => pathname.startsWith(p)) + ) { + const session = await getIronSession(request.cookies, sessionOptions) + if (session.isDemo) { + return NextResponse.json( + { error: 'Niet beschikbaar in demo-modus' }, + { status: 403 } + ) + } + } + + // Route protection: check cookie existence only — full validation in layout.tsx const hasSession = !!request.cookies.get(sessionOptions.cookieName)?.value + const isProtected = protectedRoutes.some(r => pathname.startsWith(r)) + const isAuthRoute = authRoutes.some(r => pathname.startsWith(r)) if (isProtected && !hasSession) { return NextResponse.redirect(new URL('/login', request.url)) @@ -25,5 +48,5 @@ export function proxy(request: NextRequest) { } export const config = { - matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'], + matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'], }