TASK-022: Hash session tokens in database for security
- Store session tokens as one-way SHA256 hashes instead of plaintext - Hash tokens on write (create_session) and on read (get_session, delete_session) - Add migration to drop plaintext sessions table and recreate with token_hash column - Update Session model: token field still contains raw token for signing - Add test to verify tokens are hashed in database, not plaintext - Update Architekture.md to document session token hashing - Update Backend-Development.md with implementation pattern and best practices Prevents direct session token hijacking if database file is exposed to attacker. If plaintext DB was readable, sessions are invalidated by the migration anyway. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -647,7 +647,7 @@ BanGUI maintains its **own SQLite database** (separate from the fail2ban databas
|
||||
| Table | Purpose |
|
||||
|---|---|
|
||||
| `settings` | Key-value store for application configuration (master password hash, fail2ban socket path, database path, timezone, session duration) |
|
||||
| `sessions` | Active session tokens with expiry timestamps |
|
||||
| `sessions` | Active session token hashes with expiry timestamps. Tokens are stored as one-way SHA256 hashes to prevent token hijacking if the database is exposed. |
|
||||
| `geo_cache` | Resolved IP geolocation results (ip, country_code, country_name, asn, org, cached_at). Loaded into memory at startup via `load_cache_from_db()`; new entries are flushed back by the `geo_cache_flush` background task. |
|
||||
| `blocklist_sources` | Registered blocklist URLs (id, name, url, enabled, created_at, updated_at) |
|
||||
| `import_logs` | Record of every blocklist import run (id, source_id, timestamp, ips_imported, ips_skipped, errors, status) |
|
||||
@@ -665,7 +665,8 @@ BanGUI maintains its **own SQLite database** (separate from the fail2ban databas
|
||||
|
||||
- **Single-user model** — one master password, no usernames.
|
||||
- Password is hashed with a strong algorithm (e.g., bcrypt or argon2) and stored in the application database during setup.
|
||||
- Sessions are token-based, stored server-side in the `sessions` table, and delivered to the browser as HTTP-only secure cookies.
|
||||
- Sessions are token-based, stored server-side in the `sessions` table as one-way SHA256 hashes, and delivered to the browser as HTTP-only secure cookies.
|
||||
- **Session token hashing** — Session tokens are hashed before storage to prevent token hijacking if the database file is exposed. Only the hash (`token_hash`) is stored in the database; the raw token is never persisted. When validating a session, the incoming token is hashed before the database lookup. This ensures the database alone is not sufficient to usurp a session — an attacker would also need knowledge of the original token value.
|
||||
- Session expiry is configurable (set during setup, stored in `settings`).
|
||||
- The frontend `AuthProvider` checks session validity on mount and redirects to `/login` if invalid.
|
||||
- The backend `dependencies.py` provides an `authenticated` dependency that validates the session cookie on every protected endpoint.
|
||||
|
||||
Reference in New Issue
Block a user