1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
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/<username>/`
- If it already exists, the username is taken; return error to client
- Writes password to `/users/<username>/passwd`
- `authfs` ingests and hashes the password. Subsequent reads of `/users/<username>/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/<username>/login` in `authfs`
- If `/users/<username>/` doesn't exist, the username is invalid; fail the login
- `buthauth` reads from `/users/<username>/login`.
- If the password was correct, `authfs` returns a session ID corresponding to `/sessions/<id>/
- 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/<id>/*`.
## 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/<id>/` 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/<id>` on `authfs`
- `buthauth` returns a response header telling the client browser to destroy the session cookie.
|