# Sicherheit

Dokumentation aller Sicherheitsmechanismen der eforms.cloud-Plattform.

## Authentifizierung (Sanctum)

Die API verwendet Laravel Sanctum mit Bearer-Token-Authentifizierung.

### Login-Flow

1. `POST /api/auth/login` mit `email` + `password`
2. Sanctum erstellt einen Personal Access Token (`api-token`)
3. Vorheriger Token desselben Namens wird geloescht (Single-Session)
4. Token wird als `Bearer`-Header bei allen folgenden Requests mitgeschickt
5. Bei aktivierter 2FA: Zwischenschritt mit `two_factor_token` (siehe unten)

### Token-Abilities

Tokens koennen Abilities haben. Standard-Login-Tokens erhalten `*` (alle Rechte). BI-API-Tokens erhalten `bi:read`.

## Zwei-Faktor-Authentifizierung (2FA)

TOTP-basierte 2FA mit Google Authenticator / Authy-Kompatibilitaet.

### Einrichtungs-Flow

```mermaid
sequenceDiagram
    participant U as User
    participant API as API

    U->>API: POST /auth/two-factor/enable {password}
    API-->>U: {secret, qr_code_svg, recovery_codes[8]}
    Note over U: QR-Code scannen
    U->>API: POST /auth/two-factor/confirm {code}
    API-->>U: 2FA aktiviert
```

### Login mit 2FA

```mermaid
sequenceDiagram
    participant U as User
    participant API as API

    U->>API: POST /auth/login {email, password}
    API-->>U: {two_factor: true, two_factor_token: "abc..."}
    U->>API: POST /auth/two-factor-challenge {two_factor_token, code}
    API-->>U: {token, user}
```

Der `two_factor_token` ist 5 Minuten gueltig (Cache-basiert mit SHA-256 Hash).

### Recovery Codes

- 8 Codes im Format `XXXX-XXXX` (alphanumerisch, Grossbuchstaben)
- Codes werden als SHA-256 Hashes gespeichert
- Jeder Code ist einmalig verwendbar (wird nach Nutzung entfernt)
- Regenerierung ueber `POST /auth/two-factor/recovery-codes` (erfordert Passwort)

### Deaktivierung

`DELETE /auth/two-factor` mit `password`. Entfernt Secret, Recovery Codes und Confirmation-Timestamp.

## CAPTCHA-System

Mathematik-basiertes CAPTCHA mit SVG-Rendering. Kein externer Dienst noetig.

### Schwierigkeitsgrade

| Stufe | Operationen | Zahlenbereich | Beispiel |
|-------|-------------|---------------|----------|
| `easy` | Addition | 1-10 | 3 + 7 = ? |
| `medium` | Addition, Subtraktion | 10-50, 1-20 | 34 - 12 = ? |
| `hard` | Addition, Subtraktion, Multiplikation | 2-99 | 7 * 8 = ? |

### SVG-Rendering

Das CAPTCHA wird als SVG-Bild gerendert mit:
- Zufaellige Schriftgroesse pro Zeichen (22-28px)
- Zufaellige Rotation pro Zeichen (-12 bis +12 Grad)
- 5 Stoerlinien
- 30 Stoerpunkte
- 2 gekruemmte Stoerlinien
- Graustufen-Variationen

### Token-Lifecycle

1. `GET /api/captcha` → `{token, image_svg, accessible_text}`
2. Token wird als SHA-256 Hash im Cache gespeichert (TTL: 5 Minuten)
3. Bei Submission: `captcha_token` + `captcha_answer` mitschicken
4. Verifizierung: Token wird sofort invalidiert (One-Time Use)
5. Fallback: Wenn Default-Cache-Driver fehlschlaegt, wird File-Driver versucht

### Honeypot

Zusaetzlich zum CAPTCHA: Ein verstecktes Feld `website_url`. Wenn es ausgefuellt ist, wird die Submission abgelehnt (Bots fuellen versteckte Felder aus).

### Konfiguration

Ueber Admin-UI oder API:

| Setting | Beschreibung | Default |
|---------|--------------|---------|
| `captcha.enabled` | Global ein/aus | `true` |
| `captcha.difficulty` | easy/medium/hard | `easy` |
| `captcha.forms_enabled` | Fuer Formular-Submissions | `true` |
| `captcha.login_enabled` | Fuer Login-Seite | `false` |
| `captcha.honeypot_enabled` | Honeypot-Schutz | `true` |
| `captcha.rate_limit_per_hour` | Max. CAPTCHA-Generierungen/h | `10` |

## Rollenbasierte Zugriffskontrolle (RBAC)

### 4 Rollen

| Rolle | Beschreibung |
|-------|--------------|
| `user` | Kann Meldungen einsehen und Dashboard nutzen |
| `editor` | Zusaetzlich: Meldungen verwalten |
| `admin` | Zusaetzlich: User-Verwaltung, Settings, Tokens, Reports, SSO, Notifications |
| `developer` | Zusaetzlich: Block-Editor, Template-Editor, Import/Export |

### Middleware

