feat(auth): Rollen, Benutzerverwaltung und Passkeys (#027, #028)

Drei Rollen: Administrator, Techniker, Kunde. Jede der 28 Aktionen nennt das
Recht, das sie verlangt; die Rechte stehen an einer Stelle. Kundenkonten
haengen an genau einem Kunden und sehen nur dessen Hosts und Rechnungen -
ohne Einkaufspreise und Marge. Die Einschraenkung sitzt in den Abfragen
selbst, damit keine Seite vergessen kann, sie weiterzugeben; sechs Tests
pruefen das.

Dabei gefunden: Neu ueber OIDC angelegte Konten haetten die Vorgabe des
Datenmodells geerbt - ADMIN. Jetzt gibt es dafuer eine Einstellung mit der
Vorgabe Techniker.

Passkeys (#028) als gleichwertiger, passwortloser Anmeldeweg neben Passwort
und OIDC. Mehrere je Konto, Aufgabe in einem kurzlebigen Cookie, rpID aus der
oeffentlichen Adresse. Ohne HTTPS sagt die Seite es, statt still zu scheitern.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-19 00:46:29 +02:00
co-authored by Claude Opus 5
parent 7d8e5c9172
commit 2f45e33e20
66 changed files with 2201 additions and 114 deletions
+14 -4
View File
@@ -15,8 +15,13 @@ Die Gliederung folgt den OWASP Top 10 (2021).
- Die Anmeldung prüft den `Origin`, damit keine fremde Seite jemanden unbemerkt in ein untergeschobenes
Konto anmeldet (Login-CSRF). Für Server Actions erledigt das Next.js selbst.
**Nicht vorhanden:** Rollen. Wer angemeldet ist, darf alles. Für ein Werkzeug, das ein Systemhaus intern
betreibt, ist das vertretbar – für mehrere Mandanten wäre es das nicht.
**Rollen** (#027): Administrator, Techniker und Kunde. Jede Aktion nennt das Recht, das sie verlangt;
die Rechte stehen an einer Stelle (`src/server/auth/rollen.ts`). Kundenkonten sind an einen Kunden
gebunden, und die Einschränkung sitzt in den Abfragen – nicht in der Anzeige. Einkaufspreise und Marge
werden für sie schon beim Abfragen entfernt, stehen also nicht im ausgelieferten HTML.
**Weiterhin nicht vorhanden:** Mandantenfähigkeit im eigentlichen Sinn. Mehrere Systemhäuser in einer
Installation wären ein Umbau, kein Anbau.
## A02 – Kryptografische Fehler
@@ -70,8 +75,13 @@ gespeicherten Zugangsdaten unlesbar. Er gehört in die Sicherung.
- Anmeldung wahlweise per Passwort oder OIDC (authentik, mit PKCE und `state`).
- Jede Anmeldung – erfolgreich oder nicht – landet im Audit-Log.
**Nicht vorhanden:** Zwei-Faktor-Anmeldung. Wer sie braucht, stellt OIDC davor und schaltet die
Passwortanmeldung ab.
- **Passkeys** (WebAuthn, #028) als dritter, gleichwertiger Weg. Passwortlos, an die Domäne gebunden,
mehrere je Konto. Setzt HTTPS voraus (außer auf `localhost`).
- Automatisch angelegte OIDC-Konten bekommen die eingestellte Rolle – Vorgabe *Techniker*, nicht
Administrator.
**Nicht vorhanden:** klassische Zwei-Faktor-Anmeldung mit Einmalkennwort. Ein Passkey ersetzt beides
in einem Schritt; wer einen zweiten Faktor zum Passwort erzwingen will, stellt OIDC davor.
## A08 – Datenintegrität