Inhaltsverzeichnis
2. Auth-Architektur: WvdS.Shell (Benutzeroberfläche)
Stand: 2026-03-05
Übergeordnet: Auth-Architektur — Gesamtübersicht Verwandt: 3. Gateway.Service | 4. Datenschicht | 5. Migration
Ausgangssituation
Die bisherigen WvdS-Clients — AMED und LD — liefen als native Windows-Anwendungen mit impliziter Windows-Authentifizierung. Das funktionierte gut, solange der Rechner in der Domäne eingebunden war und der Benutzer sich ohnehin am Domain-Account anmeldete. Es funktionierte nicht, sobald jemand außerhalb des Firmennetzes arbeitete, ein privates Gerät nutzte oder das System auf einem Rechner gestartet wurde, der keine interaktive Domänenanmeldung kannte.
WvdS.Shell löst dieses Problem durch eine klare Schichttrennung. Die erste Schicht — das PFX-Zertifikat — prüft, ob die Installation selbst berechtigt ist: ob sie lizenziert ist, ob sie für diese Domäne und diesen Benutzer gilt, ob das Zertifikat noch gültig ist. Diese Prüfung geschieht vollständig lokal, ohne Netzwerkzugriff. Erst wenn sie bestanden ist, beginnt die zweite Schicht: die Benutzerauthentifizierung über den Gateway.Service.
Das hat einen konkreten Effekt: Extensions laden nicht, und keine Business-Daten sind sichtbar, bevor der Benutzer vollständig authentifiziert ist. Es gibt keine Race Condition zwischen „Fenster ist offen“ und „Auth ist fertig“. Gleichzeitig ist der Offline-Betrieb — wenn das Gateway nicht erreichbar ist — kein Sonderfall, der nachträglich angeflickt wird, sondern ein eingeplantes Szenario mit eigenem Auth-Pfad und definiertem Umfang.
Konzept
WvdS.Shell verwendet eine zweischichtige Auth-Architektur:
- Schicht 1 — PFX-Zertifikat (Installations-/Lizenznachweis): Wird von WvdS ausgestellt und trägt Lizenz- und Deployment-Metadaten als Custom-Extensions. Wird lokal validiert — auch offline.
- Schicht 2 — Identity Provider (Benutzer-Authentifizierung): Kerberos (SSO, on-net) oder externer MFA-Flow (off-net). Liefert einen JWT Session Token.
Beide Schichten müssen erfolgreich sein, bevor eine Extension lädt oder Business-Daten sichtbar sind.
Schicht 1 — PFX-Zertifikat
Zweck
Das PFX (PKCS#12) dient gleichzeitig als:
- Lizenznachweis — Was ist lizenziert? Welche Features? Bis wann?
- Deployment-Nachweis — Für welche Domänen/User ist die Installation freigegeben?
- Offline-Credential — Wenn Gateway nicht erreichbar, gilt ein valides PFX als Zugangsnachweis für den Offline-Modus.
Ausstellung
WvdS betreibt eine interne CA. Jede Kundeninstallation erhält ein signiertes PFX:
- Signiert mit WvdS-CA (Root-Cert wird im Shell-Binary oder bekanntem Store-Pfad mitgeliefert)
- Laufzeit typisch 1 Jahr (Renewal-Flow ist Aufgabe des Gateway-Service)
- Kein Wildcard — pro Deployment ein eigenes Zertifikat
Custom Extensions (OID-Struktur)
Die Custom-Attributes werden als X.509v3-Extensions mit privatem OID-Arc geschrieben.
Vorgeschlagener Arc: 1.3.6.1.4.1.XXXXX.1.* (IANA Private Enterprise Number von WvdS).
| OID-Suffix | Attribut-Name | Beispielwert | Beschreibung |
|---|---|---|---|
.1 | wvds.license.tier | professional | Lizenz-Stufe |
.2 | wvds.license.expires | 2027-01-01 | Ablaufdatum (ISO 8601) |
.3 | wvds.auth.domains | ENI,VERSALIS | Erlaubte AD-Domänen (Komma-getrennt) |
.4 | wvds.auth.users | * | Erlaubte Usernamen oder * für alle |
.5 | wvds.install.id | ENIVERS-2026-001 | Eindeutige Installations-ID |
.6 | wvds.tenant.name | ENI VERSALIS GmbH | Anzeigename der Installation |
Nicht im PFX:wvds.license.features— Feature-Flags werden nach Auth aus der DB geladen (siehe Feature-Flags / ENIVERSASYS).
Deployment-Varianten
| Variante | Speicherort | Schutzmechanismus | Warum genau so? |
|---|---|---|---|
| Corpnet | Windows Cert Store (LocalMachine\My) | Windows ACL, GPO-Deployment | Kein Benutzereingriff nötig — die IT verteilt das Zertifikat per GPO. Der Private Key ist durch Windows ACL vor anderen Nutzern geschützt. |
| BYOD / Extern | Datei %APPDATA%\WvdS\license.pfx | Passwort in DPAPI SecretStorage | Kein Cert Store auf Privatgeräten. DPAPI bindet das PFX-Passwort ans Windows-Benutzerkonto — ein anderer Benutzer desselben PCs kann die Datei nicht entschlüsseln. |
Cert-Store-Variante: Kein Passwort nötig — Windows schützt den Private Key. Shell sucht Zertifikat anhand Issuer-DN automatisch.
Validierung
Shell-Start
│
▼
┌─ PFX Validator ──────────────────────────────────────────────┐
│ 1. PFX im Cert Store oder Datei vorhanden? │
│ 2. Signaturkette gültig? (gegen gebündelten WvdS-Root) │
│ 3. Zertifikat nicht abgelaufen? │
│ 4. wvds.auth.domains enthält aktuelle Domäne oder '*'? │
│ 5. wvds.auth.users enthält aktuellen User oder '*'? │
│ 6. Custom-Attributes laden → License-Objekt befüllen │
└──────────────────────────────────────────────────────────────┘
│ OK │ FAIL
▼ ▼
Context-Detector Shell zeigt nativen Fehler-Dialog:
(Schicht 2) "Kein gültiges Lizenzzertifikat"
→ Shell-Start abgebrochen
Schicht 2 — Identity Provider
Context-Aware Auth (Netzwerk-Erkennung)
│
▼
┌─ Context-Detector ────────────────────────────────────┐
│ 1. Domain-joined? → SSPI/Kerberos verfügbar? │
│ 2. DC erreichbar? → LDAP-Ping │
│ 3. Gateway erreichbar? → HTTP Health-Check │
└───────────────────────────────────────────────────────┘
│
┌─────┴──────────┬────────────────┐
▼ ▼ ▼
Corpnet Extern Offline
(Kerberos) (MFA-Flow) (PFX-Only)
Szenario A — Corpnet (LAN/WLAN)
- Domain-joined + DC erreichbar + Gateway erreichbar
- SSPI/Kerberos → Service Ticket für Gateway.Service
- Kein Dialog, kein Klick — SSO out of the box
- PFX-Domänen-Attribut wird gegen aktuelle AD-Domäne geprüft
Szenario B — Home-Office mit VPN
- VPN-Tunnel stellt DC-Erreichbarkeit wieder her → identisch wie Szenario A
- Shell führt bei Gateway-Unerreichbarkeit automatische Retries durch (konfigurierbarer Timeout), bevor auf Szenario C/D eskaliert wird
Szenario C — Extern / BYOD (MFA-Flow)
- DC nicht erreichbar, kein VPN, Gateway aber erreichbar
- Nativer Auth-Dialog (pre-WebView, FPC/Lazarus nativ)
- Ablauf:
- Username + Passwort → Gateway
- Gateway sendet TOTP-Challenge
- User öffnet MS Authenticator (OATH TOTP) → 6-stelliger Code
- Gateway validiert → Access Token (JWT, kurzlebig) + Refresh Token (langlebig)
- Refresh Token →
SecretStorage(DPAPI)
Szenario D — Offline (kein Gateway erreichbar)
- Gateway nicht erreichbar (Server down, kein Netz)
- Gültiges PFX vorhanden + nicht abgelaufen → Offline-Modus
- Context Key
auth.mode = offlinewird gesetzt - Extensions können per
when-Clause offline-sensitive Features deaktivieren - Kein Refresh Token nötig — PFX ist der Credential
- Offline-Modus-Dauer: bis PFX-Ablauf oder Gateway wieder erreichbar (Background-Retry)
Feature-Flags / ENIVERSASYS
Feature-Flags steuern, welche Funktionen in der Shell und in Extensions aktiv sind.
Sie sind kein Bestandteil des PFX — das PFX kennt nur die Lizenz-Stufe (tier).
Die granularen Feature-Flags werden nach erfolgreicher Auth aus der DB geladen.
Herkunft und Migration
| Stand | Namespace | System |
|---|---|---|
| Aktuell | auth.* | ENIVERSCAFM |
| Zukünftig | auth.* | ENIVERSASYS |
Die Shell spricht ausschließlich gegen das Gateway.Service. Das Gateway abstrahiert, ob es ENIVERSCAFM oder ENIVERSASYS als Quelle verwendet — die Shell bekommt immer dasselbe Antwortformat (JSON-Array der aktiven Feature-Keys).
Ladereihenfolge
Feature-Flags werden innerhalb von spBlockAuth geladen, nach dem JWT-Erhalt
und vor AdvancePhase(spBlockRestore). Extensions dürfen in when-Clauses
auf Feature-Flags zugreifen, also müssen sie vor dem Extension-Scan verfügbar sein.
Auth erfolgreich (JWT vorhanden)
│
▼
GET /api/features → Gateway.Service → ENIVERSASYS-DB
│
▼
Context Keys befüllen:
license.features = grids,charts,scheduling,...
│
▼
AdvancePhase(spBlockRestore)
Offline-Verhalten
Im Offline-Modus (Szenario D) ist kein Gateway-Aufruf möglich. Zwei Optionen — Entscheidung offen:
- Letzte bekannte Features aus
SecretStoragecachen (nach jedem erfolgreichen Online-Login schreiben) - Nur Basisfunktionen im Offline-Modus — Features deaktiviert bis Gateway erreichbar
TOTP — Aufgabenteilung
TOTP (RFC 6238) basiert auf einem geteilten Geheimnis zwischen Authenticator-App und Server. Die Kernfrage: Was muss WvdS.Shell selbst implementieren?
Algorithmus (zur Orientierung)
Gemeinsames Geheimnis (base32) → bei Enrollment einmalig zwischen App und Server ausgetauscht Counter = floor(unix_timestamp / 30) ← 30-Sekunden-Fenster Code = HMAC-SHA1(secret, counter) → auf 6 Dezimalstellen gekürzt
MS Authenticator, Google Authenticator und jede andere OATH-TOTP-App erzeugen denselben Code, solange sie dasselbe Geheimnis und eine synchrone Uhrzeit haben.
Was Gateway.Service implementiert
Das ist ausschließlich Server-Aufgabe:
- Shared Secret pro User erzeugen und sicher speichern
- Enrollment-URI (otpauth-Schema) und QR-Code für Authenticator-App generieren
- Eingehenden 6-stelligen Code validieren (HMAC-SHA1, ±1 Fenster Toleranz für Uhrzeitabweichung)
- Enrollment-Status pro User verwalten
- Fehlversuche zählen, Lockout-Policy durchsetzen
Was WvdS.Shell implementiert
Nahezu nichts vom Algorithmus. Die Shell ist nur ein UI-Träger für den Challenge-Response-Austausch:
- Challenge erkennen: Gateway antwortet mit
HTTP 401+ JSON-Body{„mfa_required“: true, „challenge_id“: „…“} - Nativen TOTP-Eingabe-Dialog anzeigen (6 Ziffern, pre-WebView, FPC/Lazarus)
- Optionaler 30-Sekunden-Countdown (UX-Hilfe, kein funktionaler Bedarf)
- Code +
challenge_idan Gateway senden - Falsche Eingabe: Fehlermeldung anzeigen, Retry erlauben (Gateway definiert Max-Versuche)
- Kein Zugriff auf das Shared Secret — liegt ausschließlich beim Gateway
Enrollment-Flow
Enrollment (erstmalige Einrichtung) ist kein Shell-Startup-Vorgang. Zwei Optionen:
| Option | Umsetzung | Wann sinnvoll |
|---|---|---|
| Admin-seitig | Gateway-Weboberfläche, Admin verknüpft User mit Authenticator-App | Verwaltete Deployments |
| Self-Service im Shell | Shell öffnet Gateway-Enrollment-URL in dediziertem WebView-Tab | BYOD, erster Start ohne Enrollment |
Beim Self-Service-Flow zeigt die Shell einen WebView, der auf die Gateway-Enrollment-Seite zeigt. Die Shell selbst generiert dabei nichts — der gesamte Enrollment-Prozess läuft im Gateway.
Zusammenfassung: Was WvdS.Shell selbst codiert
WvdS.Shell.Auth.Provider.TOTP.pas— nur Challenge/Response-Protokoll (HTTP-Austausch)WvdS.Shell.GUI.AuthDialog.pas— 6-Ziffern-Eingabefeld + optionaler Countdown-Timer- Kein HMAC, kein base32, kein Geheimnis-Management — das gehört zum Gateway
Gateway-seitige TOTP-Implementierung (Shared Secret, HMAC-SHA1, Lockout): 3. Gateway-Doku: TOTP Service
Token-Flow zwischen Shell und Gateway.Service
Shell (Client) Gateway.Service
│ │
│── SSPI Negotiate ─────────►│ (Kerberos — Szenario A/B)
│ + PFX install.id │ → DC validiert Kerberos
│◄─ Session JWT ─────────────│ → Gateway prüft PFX install.id
│ │
│ oder: │
│── username/pw + install.id►│ (Szenario C)
│◄─ TOTP-Challenge ──────────│
│── TOTP-Code ──────────────►│
│◄─ {access_token, refresh} ─│
│ │
│── refresh_token ──────────►│ (Silent Refresh, Hintergrund)
│◄─ neues access_token ──────│
Extensions bekommen nie den Refresh Token. Via IPC (JSON-RPC) fordern Extensions ein scoped Token an — der Shell-AuthManager tauscht das Shell-Token gegen ein Extension-spezifisches Token beim Gateway.
Technische Details der Gateway-Endpoints (Kerberos, TOTP, JWT, Refresh): 3. Gateway-Doku: Neue Endpoints
Startup-Phasen-Integration
In WvdS.Shell.Types.pas wird spBlockAuth eingefügt:
TWvdSShellStartupPhase = ( spBlockStartup, // Config, Log init spBlockAuth, // [WvdS 2026-03-05] PFX-Validation + Identity Provider spBlockRestore, // Extension scan, contribution routing spAfterRestored, // Activate startup extensions, show UI spEventually // Deferred tasks (auto-update check) );
Reihenfolge innerhalb von spBlockAuth:
- PFX laden und validieren (Schicht 1)
- PFX-Attribute in Context Keys schreiben (tier, expires, domains, install.id)
- Context-Detector ausführen (Schicht 2)
- Auth-Provider starten (Kerberos / MFA / Offline)
- Auth-Context Keys setzen (state, method, username, mfa)
- Feature-Flags aus ENIVERSASYS via Gateway laden →
license.featuressetzen AdvancePhase(spBlockRestore)— erst jetzt startet Extension-Scan
Context Keys nach Auth
| Key | Werte / Beispiel | Beschreibung |
|---|---|---|
auth.state | authenticated / pending / failed | Auth-Status |
auth.mode | online / offline | Gateway erreichbar? |
auth.method | windows / external | Verwendetes Verfahren |
auth.username | UPN oder Benutzername | Aktuell angemeldeter User |
auth.mfa | true / false | MFA wurde durchgeführt |
license.tier | professional / enterprise | Aus PFX (.1) |
license.expires | 2027-01-01 | Aus PFX (.2) |
license.installId | ENIVERS-2026-001 | Aus PFX (.5) |
license.features | grids,charts,scheduling | Aus ENIVERSASYS-DB (nach Auth) |
Beispiel-when-Clause in einem Extension-Manifest:
"when": "auth.state == authenticated && license.features contains charts"
Vorgeschlagene Unit-Struktur
Security/
WvdS.Shell.Security.SecretStorage.pas ← bereits vorhanden (DPAPI)
Auth/
WvdS.Shell.Auth.Types.pas ← Enums, Records, IAuthProvider
WvdS.Shell.Auth.Certificate.pas ← PFX laden, Kette validieren
WvdS.Shell.Auth.License.pas ← Custom-Attributes lesen, Feature-Flags
WvdS.Shell.Auth.ContextDetector.pas ← Domain-Join + DC-Ping + Gateway-Check
WvdS.Shell.Auth.SessionManager.pas ← Token-Lifecycle, Silent Refresh, Offline-Retry
Providers/
WvdS.Shell.Auth.Provider.Kerberos.pas ← SSPI/Kerberos (Windows-only)
WvdS.Shell.Auth.Provider.External.pas ← JWT-basiert (HTTP + Gateway)
WvdS.Shell.Auth.Provider.TOTP.pas ← Challenge-Response Handling
WvdS.Shell.Auth.Provider.Offline.pas ← PFX-basierter Offline-Pfad
GUI/
WvdS.Shell.GUI.AuthDialog.pas ← Nativer Login-Dialog (pre-WebView)
WvdS.Shell.GUI.OfflineBanner.pas ← StatusBar-Hinweis im Offline-Modus
WvdS.Shell.Auth.Types importiert nur RTL — null Shell-interne Deps, passend zur Schichten-Regel.
Design-Entscheidungen (protokolliert)
| Thema | Entscheidung | Begründung |
|---|---|---|
| Multi-Tenant | Nicht in Phase 1. Single-Tenant-Deployment. Erweiterbar via wvds.tenant.*-Attributes. | Reduziert Komplexität für den Erstaufbau. Die OID-Struktur ist vorbereitet — Multi-Tenant ist eine Konfigurationserweiterung, keine Architekturänderung. |
| SSPI-Fallback | Kein NTLM-Fallback. 2026 wird Kerberos vorausgesetzt. | NTLM ist anfällig für Pass-the-Hash-Angriffe und gilt als veraltet. Kein Fallback zu verwalten bedeutet eine kleinere Angriffsfläche. |
| Offline-Modus | PFX als Offline-Credential. Dauer bis PFX-Ablauf oder Gateway-Reconnect. | Ein Serverausfall darf den Betrieb nicht blockieren. Das PFX ist kryptografisch signiert — es kann ohne Serververbindung sicher geprüft werden. |
| PFX-Speicher | Cert Store (Corpnet/GPO) oder Datei + DPAPI-Passwort (BYOD). | Beide Varianten nutzen plattformeigene Schutzmechanismen. Kein eigenes Passwort-Management, keine eigene Verschlüsselung — Windows übernimmt das. |
| SSO | Out-of-the-box via Kerberos. Kein Benutzereingriff bei Corpnet. | Ein Passwort-Dialog beim Unternehmensrechner ist vermeidbare Reibung. Kerberos nutzt das bereits vorhandene Domain-Login — null Zusatzaufwand für den Benutzer. |
| CA | WvdS-interne CA. Root-Cert im Shell-Binary gebündelt. | Kein Abhängigkeit von öffentlichen CAs oder externen Zertifikatsdiensten. WvdS kontrolliert Ausstellung, Laufzeit und Widerruf vollständig selbst. |