- **`admin`** - Erlaubt `admin` und `developer` Rollen
- **`developer`** - Erlaubt nur `developer` Rolle
- **`plan.feature:{feature}`** - Prueft ob Feature im aktuellen Plan verfuegbar ist
- **`ability:{ability}`** - Prueft Token-Ability (z.B. `bi:read`)
- **`demo`** - Im Demo-Modus: blockiert bestimmte Schreib-Operationen

## PII-Anonymisierung

Der `AnonymisierungsService` wird bei jeder Formular-Submission automatisch ausgefuehrt.

### Was anonymisiert wird

1. **Felder mit `anonymize: true`** in der Block-Definition
2. **Alle `otherDbField`-Felder** (Sonstiges-Freitextfelder enthalten immer freie Eingabe)

### Erkannte Muster

| Muster | Ersetzung |
|--------|-----------|
| `Herr/Frau/Dr./Prof. + Name` | `[NAME ANONYMISIERT]` |
| `email@example.com` | `[E-MAIL ANONYMISIERT]` |
| `+49 123 456789`, `0123/456789` | `[TELEFON ANONYMISIERT]` |
| `Zimmer 123`, `Station 4B`, `Raum A-2` | `[RAUM ANONYMISIERT]` |
| `12.03.2025` (DD.MM.YYYY) | `[DATUM ANONYMISIERT]` |

### Verbotene Keys

Folgende Keys werden vor dem Speichern entfernt: `ip`, `user_agent`, `session_id`, `debug_info`.

## Audit-Logging

Der `AuditService` protokolliert sicherheitsrelevante Aktionen in der `audit_logs`-Tabelle.

### Protokollierte Events

- `login_success`, `login_failed`
- `logout`
- `sso_login_success`, `sso_login_failed`
- Model-CRUD-Aktionen (Create, Update, Delete)
- Settings-Aenderungen

### Gespeicherte Daten

| Feld | Beschreibung |
|------|--------------|
| `user_id` | Ausfuehrender User (nullable) |
| `action` | Event-Name |
| `auditable_type/id` | Betroffenes Model (polymorph) |
| `changes` | Geaenderte Felder (sensible Felder gefiltert) |
| `ip_address` | IP-Adresse |
| `user_agent` | Browser User-Agent |
| `metadata` | Zusaetzliche Informationen |

### Sensitive-Field-Filtering

Felder die `password`, `token`, `secret` oder `api_key` im Namen enthalten, werden automatisch als `[FILTERED]` maskiert.

## Rate Limiting

Laravel-eigenes Rate-Limiting via Throttle-Middleware:

| Kontext | Throttle-Group | Beschreibung |
|---------|----------------|--------------|
| Formular-Submission | `throttle:submissions` | Schutz vor Spam-Submissions |
| Login | `throttle:login` | Schutz vor Brute-Force |
| CAPTCHA-Generierung | `throttle:captcha` | Schutz vor CAPTCHA-Farming |

## CORS-Konfiguration

CORS wird ueber Laravel's `cors`-Middleware konfiguriert. `SANCTUM_STATEFUL_DOMAINS` definiert die erlaubten Frontend-Domains fuer Cookie-basierte Auth.

## Demo-Modus-Schutz

Die `DemoModeMiddleware` blockiert im Demo-Modus destruktive Operationen:

- User-Erstellung/-Aenderung/-Loeschung
- App-Name, Layout, CAPTCHA-Settings aendern
- API-Tokens erstellen/loeschen
- Meldungen loeschen
- Profil-Aenderungen
- 2FA Ein-/Ausschalten

Erlaubt bleibt: Meldungen einsehen, Dashboard nutzen, Formular-Submissions einreichen.

## Input-Validierung

### Backend

- Alle Endpoints verwenden Laravel `$request->validate()` mit expliziten Regeln
- Formular-Validierung wird dynamisch aus Block-Definitionen generiert
- HTML in Layout-Settings wird via `strip_tags()` auf erlaubte Tags beschraenkt: `<b>`, `<strong>`, `<i>`, `<em>`, `<u>`, `<a>`, `<br>`, `<p>`, `<span>`
- Farb-Werte werden gegen Regex `^#[0-9a-fA-F]{6}$` validiert
- Datei-Uploads: Typ-Validierung (`image|mimes:jpg,jpeg,png,svg,webp`), Max 2MB

### Frontend

- TypeScript-Typisierung aller API-Responses
- Client-seitige Validierung vor Submit (Required-Checks, Typ-Pruefungen)

## Hosting & Rechenzentren

Die SaaS-Variante von eforms.cloud wird auf **Hetzner Cloud** in Deutschland betrieben.

| Standort | Land | Verwendung |
|----------|------|------------|
| Falkenstein (FSN1) | Deutschland | Standard-Region fuer alle Tenants |
| Frankfurt (FSN-FRA-Failover) | Deutschland | Optional als zweite DE-Region (Enterprise) |

- **Standard:** Alle Tenants laufen in Falkenstein.
- **Reine DE-Standortbindung:** Im Enterprise-Plan auf Wunsch garantiert — Daten verlassen Deutschland nicht (Backups, Failover, KI-Pipeline inklusive).
- **Kein Drittland-Transfer:** Es werden weder US-Cloud-Anbieter noch Hetzner-Standorte ausserhalb Deutschlands (z. B. Helsinki) verwendet.
