webui: persist login sessions so they survive restarts

Sessions lived in an in-memory array, so every daemon restart wiped them
and forced a re-login. Move them into the webui DB:

- New sessions table storing a SHA-256 of the bearer token (never the
  raw token, so a DB read can't be replayed), the user, role, and an
  absolute expiry.
- create/lookup/touch/delete + per-user delete + prune in webui_store.
- Login persists the session; auth checks validate against the DB with a
  throttled sliding expiry (re-extended at most hourly to avoid a write
  per request); logout and admin reset/delete drop the rows. Expired
  rows are reaped lazily on lookup and pruned at startup.
- TTL is configurable via NAUT_SESSION_TTL (default 7 days) and drives
  the cookie Max-Age. Removes the in-memory session array + auth_lock.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
ookami125 2026-06-24 21:00:36 -04:00
parent 096535292d
commit 067b62c23a
3 changed files with 190 additions and 70 deletions

View file

@ -44,6 +44,20 @@ bool webui_store_delete_user(webui_store *s, const char *username);
* json array `out`. Returns false on error. */
bool webui_store_list_users(webui_store *s, json_t *out);
/* --- sessions (persisted so logins survive daemon restarts) --------------- *
* Only a SHA-256 of the bearer token is stored, so a DB read can't be replayed
* as a live cookie. `expires` is an absolute unix time. */
bool webui_store_session_create(webui_store *s, const char *token,
const char *user, const char *role, long expires);
/* On a live (unexpired) session, copies username/role and the stored expiry. */
bool webui_store_session_lookup(webui_store *s, const char *token,
char *user, size_t user_sz,
char *role, size_t role_sz, long *expires_out);
bool webui_store_session_touch(webui_store *s, const char *token, long expires);
bool webui_store_session_delete(webui_store *s, const char *token);
bool webui_store_sessions_delete_user(webui_store *s, const char *user);
void webui_store_sessions_prune(webui_store *s, long now);
/* --- category / tag taxonomy (web-UI organization, owned here) ------------- *
* The save_* calls replace the whole list atomically; the load_* calls append
* to the (array) `out`. Categories are {name, savePath}; tags are strings. */