d360c9a5ba
- Systemauslastungs-Sektion wird immer gerendert (nicht nur bei Erfolg) - Fehlermeldung wenn /api/admin/system/stats nicht erreichbar ist - Feature-Status auf In Review gesetzt Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
186 lines
9.0 KiB
Markdown
186 lines
9.0 KiB
Markdown
# PROJ-1: Nutzer-Authentifizierung & Rollen
|
||
|
||
## Status: In Progress
|
||
**Created:** 2026-03-12
|
||
**Last Updated:** 2026-03-12
|
||
|
||
## Dependencies
|
||
- PROJ-16 (LDAP / Active Directory Anbindung) — optionale Erweiterung des Login-Flows
|
||
|
||
## Rollen-Übersicht
|
||
|
||
| Rolle | Zugriff |
|
||
|-------|---------|
|
||
| `user` | Suche und Lesen eigener archivierter E-Mails |
|
||
| `auditor` | Alle E-Mails lesen und suchen (postfachübergreifend) + Audit-Log einsehen und exportieren – keine Konfiguration |
|
||
| `admin` | Konfiguration, Nutzerverwaltung, Import-Quellen, Systemeinstellungen – kein Zugriff auf E-Mails, kein Audit-Log |
|
||
|
||
## User Stories
|
||
- Als Admin möchte ich mich mit Benutzername/Passwort einloggen, damit nur autorisierte Personen Zugriff haben.
|
||
- Als Admin möchte ich neue Nutzer anlegen und ihnen eine Rolle zuweisen (`user`, `auditor`, `admin`).
|
||
- Als Auditor möchte ich den Audit-Log einsehen und als CSV exportieren, ohne Zugriff auf E-Mails oder Konfiguration zu haben.
|
||
- Als Nutzer möchte ich mich abmelden können, damit meine Session sicher beendet wird.
|
||
- Als Admin möchte ich Passwörter zurücksetzen können, damit gesperrte Nutzer wieder Zugang erhalten.
|
||
- Als System möchte ich Sessions nach Inaktivität automatisch beenden, damit unbefugter Zugriff verhindert wird.
|
||
|
||
## Acceptance Criteria
|
||
- [ ] Login-Seite mit E-Mail/Benutzername und Passwort-Formular
|
||
- [ ] Fehlermeldung bei falschen Zugangsdaten (kein Hinweis ob E-Mail oder Passwort falsch)
|
||
- [ ] Session-Token wird sicher gespeichert (httpOnly Cookie oder JWT)
|
||
- [ ] Sessions laufen nach konfigurierbarer Inaktivität ab (Standard: 8 Stunden)
|
||
- [ ] Drei Rollen: `user`, `auditor`, `admin` – strikt getrennte Zugriffsrechte
|
||
- [ ] `auditor` hat Zugriff auf alle E-Mails (postfachübergreifend, auch fremde Postfächer) + Audit-Log – keine Konfiguration
|
||
- [ ] `admin` hat ausschließlich Zugriff auf Konfiguration und Nutzerverwaltung – kein Zugriff auf E-Mails und kein Zugriff auf Audit-Log
|
||
- [ ] Admin kann Nutzer anlegen, deaktivieren und löschen
|
||
- [ ] Admin kann Passwörter zurücksetzen (temporäres Passwort)
|
||
- [ ] Alle API-Endpunkte prüfen Authentifizierung und Rolle
|
||
- [ ] Logout löscht die Session serverseitig
|
||
|
||
## Edge Cases
|
||
- Login mit deaktiviertem Account → klare Fehlermeldung, kein Zugang
|
||
- Mehrfaches Fehllogin → Rate-Limiting oder Account-Sperre nach X Versuchen
|
||
- Session-Token abgelaufen → automatische Weiterleitung zur Login-Seite
|
||
- Erster Start: Zwei feste Default-User werden beim ersten Start automatisch angelegt:
|
||
- `admin@archivmail` / `archivmailrockz` (Rolle: `admin`)
|
||
- `auditor@archivmail` / `archivmailrockz` (Rolle: `auditor`)
|
||
- Passwörter sollten nach dem ersten Login geändert werden (Hinweis in der UI)
|
||
- Admin löscht sich selbst → verhindern wenn letzter Admin
|
||
|
||
## Technical Requirements
|
||
- Passwörter mit bcrypt gehasht (min. Cost 12)
|
||
- Alle Routen außer `/login` erfordern gültige Session
|
||
- Admin-Routen (`/admin/*`) nur für `admin`-Rolle
|
||
- Audit-Routen (`/audit/*`) und E-Mail-Suche/Ansicht nur für `auditor`- und `user`-Rolle
|
||
- `admin` erhält bei E-Mail-Endpunkten HTTP 403 – keine Ausnahmen
|
||
- Keine Rolle vereint `admin` + `auditor` – strikte Funktionstrennung
|
||
- Audit-Log-Eintrag bei Login, Logout, fehlgeschlagenem Login
|
||
|
||
---
|
||
<!-- Sections below are added by subsequent skills -->
|
||
|
||
## Tech Design (Solution Architect)
|
||
|
||
### Systemübersicht: Two-Tier Architektur
|
||
|
||
```
|
||
Browser (Next.js App) Go REST API Backend
|
||
│ │
|
||
│ POST /api/auth/login │
|
||
│ {email, password} │
|
||
│ ─────────────────────────────────► │
|
||
│ 1. Lokaler Account? → bcrypt verify
|
||
│ 2. Nicht gefunden + LDAP aktiv?
|
||
│ → LDAP-Bind (Service Account)
|
||
│ → User-DN suchen
|
||
│ → User-Bind mit Passwort
|
||
│ → AD-Gruppen → Rolle bestimmen
|
||
│ → UpsertLDAPUser in PostgreSQL
|
||
│ 3. Session-Token erstellen
|
||
│ Session in PostgreSQL speichern
|
||
│ ◄─────────────────────────────────
|
||
│ Set-Cookie: session=TOKEN │
|
||
│ (httpOnly, Secure, SameSite) │
|
||
│ │
|
||
│ GET /api/search?q=... │
|
||
│ Cookie: session=TOKEN │
|
||
│ ─────────────────────────────────► │
|
||
│ Session-Middleware: Token prüfen
|
||
│ Role-Middleware: Route erlaubt?
|
||
│ ◄─────────────────────────────────
|
||
│ JSON-Antwort │
|
||
```
|
||
|
||
> **LDAP ist vollständig optional.** Wenn `ldap.enabled: false` (Standard), verhält sich das System exakt wie ohne LDAP. Lokale Accounts funktionieren immer — auch wenn LDAP aktiviert ist (Fallback bei LDAP-Fehler).
|
||
|
||
### Komponentenstruktur
|
||
|
||
**Next.js Frontend:**
|
||
```
|
||
src/app/
|
||
├── /login ← Login-Seite (öffentlich)
|
||
├── /search ← Suche + E-Mail-Ansicht (user + auditor)
|
||
├── /audit ← Audit-Log (nur auditor)
|
||
└── /admin ← Admin-Bereich (nur admin)
|
||
|
||
src/components/
|
||
├── LoginForm ← E-Mail + Passwort, Fehlermeldungen
|
||
├── RoleGuard ← Schützt Routen clientseitig, redirect auf /login
|
||
└── PasswordChangePrompt ← Hinweis bei Default-Passwort
|
||
```
|
||
|
||
**Go Backend:**
|
||
```
|
||
HTTP-Server
|
||
├── POST /api/auth/login ← Session ausstellen
|
||
├── POST /api/auth/logout ← Session löschen
|
||
├── Session Middleware ← prüft Token bei allen /api/* Routen
|
||
├── Role Middleware
|
||
│ ├── /api/admin/* → nur `admin`
|
||
│ ├── /api/audit/* → nur `auditor`
|
||
│ └── /api/* → `user` + `auditor` (admin → 403)
|
||
├── Password Manager ← bcrypt Hash + Verify
|
||
├── User Store ← PostgreSQL users-Tabelle
|
||
└── Bootstrap ← Default-User beim ersten Start
|
||
```
|
||
|
||
### Datenmodell
|
||
|
||
**Tabelle `users`:**
|
||
|
||
| Feld | Beschreibung |
|
||
|------|-------------|
|
||
| `id` | Interne ID |
|
||
| `email` | Login-E-Mail (eindeutig) |
|
||
| `password_hash` | bcrypt-Hash (Cost 12) — NULL bei LDAP-Usern |
|
||
| `role` | `user` / `auditor` / `admin` |
|
||
| `source` | `local` oder `ldap` — Herkunft des Accounts |
|
||
| `active` | Deaktivierte Nutzer können sich nicht einloggen |
|
||
| `created_at` | Erstellungszeitpunkt |
|
||
| `last_login_at` | Letzter erfolgreicher Login |
|
||
|
||
**Tabelle `sessions`:**
|
||
|
||
| Feld | Beschreibung |
|
||
|------|-------------|
|
||
| `token` | Zufälliger 32-Byte-Token |
|
||
| `user_id` | Referenz auf `users` |
|
||
| `expires_at` | Ablaufzeitpunkt (rollierend, +8h bei Aktivität) |
|
||
| `last_active_at` | Wird bei jeder Anfrage aktualisiert |
|
||
|
||
### Technische Entscheidungen
|
||
|
||
| Entscheidung | Begründung |
|
||
|---|---|
|
||
| **Next.js Frontend + Go REST API** | Klare Trennung: Next.js rendert die UI, Go verwaltet Daten und Sicherheit. Kein Java. |
|
||
| **Session-Cookie (httpOnly)** | Next.js sendet Cookie automatisch mit – kein manuelles Token-Handling im Frontend-Code nötig |
|
||
| **Server-side Sessions (nicht JWT)** | Logout und Admin-Deaktivierung wirken sofort – JWT wäre bis Ablauf weiterhin gültig |
|
||
| **Role-Check im Go-Backend** | Sicherheits-kritische Prüfung liegt im Backend, nicht im Next.js-Client (der wäre manipulierbar) |
|
||
| **RoleGuard in Next.js zusätzlich** | Verhindert kurzes Aufblitzen falscher Seiten – rein UX, kein Sicherheits-Feature |
|
||
| **bcrypt Cost 12** | Ausreichend langsam gegen Brute-Force |
|
||
| **LDAP als optionaler Fallback** | Login versucht erst lokalen Account, dann LDAP – Reihenfolge garantiert, dass lokale Admins immer funktionieren |
|
||
| **LDAP-User in PostgreSQL gespiegelt** | Nach erstem Login landet LDAP-User in `users`-Tabelle (`source: ldap`) – einheitliche Session-Verwaltung, kein Sonder-Code |
|
||
| **AD-Gruppen → Rollen-Mapping** | Rolle wird bei jedem Login aus AD-Gruppenmitgliedschaft neu bestimmt – Rollen-Änderung in AD wirkt beim nächsten Login |
|
||
|
||
### Abhängigkeiten
|
||
|
||
**Go Backend:**
|
||
|
||
| Paket | Zweck |
|
||
|---|---|
|
||
| `golang.org/x/crypto/bcrypt` | Passwort-Hashing |
|
||
| `crypto/rand` | Sichere Token-Generierung (Stdlib) |
|
||
| `github.com/go-ldap/ldap/v3` | LDAP/AD-Authentifizierung (PROJ-16) |
|
||
|
||
**Next.js Frontend:**
|
||
|
||
| Paket | Zweck |
|
||
|---|---|
|
||
| `react-hook-form` + `zod` | Login-Formular-Validierung (bereits im Template) |
|
||
| `shadcn/ui` | UI-Komponenten (bereits installiert) |
|
||
|
||
## QA Test Results
|
||
_To be added by /qa_
|
||
|
||
## Deployment
|
||
_To be added by /deploy_
|