From 6cdfc55e5712075fef24a559138c054ef58e1ac1 Mon Sep 17 00:00:00 2001 From: Peter Stone Date: Tue, 20 Jan 2026 17:02:16 -1000 Subject: Fix CSRF token missing from refresh fetch requests Manual JavaScript fetch() calls weren't including the CSRF token, causing 403 Forbidden on /api/refresh. Extract token from hx-headers body attribute and include in all POST requests. Co-Authored-By: Claude Opus 4.5 --- web/static/js/app.js | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/web/static/js/app.js b/web/static/js/app.js index 0f1f087..4d26e66 100644 --- a/web/static/js/app.js +++ b/web/static/js/app.js @@ -3,6 +3,21 @@ // Constants const AUTO_REFRESH_INTERVAL = 5 * 60 * 1000; // 5 minutes in milliseconds +// Get CSRF token from body hx-headers attribute +function getCSRFToken() { + const body = document.body; + const headers = body.getAttribute('hx-headers'); + if (headers) { + try { + const parsed = JSON.parse(headers); + return parsed['X-CSRF-Token'] || ''; + } catch (e) { + console.error('Failed to parse CSRF token:', e); + } + } + return ''; +} + // Track current active tab (read from URL for state persistence) const urlParams = new URLSearchParams(window.location.search); let currentTab = urlParams.get('tab') || 'tasks'; @@ -94,7 +109,10 @@ async function refreshData() { try { // Force API refresh (updates cache) const refreshResponse = await fetch('/api/refresh', { - method: 'POST' + method: 'POST', + headers: { + 'X-CSRF-Token': getCSRFToken() + } }); if (!refreshResponse.ok) throw new Error('Refresh failed'); @@ -148,7 +166,10 @@ async function autoRefresh() { try { // Force API refresh (updates cache) const refreshResponse = await fetch('/api/refresh', { - method: 'POST' + method: 'POST', + headers: { + 'X-CSRF-Token': getCSRFToken() + } }); if (!refreshResponse.ok) throw new Error('Refresh failed'); -- cgit v1.2.3