# 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 - [ ] `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 --- ## 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_