request; // Skip CSRF validation for API routes temporarily for testing if (str_starts_with($request->path, '/api/')) { error_log("CsrfMiddleware: Skipping CSRF validation for API route: " . $request->path); return $next($context); } // Try to get session from container - graceful fallback if not available try { $session = $this->container->get(SessionInterface::class); } catch (\Throwable $e) { // Session not available - skip CSRF validation gracefully error_log("CsrfMiddleware: Session not available, skipping CSRF validation"); return $next($context); } if (in_array($request->method, [Method::POST, Method::PUT, Method::DELETE, Method::PATCH])) { $this->validateCsrfToken($request, $session); } $context = $next($context); // After successful request processing, optionally rotate token for enhanced security // This can be enabled for high-security applications // $this->rotateTokenIfNeeded($request, $session); return $context; } /** * Validates CSRF token from the request */ private function validateCsrfToken(Request $request, SessionInterface $session): void { $formId = $request->parsedBody->get('_form_id') ?? $request->headers->getFirst('X-CSRF-Form-ID'); $tokenValue = $request->parsedBody->get('_token') ?? $request->headers->getFirst('X-CSRF-Token'); // Debug: Log CSRF validation attempt error_log("CSRF Debug: Validating tokens for form_id='$formId'"); if (! $formId || ! $tokenValue) { throw new \InvalidArgumentException('CSRF protection requires both form ID and token'); } try { $token = CsrfToken::fromString($tokenValue); } catch (\InvalidArgumentException $e) { throw new \InvalidArgumentException('Invalid CSRF token format: ' . $e->getMessage()); } if (! $session->csrf->validateToken($formId, $token)) { error_log("CSRF validation failed for form: " . $formId); throw new \RuntimeException('CSRF token validation failed. This may indicate a security threat.'); } } /** * Rotates CSRF token after successful form submission for enhanced security */ private function rotateTokenIfNeeded($request): void { $formId = $request->parsedBody->get('_form_id'); if ($formId) { // Generate a fresh token for the next request $this->session->csrf->rotateToken($formId); } } }