Expand description
Session tokens, the cookie they travel in, the extractors that resolve them, the CSRF check, and the login rate limiter.
§The token
32 bytes from the system CSPRNG, base64url-unpadded (43 characters, cookie-
safe unquoted). Stored as hex(SHA-256(token)) and never in plaintext, so
a read of the database — a backup, a .dump, an injection — yields nothing
replayable. Not the password KDF: the token has 256 bits of entropy, so
there is no dictionary to slow down and a slow hash would buy nothing but
latency on every request. Lookup is by the hash, and the value looked up
is the secret, so that path needs no constant-time comparison — unlike
the CSRF token, which is compared against a caller-supplied string.
§CSRF, and why SameSite=Strict is not enough
The usual answer is that SameSite covers it. It does not, here, and the
reason is specific: SameSite is scoped to the registrable domain, not the
origin — different ports of the same host are same-site. A panel on
:3001 beside anything else on :8080 of the same box is exactly the
configuration it does not protect. So there is a per-session token as well,
plus an origin gate that also covers login (which by definition carries no
session token yet).
Enforcement is structural: one of AuthenticatedWrite,
AdminWrite or SelfServiceWrite is the only way for a mutating
handler to reach a session, and constructing any of them runs the origin
and CSRF checks. The three differ only in the privilege tier they demand —
operator+, admin, and none (own-account routes) — so a handler that
forgets the role check cannot compile. Same reasoning as hoisting the
media-type/crit/url/nonce checks into AcmeRequest — a new endpoint
cannot forget what it cannot express.
Structs§
- Admin
Client Ip - The client address of an admin request, if the socket carried one.
- Admin
Read Authenticatedplus a privilege tier ofAdminRole::Admin– the read-side sibling ofAdminWrite, with no CSRF or origin gate, since aGETchanges nothing.- Admin
Write AuthenticatedWrite, but requiring the fullAdminRole::Admintier.- Authenticated
- A live session and the operator it belongs to. Read-only handlers take this.
- Authenticated
Write Authenticated, the origin gate and the CSRF check, plus a privilege tier of at leastAdminRole::Operator.- Enrol
Write - A session allowed to set up a factor.
- Login
Attempt - One login attempt’s slot in the
LoginLimiter. - Login
Limiter - Fixed-window failed-login counter, keyed by client address.
- Minted
Token - A freshly minted session token, and the hash to store for it.
- Pending
Mfa - A session with a verified password and nothing more.
- Pending
MfaSubmit PendingMfawith the origin gate only, and no CSRF check.- Self
Service Write - The origin gate, a live
activesession and the CSRF check – no privilege check, so any role includingviewerpasses.
Enums§
- MfaStep
- What still stands between a
pending_mfacookie and a usable session.
Constants§
- COOKIE_
NAME - The session cookie’s name.
- CSRF_
HEADER - The header carrying the per-session CSRF token on unsafe methods.
- PENDING_
MFA_ TTL - How long a half-authenticated session may sit unfinished.
Functions§
- check_
csrf - Compares the request’s
X-CSRF-Tokenagainst the session’s, in constant time. - check_
origin - Refuses a request whose
OriginorSec-Fetch-Sitesays it came from somewhere else. - clearing_
cookie - The
Set-Cookievalue that clears one. - cookie_
value - Reads the session token out of a
Cookieheader set. - hash_
token hex(SHA-256(token))— theadmin_sessionsprimary key.- log_
login - Logs a completed login attempt. One place, so the events cannot drift.
- mint_
csrf_ token - Mints a CSRF token. Same entropy as a session token — it is stored in plaintext, but it still has to be unguessable.
- mint_
token - Mints a session token. RNG failure is unrecoverable, as elsewhere in this crate.
- session_
cookie - The
Set-Cookievalue that establishes a session.