Skip to content

Security

Matthias Schabhüttl edited this page Jun 12, 2026 · 1 revision

Security

Diese Seite beschreibt das Sicherheitsmodell der OpenSchichtplaner5-API.


Benutzerrollen

Das System kennt drei Rollen, die hierarchisch aufgebaut sind:

Rolle Level Berechtigungen
Leser 1 Lesezugriff auf Dienstplan, Mitarbeiter, Schichten, Abwesenheiten, Statistiken
Planer 2 Alles wie Leser + Schreiben: Dienstplan, Abwesenheiten, Notizen, Schichtwünsche, Besetzungsanforderungen
Admin 3 Alles wie Planer + Benutzerverwaltung, Stammdaten (Schichten, Gruppen, Mitarbeiter), Backup/Restore, Jahresabschluss

Endpunkte prüfen die Mindestrolle über einen Dependency-Mechanismus in FastAPI:

  • require_auth → Leser oder höher
  • require_planer → Planer oder höher
  • require_admin → nur Admin

Anfragen mit zu niedriger Rolle erhalten HTTP 403 Forbidden.


Auth-Flow

POST /api/auth/login
  Body: { "username": "...", "password": "..." }

→ 200 OK
  { "token": "<hex-token>", "user": {...}, "expires_at": <unix-timestamp> }

→ Alle folgenden Anfragen mit Header:
  X-Auth-Token: <hex-token>

Schritt-für-Schritt

  1. LoginPOST /api/auth/login mit Benutzername und Passwort
  2. Token erhalten — Der Server legt eine Session an und gibt ein zufälliges Hex-Token zurück
  3. Token verwenden — Alle geschützten Endpunkte erwarten den Header X-Auth-Token
  4. LogoutPOST /api/auth/logout invalidiert das Token serverseitig

Tokens werden in einem In-Memory-Dictionary (_sessions) gespeichert. Ein Neustart des Servers invalidiert alle Sessions.


Token Expiry

  • Standard-Laufzeit: 8 Stunden (konfigurierbar via Umgebungsvariable TOKEN_EXPIRE_HOURS)
  • Abgelaufene Tokens werden bei jeder Anfrage geprüft und gelöscht
  • Nach Ablauf: HTTP 401, erneuter Login erforderlich
# Token-Laufzeit anpassen (z.B. 4 Stunden):
TOKEN_EXPIRE_HOURS=4 uvicorn sp5api.main:app ...

Brute-Force-Schutz

Der Login-Endpunkt ist durch zwei Mechanismen geschützt:

Rate Limiting (slowapi)

  • 5 Anfragen pro Minute pro IP-Adresse auf POST /api/auth/login
  • Bei Überschreitung: HTTP 429 Too Many Requests

Account-Lockout

  • Nach 5 fehlgeschlagenen Loginversuchen wird das Konto gesperrt (_LOCKOUT_MAX = 5)
  • Gesperrte Konten können nur durch einen Admin entsperrt werden (POST /api/auth/unlock/{user_id})
  • Fehlversuche werden pro Benutzer im Speicher gezählt

CORS-Konfiguration

Cross-Origin Resource Sharing (CORS) ist über Umgebungsvariablen konfigurierbar:

# Erlaubte Origins (kommagetrennt):
ALLOWED_ORIGINS="https://mein-schichtplaner.example.com,https://admin.example.com"

Standardwerte (Entwicklungsmodus):

  • http://localhost:5173 (Vite Dev Server)
  • http://localhost:8000 (lokale API)

CORS-Einstellungen in der API:

  • allow_credentials: true
  • allow_methods: ["*"]
  • allow_headers: ["*"]

⚠️ Produktion: ALLOWED_ORIGINS immer explizit auf die eigene Domain beschränken!


Passwort-Hashing

Passwörter werden mit bcrypt gehasht (via passlib). Klartext-Passwörter werden nie gespeichert.


Fehlerbehandlung & Information Leakage

  • Interne Fehlermeldungen werden im Production-Modus nicht an den Client weitergegeben
  • Alle 500-Fehler werden durch _sanitize_500() bereinigt
  • Logs auf dem Server enthalten den vollen Stack-Trace für Debugging

Zwei-Faktor-Authentifizierung (2FA)

