Add two-factor login (TOTP) with recovery codes

Users can set up an authenticator app from their account page; login
then asks for a code after the password, with one-time recovery codes
as a fallback. Sensitive actions (tokens, user changes, 2FA resets)
need a code from the last 5 minutes. totp.require (none/admins/all)
forces setup, and admins can reset a user's 2FA from the UI, the jarl
CLI or jarld on the server. The dashboard and jarl status flag users
missing 2FA and a shared "admin" account still in use.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
abrown38andClaude Opus 5.5 committed 2026-10-09 14:12:24 +00:00
1 parent b22ffee1bb
commit 8f9cdd0a17
35 files changed
+1965 -43

No files matched your search

+26
View File
@@ -8,6 +8,29 @@ All notable changes to Jarl are documented here. The format follows
### Added
- Two-factor login to the web UI with an authenticator app (TOTP: SHA-1,
6 digits, 30 s, as every app supports). Users turn it on under Account
(password, QR code, a code to confirm) and get 10 one-time recovery
codes. Logging in then asks for a code (or a recovery code) after the
password; each code works once. In a session with two-factor login,
creating or rotating API tokens, changing users and resetting someone's
two-factor login need a code from the last 5 minutes: the web UI asks
for one, API clients send `X-Jarl-TOTP`. API tokens and the local socket
are not affected.
- `totp.require` in jarl.yaml (`none`, `admins`, `all`) makes two-factor
login compulsory; such a user who hasn't set it up can only set it up
after logging in. `totp.issuer` names the server in authenticator apps
(default `Jarl <hostname>`).
- Resetting a user's two-factor login (lost phone): Users → Reset 2FA,
`jarl user totp reset NAME`, or on the server
`jarld user totp reset NAME` (also with jarld stopped).
- The dashboard and `jarl status` list users who must use two-factor login
but haven't set it up, and suggest disabling the first `admin` account
when it is still active next to personal administrator accounts.
`jarl user list`/`show` and the Users page show who uses it.
- API: `POST /auth/login/totp`, `/me/totp` (`setup`, `enable`, `disable`,
`recovery-codes`), `DELETE /users/{id}/totp`; database migration 3.
- `scripts/testenv.sh`: turns a fresh Debian/Ubuntu machine into a test bed.
It installs BIND and the build tools (Go from go.dev), writes a hand-made
style configuration with internal and external views, a split-horizon
@@ -17,6 +40,9 @@ All notable changes to Jarl are documented here. The format follows
### Fixed
- `jarld init -u` and the install guide recommend naming the first
administrator after yourself (one account per person).
- `jarld import` no longer warns that a zone with `allow-update { none; }`
uses dynamic updates (validation already allowed it).
- docs/cli.md gives the CLI configuration file's location on macOS