53 lines
3.9 KiB
Markdown
53 lines
3.9 KiB
Markdown
# Authentication boundary (§13)
|
|
|
|
- Real logins retain `dsh_session` as a database session binding and require a
|
|
five-minute HS256 access JWT in an additional HttpOnly cookie. JWT verification
|
|
fixes the algorithm and binds subject/session/issuer/audience/expiry. Bare
|
|
session IDs never authenticate. Internal callers and test fixtures must also
|
|
attach a signed access cookie. Database session expiry or revocation rejects
|
|
access even if the JWT's five-minute expiry has not yet elapsed.
|
|
- The initial refresh token is random 256-bit data in an HttpOnly cookie, scoped to `/api`, with only its
|
|
SHA-256 hash stored in SQLite. The session has an absolute lifetime configured
|
|
by SESSION_TTL (default 24h), applied only to new logins. Values use Go duration
|
|
syntax (e.g. 168h, not 7d), must be at least one second and a whole number of
|
|
seconds; invalid values prevent startup when the store is opened.
|
|
Session, refresh and CSRF cookies persist across browser restarts with explicit
|
|
Max-Age/Expires bounded by that database expiry; rotation does not extend it.
|
|
Transactional rotation stores current and previous token hashes. A keyed,
|
|
session-bound successor derivation makes retries of the previous token return
|
|
the same current token, including after response loss or server restart. Only
|
|
one previous generation is accepted (until the next rotation or session expiry);
|
|
this intentionally permits that generation to be replayed with the required
|
|
session/Origin/CSRF checks. Older and unknown tokens are rejected. Plaintext
|
|
refresh credentials are never stored.
|
|
Logout deletes the database session and its refresh binding. Both refresh and
|
|
logout retain mandatory exact Origin and session-bound CSRF checks, even when
|
|
access has expired, but require an unexpired database session. Logout does not
|
|
require the refresh cookie. Other protected operations require valid access.
|
|
Self-service password changes and administrator password resets revoke all of
|
|
that user's sessions and refresh bindings, requiring a new login.
|
|
- Signing key is generated once under the configured data root, private mode
|
|
0600, and reused across restarts. Initialization errors fail authentication closed.
|
|
Session/access/refresh credentials are issued as cookies, not JSON or URLs,
|
|
and are not included in authentication audit detail or application logs. The
|
|
CSRF token is intentionally returned as `csrf_token` by login, refresh and
|
|
`/api/me`, and is also in the JavaScript-readable `dsh_csrf` cookie. All four
|
|
cookies use SameSite=Lax; the other three are HttpOnly. Secure is enabled by
|
|
direct TLS or an HTTPS PANEL_PUBLIC_URL, not forwarded protocol headers.
|
|
Origin checks compare against the configured public origin, or direct request
|
|
scheme/Host if it is unset; forwarded Host/Proto headers are not used.
|
|
- Known accounts lock for 15 minutes after five failures; the counter/lock survive
|
|
restart. Successful login resets the counter; expired locks reset the counter.
|
|
Current-password reauthentication failures share this account lock; successful
|
|
reauthentication alone does not reset the counter. Additional login protection
|
|
allows 30 attempts per source per minute, at most 1024 source buckets, and eight
|
|
admitted concurrent login requests (credential checks are serialized). Source
|
|
identity uses the direct peer unless it matches TRUSTED_PROXY_CIDRS, a
|
|
comma-separated CIDR list; then X-Forwarded-For is scanned right-to-left for
|
|
the first untrusted address. These in-memory limits reset on process restart.
|
|
The server runs expired-session/refresh and elapsed-lock cleanup immediately
|
|
and every ten minutes; expiry checks do not wait for cleanup.
|
|
- Tests cover missing/tampered/expired access, database binding, refresh rotation
|
|
and replay, CSRF/Origin rejection, logout revocation, key reuse/permissions,
|
|
account isolation, restart persistence, lock expiry, and runtime compatibility.
|