Skip to content

feat(web): token login page with persisted sessions - #30

Merged
tylinux merged 1 commit into
mainfrom
feat/web-token-login
Oct 8, 2026
Merged

tylinux merged 1 commit into
mainfrom
feat/web-token-login

Conversation

@tylinux

@tylinux tylinux commented Oct 8, 2026

Copy link
Copy Markdown
Collaborator

Summary

Servers started with NEX_SERVER_AUTH_TOKEN now show a sign-in page instead of a half-working app when the browser has no valid session. Spec: docs/specs/web-token-login.md.

  • Login page (/login): one field, the access token. No/invalid session sends the browser to /login?next=<original page>; after login it returns there. next only accepts same-origin relative paths.
  • Sessions: the browser holds a random nex_session cookie (HttpOnly, SameSite=Lax, Secure behind https, 30 days). Session ids are stored as SHA-256 hashes in <configDir>/web-sessions.json (0600, atomic write). Changing the token invalidates all stored sessions. A corrupt file fails closed.
  • Compatibility: ?token= still works for programmatic /ws//api clients, and /?token=… still signs in a browser (then the token is removed from the address bar).
  • Hardening: constant-time token compare; 5 failed logins per address lock sign-in for 60s (429 + Retry-After).
  • Mid-session loss: if the socket closes and the server reports the session is gone (expiry, token rotation), the app returns to /login. Plain disconnects are not treated as logout; checks retry with backoff while the server restarts.

Behaviour change

The old nex_lite_token cookie (which held the raw token) is no longer accepted. Existing browsers see the login page once. Provisioning (install.sh, plist, docker-compose) is unchanged.

Testing

  • pnpm typecheck: pass; pnpm lint: 0 errors (80 existing warnings); pnpm architecture:check --changed: 0 new violations
  • New unit tests: server 19, web 11 (also added to both CI workflows); ui 79 pass
  • Real browser run (headless Chromium against an isolated server on :3131): redirect to login, wrong token error, login, reload, /login while signed in, open-redirect next ignored, deep link preserved, ?token= first visit and address-bar cleanup, logout, restart with same token keeps the user in, token rotation while open returns to login, 6th bad attempt rate-limited
  • Not verified: behind an https reverse proxy (Secure cookie covered by a unit test only), mobile browsers, the production :3030 service (not redeployed)

Replace the raw-token cookie with a sign-in flow for servers started with
NEX_SERVER_AUTH_TOKEN.

- Server: /api/auth/{session,login,logout}; random session ids, stored hashed
  in <configDir>/web-sessions.json (0600, atomic writes) and discarded when
  the token changes; per-address login rate limit; ?token= still works for
  programmatic /ws clients and first visits.
- Web: /login page (token only), redirect to /login?next=... when there is no
  valid session, return to the original page after login, and back to /login
  if the session is lost while the app is open.
- Spec: docs/specs/web-token-login.md. CI now runs the server and web unit tests.
@tylinux
tylinux merged commit 85acf61 into main Oct 8, 2026
2 checks passed
@tylinux
tylinux deleted the feat/web-token-login branch October 8, 2026 12:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant