summaryrefslogtreecommitdiffstats
path: root/doc/auth.md
blob: d3a292450a4d0abf9a3a1c39cfc786c5e86cd60c (plain) (blame)
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
# Authentication

## Registration
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 `api./register`
- `buthd`  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.
- If successful, client can now login to obtain a session

## Login
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.
- JS script running in client generates a 256-bit session ID and injects it into the login form.
- Client `POST`s the login form to `api./login`
- `buthd` writes the password to `/users/<username>/login` in `authfs`
	- If `/users/<username>/` doesn't exist, the username is invalid; fail the login
- `buthd` 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`. `buthd` fails the login, returning an error to the client
- `buthd` 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>/*`.

Generate the session id on the client side to take advantage of the abundance of entropy there compared to on the server.

## Logout
This is how a client destroys an active session on the server.
- Client clicks Logout button
- htmx `POST`s to `api./logout`, includes the session cookie in the request
- `buthd reads the session ID from the cookie
- `buthd` removes `/sessions/<id>` on `authfs`
- `buthd` returns a response header telling the client browser to destroy the session cookie.

## TODO
- Allow the user to register an email for password recovery?
- Document changing password: buthd writes to `/users/<username>/passwd`

## Implementation notes

Don't leave 9p connections laying around. Open a new one for each http request as required. This is to avoid attacks like the following.
Suppose buthd has a single connection to authfs that it uses for every http connection. Alice (the attacker) and Bob are both trying to login as `bob`. Alice's connection writes a junk password to `/users/bob/login`. Bob's connection writes the correct password. Alice's connection reads `login`, obtaining the session ID, as does Bob's connection. Now Alice has Bob's session ID and can act as Bob. This is bad.