Seit v1.0.0-rc3 unterstützt die Anwendung TOTP-basierte 2FA (Time-based One-Time Password):

  • Authenticator-Apps: Google Authenticator, Authy, etc.
  • QR-Code-basiertes Setup
  • 10 einmalige Backup-Codes
  • Admins können 2FA für andere Benutzer zurücksetzen

→ Details: Zwei-Faktor-Authentifizierung


Rate Limiting (ab v1.0.0-rc3)

API-Endpunkte sind gegen Brute-Force und Missbrauch gesichert:

Endpunkt Limit
POST /api/auth/login 5 Anfragen/Minute
Alle anderen API-Endpunkte 100 Anfragen/Minute

Bei Überschreitung: HTTP 429 Too Many Requests mit Retry-After-Header.


Session Expiry (ab v1.0.0-rc3)

  • JWT-basierte Token mit konfigurierbarer Laufzeit
  • Frontend erkennt ablaufende Tokens und zeigt Notification-Toast
  • Automatischer Logout vor Token-Ablauf

Empfehlungen für den Produktiveinsatz

  1. HTTPS erzwingen (z.B. via nginx Reverse Proxy mit Let's Encrypt)
  2. ALLOWED_ORIGINS auf eigene Domain einschränken
  3. TOKEN_EXPIRE_HOURS je nach Sicherheitsanforderung reduzieren (z.B. 4)
  4. API nicht direkt exponieren — immer hinter einem Reverse Proxy betreiben
  5. Regelmäßige Backups über /api/backup einrichten

Dev-Mode & SP5_DEV_MODE

⚠️ Nur für Entwicklung! Dev-Mode darf niemals in Produktionsumgebungen aktiviert werden.

Der Entwicklungsmodus ermöglicht vereinfachtes Testen ohne vollständige Auth-Flows:

# Entwicklungsmodus aktivieren:
SP5_DEV_MODE=true uvicorn sp5api.main:app --reload

Im Dev-Mode:

  • Ein fester Dev-Token wird akzeptiert (konfigurierbar via SP5_DEV_TOKEN)
  • Brute-Force-Schutz ist deaktiviert
  • Ausführlichere Fehlermeldungen werden zurückgegeben

In Production (SP5_DEV_MODE nicht gesetzt oder false):

  • Der Dev-Token wird strikt abgelehnt (HTTP 401)
  • Alle Sicherheitsmechanismen sind aktiv

CSV-Import Sicherheit (ab v0.3.21)

CSV-Import-Endpunkte sind ab v0.3.21 durch zusätzliche Validierung geschützt:

Schutz Details
Dateigröße Maximale Upload-Größe: 10 MB pro Datei
MIME-Type Nur text/csv und application/csv akzeptiert
Dateiname-Sanitierung Dateinamen werden beim Photo-Upload bereinigt (keine Path-Traversal-Angriffe)

Uploads mit ungültigem MIME-Type oder zu großer Datei werden mit HTTP 400 Bad Request abgewiesen.


Content-Security-Policy (ab v1.0.0)

Ab v1.0.0 werden Content-Security-Policy (CSP) Header und Subresource Integrity (SRI) eingesetzt:

Content-Security-Policy: default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; connect-src 'self'

Subresource Integrity (SRI):

  • Alle statischen Assets (JS, CSS) erhalten Integrity-Hashes
  • Browser verweigern das Laden manipulierter Dateien
  • Schutz gegen CDN-Kompromittierung und Man-in-the-Middle

HTTP Security Headers

Die API sendet folgende Security-Header:

Header Wert (Standard) Zweck
X-Content-Type-Options nosniff Verhindert MIME-Sniffing
X-Frame-Options DENY Verhindert Clickjacking
X-XSS-Protection 1; mode=block XSS-Filter (ältere Browser)
Referrer-Policy strict-origin-when-cross-origin Kontrolliert Referrer-Info
Permissions-Policy camera=(), microphone=(), geolocation=() Deaktiviert Browser-APIs

🧸 OpenSchichtplaner5 v1.2.0

Home — Startseite


🚀 Einstieg


📊 Dashboard

  • Dashboard — Charts, Widgets & Performance

📅 Planung


📄 Berichte & Daten


🗃️ Stammdaten


🔗 Integrationen


⚙️ Administration


📱 Features


🔗 Links


📚 Verwandte Wikis

Clone this wiki locally