fix(dashboard): exempt SPA shell from bearer-token auth
The bearer-token middleware was mounted globally on the Express app, so the initial GET /?token=<token> request for index.html was rejected with 401 before the frontend JS could even load and capture the token from the URL. The server-side query-string fallback only accepts fn_token=, while the banner URL uses ?token= (which only the frontend captures), so the bootstrap request had no valid auth path. Fix: gate auth on /api/* only. The SPA shell (index.html, /assets/*, favicon) is public — it contains no secrets, and the frontend auth.ts module captures the token into localStorage and installs a fetch wrapper that injects Authorization: Bearer on every /api/* call. Also: add .env / .env.local to .gitignore so local FUSION_DAEMON_TOKEN values don't accidentally get committed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -392,8 +392,12 @@ export function createServer(store: TaskStore, options?: ServerOptions): ReturnT
|
||||
}));
|
||||
|
||||
// Daemon mode: bearer token authentication middleware
|
||||
// Auth is enabled when daemon option is provided OR FUSION_DAEMON_TOKEN env var is set
|
||||
// The middleware itself exempts /api/health for liveness probes
|
||||
// Auth is enabled when daemon option is provided OR FUSION_DAEMON_TOKEN env var is set.
|
||||
// The middleware exempts /api/health and everything outside /api/ — the SPA shell
|
||||
// (index.html + built assets) is public so the browser can load the frontend JS
|
||||
// that then captures ?token= from the URL and injects a Bearer header on every
|
||||
// /api/* call. WebSocket upgrades are gated separately in setupTerminalWebSocket /
|
||||
// setupBadgeWebSocket.
|
||||
const daemonToken = options?.daemon?.token ?? process.env.FUSION_DAEMON_TOKEN;
|
||||
if (daemonToken) {
|
||||
app.use(createAuthMiddleware(daemonToken));
|
||||
|
||||
Reference in New Issue
Block a user