Commit Graph

18 Commits

Author SHA1 Message Date
mteehan 6404508519 fix: harden auth with refresh token session binding, logging, and router state
- Add session_id to refresh tokens and enforce it during validation,
  preventing stolen refresh tokens from being usable without the
  originating browser session
- Set router.isAuthenticated via auth:login event after successful
  login (previously only set at page load)
- Add console.warn logging to WS message parse/handler errors
- Improve _refreshPromise error handling in token refresh flow
- Document rate limiter in-memory limitation and CSP connect-src
  same-origin requirement
- Add 3 tests for session-bound refresh token validation
2026-08-12 15:53:17 +00:00
mteehan a82578f342 fix: invalidate tokens on permission change (medium), optimize create_user query, fix ws reconnect race
- update_permissions now calls blacklist_active_refresh_token and
  rotate_user_secret to immediately invalidate stale tokens
- create_user uses returned id from tx.run_one instead of redundant SELECT
- websocket reconnect explicitly closes old connection after token refresh
  to prevent onclose handler race condition
2026-07-28 18:02:14 +00:00
mteehan 3de82e3b9b Remove query-string cache-busting from static assets
Drop ?v=N version pins from all JS imports and HTML <link>/<script> tags.
Cache invalidation is now handled solely by server-side cache-control headers.
Update docs and AGENTS.md accordingly.
2026-07-28 13:50:22 +00:00
mteehan f77473c13c fix: missing brace in users.js, ws double-increment, b64url stack overflow, docs storage 2026-07-28 13:17:12 +00:00
mteehan d52a0fad12 fix: check tryRefreshToken result in WS reconnect, clear permissions on logout
The token refresh callback in websocket.js ignored its ok parameter, causing
an infinite reconnect loop when the server rejected the refresh attempt. On
failure, redirect to login instead of reconnecting with a cleared token.

clearAuthTokens() now also removes vw:permissions from sessionStorage to
prevent stale permissions from persisting across logout/login cycles. Also
removed duplicate vw:user removeItem call.
2026-07-28 02:44:09 +00:00
mteehan 739253b2e5 fix: WS reconnection deadlock, remove redundant try/except, fix docs
- websocket.js: schedule reconnect backoff when token refresh fails,
  otherwise WebSocket stays dead after 3+ disconnects with failed refresh
- daemon/handlers/auth.py: remove two redundant try/except ValueError: raise
  blocks in webauthn register/authenticate finish handlers
- docs/api.md: mark permissions as optional in Create User endpoint
2026-07-28 01:44:10 +00:00
mteehan 358573567d fix: dual-key rate limiting for auth + websocket reconnect guard
- Pass client IP (X-Real-IP header) through Flask to daemon for both
  password login and WebAuthn authenticate-finish endpoints
- Rate limiter now checks both IP and username buckets: IP layer catches
  enumeration/brute-force attacks across multiple usernames; username
  layer protects against single-account targeting from multiple IPs
- Add _wsRefreshing flag to prevent double-scheduling reconnect when
  onclose fires during token refresh; simplify async IIFE to .then()/.catch()
