bb963a796f
- seedDefaultUsers: generiert kryptographisch zufällige Passwörter (crypto/rand) statt hartkodiertes "archivmailrockz" — Passwörter werden einmalig im Terminal angezeigt und können danach nicht wiederhergestellt werden - generateJTI: verwendet crypto/rand (16 Byte, hex) statt time.UnixNano XOR deadbeef Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8.9 KiB
8.9 KiB
PROJ-1: Nutzer-Authentifizierung & Rollen
Status: Deployed
Created: 2026-03-12 Last Updated: 2026-03-17
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 auditorhat Zugriff auf alle E-Mails (postfachübergreifend, auch fremde Postfächer) + Audit-Log – keine Konfigurationadminhat 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
/loginerfordern gültige Session - Admin-Routen (
/admin/*) nur füradmin-Rolle - Audit-Routen (
/audit/*) und E-Mail-Suche/Ansicht nur fürauditor- unduser-Rolle adminerhält bei E-Mail-Endpunkten HTTP 403 – keine Ausnahmen- Keine Rolle vereint
admin+auditor– strikte Funktionstrennung - Audit-Log-Eintrag bei Login, Logout, fehlgeschlagenem Login
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