From d8671aa47dd0472b9779918a7a9cdddf9bfde355 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Fri, 6 Mar 2026 16:31:54 -0500 Subject: doc: architecture and authentication --- doc/auth.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 doc/auth.md (limited to 'doc/auth.md') diff --git a/doc/auth.md b/doc/auth.md new file mode 100644 index 0000000..a8aeb25 --- /dev/null +++ b/doc/auth.md @@ -0,0 +1,50 @@ +# Authentication + +## Registration flow +This is how a new user registers himself in `authfs`, after which he can open sessions. +- Client `GET`s `shop./register.html` +- Client enters username and password, `POST`s form to `auth./register` +- `buthauth` server registers user in `authfs` + - Creates `/users//` + - If it already exists, the username is taken; return error to client + - Writes password to `/users//passwd` +- `authfs` ingests and hashes the password. Subsequent reads of `/users//passwdhash` will return the hash (`authfs` discards the cleartext password after it is hashed). +- If successful, client can now login to obtain a session + +## Login flow +This is how a client authenticates itself and creates a _session_. A session gives the client a shopping cart and access to the checkout. +- Client `GET`s `shop./login.html`. +- Client enters username and password (assume they already have an account). +- Js or wasm script running in client generates a 256-bit session ID and injects it into the login form. +- Client `POST`s the login form to `auth./login` +- `buthauth` writes the password to `/users//login` in `authfs` + - If `/users//` doesn't exist, the username is invalid; fail the login +- `buthauth` reads from `/users//login`. +- If the password was correct, `authfs` returns a session ID corresponding to `/sessions// + - Otherwise if the password was wrong, `authfs` returns `Rerror`. `buthauth` fails the login, returning an error to the client +- `buthauth` returns a session cookie, containing the session ID, to the client (with proper security params: HttpOnly etc.) +- Client includes the session cookie in subsequent requests, giving it elevated privileges. + +On the client, session is a _session cookie_ (no expiry date). On the server, it should expire after `lastseen+t`. `authfs` periodically sweeps the sessions and removes old ones. `authfs` updates a sessions's last-seen time whenever it gets a request on `/sessions//*`. + +## API usage +This is how a client accesses the 9P API once he's logged in (has a session cookie). +- Client `GET`s `shop./foo.html` + - Includes cookie in request +- Httpd returns static page and scripts +- Script opens websocket on `api./ws` +- Browser sends cookie automatically in upgrade request +- `buthapi` validates session (using cookie) by checking if `/sessions//` exists on `authfs`. + - If not, the session is invalid, return 401 +- `buthapi` upgrades the websocket connection and serves 9P +- Client uses ws/9p connection to access API + - E.g. pressing "add to cart" button does `Tcreate /cart/sku123` + - (will need to figure out how to wire this up with htmx/js and 9p js/wasm lib) + +## Logout flow +This is how a client destroys an active session on the server. +- Client clicks Logout button +- Htmx `POST`s to `auth./logout`, includes the session cookie in the request +- `buthauth` reads the session ID from the cookie +- `buthauth` removes `/sessions/` on `authfs` +- `buthauth` returns a response header telling the client browser to destroy the session cookie. -- cgit v1.2.3