- Reset _wsRefreshing on websocket onopen for safety
2026-07-28 00:54:48 +00:00
mteehan cc5679a1cd fix: deduplicate token refresh, serialize concurrent attempts, clean up logout path 2026-07-27 19:15:27 +00:00
wall d4213fb93b fix: auth reconnection loop, duplicate login listeners, modal double-disable
- websocket: clear tokens on refresh failure to prevent infinite 401 loop
- api: write vw:user to sessionStorage on refresh for consistency with WS
- api: remove vw:user from sessionStorage in clearAuthTokens
- login: guard listener setup with flags to prevent duplicate attachment
- modal: skip inline button disable when handler uses processing state
- users: remove unused requestUpdate import
2026-07-24 04:02:44 +00:00
mteehan a365059976 security: harden JWT auth with session binding, CSP headers, and sessionStorage
- Reduce access_token_ttl from 900s to 300s (5 min) to shrink XSS exploit window
- Add session_id claim to JWT tokens tied to browser session (X-Session-Id header)
- Flask middleware validates session_id matches header on every request
- CSP headers: default-src/script-src 'self', no unsafe-inline/eval, frame-ancestors none
- X-Content-Type-Options: nosniff on all responses
- Move refresh token from localStorage to sessionStorage (tab-scoped, cleared on close)
- Timing-safe password verification (dummy Argon2id for unknown users)
- WebSocket auth also validates session_id header
- Add 5 session_id tests and 3 CSP header tests
2026-07-24 03:09:07 +00:00
mteehan 56b200d233 feat: add auth subsystem with WebAuthn passkeys support
New modules: lib/auth, lib/auth_users, lib/db, lib/db_sqlite, lib/password,
lib/webauthn, daemon/handlers/auth, scripts/bootstrap_auth, tests/test_auth

Frontend: webui/api/auth, hoover/components/auth, pages/login, passkeys, users

Updates: daemon/iface and server, lib/common and nginx, pyproject.toml deps,
install script, server.py, app.js, and websocket/api clients
2026-07-24 01:21:39 +00:00
mteehan 2e49dec633 feat: auto-generate self-signed certs, hoover modal processing guard, refactor backends/proxy pages 2026-07-13 14:30:35 +00:00
mteehan 5135de0921 feat: add system config import, refactor install script and nginx auth
- lib/system_import: new module to import system configs into JSON at daemon startup
- daemon/server.py: call import_all() during startup for config reconciliation
- daemon/handlers/nginx.py: simplify add_domain auth handling, remove duplicate code
- scripts/install.sh: replace inline Python setup with curl-based daemon API calls; apply IP forwarding at runtime
- hoover: bump internal asset versions to v=8
- pages: bump asset versions to v=9
2026-07-08 02:20:28 +00:00
mteehan 5ba0f31767 Add state management, WebSocket polling, html.js templating, and refactor pages
- lib/state.py: per-subsystem collectors with versioned state store
- daemon/server.py: state refresh on request, batch routing updates
- webui/static/hoover/html.js: new html tag template helper via htm.js
- webui/static/hoover/websocket.js: real-time state change notifications
- webui/static/hoover/vdom.js: VDOM improvements for keyed diff
- All frontend pages refactored to use html templates
- Add tests for state management and polling
- Update docs and AGENTS.md
2026-06-23 21:12:56 +00:00
mteehan b673e87c9b refactor: introduce model layer for centralized data synchronization
Add hoover model.js as a central reactive store per subsystem, replacing
per-component data fetching with a single source of truth.

- Add hoover/model.js with modelRegister, modelFetch, and WS invalidation
- Refactor websocket.js to route messages to model refresh (drop per-component
  subscribe/unsubscribe)
- Simplify component.js by removing WS subscription management
- Add refresh option to apiSubmit, deprecate refactorLoad and checkAbort
- Rewrite all pages to use getModel() instead of inline data fetching
- Bootstrap model registrations in app.js
- Add GET /api/firewall/state endpoint
- Fix restart-services.sh restart order and add service health verification
- Update hoover.md docs with model layer architecture
2026-06-22 22:54:29 +00:00
mteehan 633505e7dc refactor: modernize frontend with hoover framework components and docs
- Add quick modal, table, service status, and confirmation dialog components
- Refactor all pages (certs, dhcp, proxy, etc.) to use new component patterns
- Introduce refactor load utility and render guard for consistent UX
- Add hoover documentation and update AGENTS.md, architecture, overview
2026-06-21 04:29:27 +00:00
mteehan 687fa8f52f pre-refactor 2026-06-17 03:41:08 +00:00
mteehan 593dece92b refactor: replace Jinja templates with static frontend pages 2026-06-16 03:50:00 +00:00