Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| de:int:wvdsshell:notes:01-auth-architecture:auth-shell [2026/03/05 14:21] – angelegt - Externe Bearbeitung 127.0.0.1 | de:int:wvdsshell:notes:01-auth-architecture:auth-shell [Unbekanntes Datum] (aktuell) – gelöscht - Externe Bearbeitung (Unbekanntes Datum) 127.0.0.1 | ||
|---|---|---|---|
| Zeile 1: | Zeile 1: | ||
| - | ====== Auth-Architektur: | ||
| - | |||
| - | //Stand: 2026-03-05// | ||
| - | |||
| - | Übergeordnet: | ||
| - | Verwandt: [[de: | ||
| - | |||
| - | ===== Konzept ===== | ||
| - | |||
| - | WvdS.Shell verwendet eine **zweischichtige Auth-Architektur**: | ||
| - | |||
| - | - **Schicht 1 — PFX-Zertifikat** (Installations-/ | ||
| - | - **Schicht 2 — Identity Provider** (Benutzer-Authentifizierung): | ||
| - | |||
| - | 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/ | ||
| - | * **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: '' | ||
| - | |||
| - | ^ OID-Suffix ^ Attribut-Name | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | |||
| - | > **Nicht im PFX:** '' | ||
| - | |||
| - | ==== Deployment-Varianten ==== | ||
| - | |||
| - | ^ Variante | ||
| - | | **Corpnet** | ||
| - | | **BYOD / Extern** | Datei '' | ||
| - | |||
| - | Cert-Store-Variante: | ||
| - | |||
| - | ==== 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 | ||
| - | (Schicht 2) "Kein gültiges Lizenzzertifikat" | ||
| - | → Shell-Start abgebrochen | ||
| - | </ | ||
| - | |||
| - | ===== Schicht 2 — Identity Provider ===== | ||
| - | |||
| - | ==== Context-Aware Auth (Netzwerk-Erkennung) ==== | ||
| - | |||
| - | < | ||
| - | │ | ||
| - | ▼ | ||
| - | ┌─ Context-Detector ────────────────────────────────────┐ | ||
| - | │ 1. Domain-joined? | ||
| - | │ 2. DC erreichbar? | ||
| - | │ 3. Gateway erreichbar? → HTTP Health-Check | ||
| - | └───────────────────────────────────────────────────────┘ | ||
| - | │ | ||
| - | | ||
| - | | ||
| - | | ||
| - | (Kerberos) | ||
| - | </ | ||
| - | |||
| - | ==== Szenario A — Corpnet (LAN/WLAN) ==== | ||
| - | |||
| - | * Domain-joined + DC erreichbar + Gateway erreichbar | ||
| - | * SSPI/ | ||
| - | * **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, | ||
| - | * 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 → '' | ||
| - | |||
| - | ==== Szenario D — Offline (kein Gateway erreichbar) ==== | ||
| - | |||
| - | * Gateway nicht erreichbar (Server down, kein Netz) | ||
| - | * Gültiges PFX vorhanden + nicht abgelaufen → **Offline-Modus** | ||
| - | * Context Key '' | ||
| - | * Extensions können per '' | ||
| - | * Kein Refresh Token nötig — PFX ist der Credential | ||
| - | * Offline-Modus-Dauer: | ||
| - | |||
| - | ===== 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 ('' | ||
| - | Die granularen Feature-Flags werden nach erfolgreicher Auth aus der DB geladen. | ||
| - | |||
| - | ==== Herkunft und Migration ==== | ||
| - | |||
| - | ^ Stand ^ Namespace | ||
| - | | Aktuell | ||
| - | | Zukünftig | '' | ||
| - | |||
| - | 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 '' | ||
| - | und **vor** '' | ||
| - | auf Feature-Flags zugreifen, also müssen sie vor dem Extension-Scan verfügbar sein. | ||
| - | |||
| - | < | ||
| - | Auth erfolgreich (JWT vorhanden) | ||
| - | │ | ||
| - | ▼ | ||
| - | GET / | ||
| - | │ | ||
| - | ▼ | ||
| - | | ||
| - | | ||
| - | │ | ||
| - | ▼ | ||
| - | | ||
| - | </ | ||
| - | |||
| - | ==== Offline-Verhalten ==== | ||
| - | |||
| - | Im Offline-Modus (Szenario D) ist kein Gateway-Aufruf möglich. | ||
| - | Zwei Optionen — Entscheidung offen: | ||
| - | |||
| - | * **Letzte bekannte Features** aus '' | ||
| - | * **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, | ||
| - | </ | ||
| - | |||
| - | MS Authenticator, | ||
| - | 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 '' | ||
| - | - Nativen TOTP-Eingabe-Dialog anzeigen (6 Ziffern, pre-WebView, | ||
| - | - Optionaler 30-Sekunden-Countdown (UX-Hilfe, kein funktionaler Bedarf) | ||
| - | - Code + '' | ||
| - | - 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, | ||
| - | | **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: | ||
| - | |||
| - | * '' | ||
| - | * '' | ||
| - | * Kein HMAC, kein base32, kein Geheimnis-Management — das gehört zum Gateway | ||
| - | |||
| - | Gateway-seitige TOTP-Implementierung (Shared Secret, HMAC-SHA1, Lockout): | ||
| - | [[de: | ||
| - | |||
| - | ===== Token-Flow zwischen Shell und Gateway.Service ===== | ||
| - | |||
| - | < | ||
| - | Shell (Client) | ||
| - | │ │ | ||
| - | │── SSPI Negotiate ─────────►│ | ||
| - | │ + PFX install.id | ||
| - | │◄─ Session JWT ─────────────│ | ||
| - | │ │ | ||
| - | │ oder: │ | ||
| - | │── username/pw + install.id►│ | ||
| - | │◄─ TOTP-Challenge ──────────│ | ||
| - | │── TOTP-Code ──────────────►│ | ||
| - | │◄─ {access_token, | ||
| - | │ │ | ||
| - | │── refresh_token ──────────►│ | ||
| - | │◄─ neues access_token ──────│ | ||
| - | </ | ||
| - | |||
| - | Extensions bekommen **nie** den Refresh Token. Via IPC (JSON-RPC) fordern Extensions ein scoped Token an — der Shell-'' | ||
| - | |||
| - | Technische Details der Gateway-Endpoints (Kerberos, TOTP, JWT, Refresh): | ||
| - | [[de: | ||
| - | |||
| - | ===== Startup-Phasen-Integration ===== | ||
| - | |||
| - | In '' | ||
| - | |||
| - | <code pascal> | ||
| - | TWvdSShellStartupPhase = ( | ||
| - | spBlockStartup, | ||
| - | spBlockAuth, | ||
| - | spBlockRestore, | ||
| - | spAfterRestored, | ||
| - | spEventually | ||
| - | ); | ||
| - | </ | ||
| - | |||
| - | Reihenfolge innerhalb von '' | ||
| - | - 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 → '' | ||
| - | - '' | ||
| - | |||
| - | ===== Context Keys nach Auth ===== | ||
| - | |||
| - | ^ Key ^ Werte / Beispiel | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | |||
| - | Beispiel-'' | ||
| - | |||
| - | <code json> | ||
| - | " | ||
| - | </ | ||
| - | |||
| - | ===== Vorgeschlagene Unit-Struktur ===== | ||
| - | |||
| - | < | ||
| - | Security/ | ||
| - | WvdS.Shell.Security.SecretStorage.pas | ||
| - | Auth/ | ||
| - | WvdS.Shell.Auth.Types.pas | ||
| - | WvdS.Shell.Auth.Certificate.pas | ||
| - | WvdS.Shell.Auth.License.pas | ||
| - | WvdS.Shell.Auth.ContextDetector.pas | ||
| - | WvdS.Shell.Auth.SessionManager.pas | ||
| - | Providers/ | ||
| - | WvdS.Shell.Auth.Provider.Kerberos.pas | ||
| - | WvdS.Shell.Auth.Provider.External.pas | ||
| - | WvdS.Shell.Auth.Provider.TOTP.pas | ||
| - | WvdS.Shell.Auth.Provider.Offline.pas | ||
| - | |||
| - | GUI/ | ||
| - | WvdS.Shell.GUI.AuthDialog.pas | ||
| - | WvdS.Shell.GUI.OfflineBanner.pas | ||
| - | </ | ||
| - | |||
| - | '' | ||
| - | |||
| - | ===== Design-Entscheidungen (protokolliert) ===== | ||
| - | |||
| - | ^ Thema ^ Entscheidung | ||
| - | | Multi-Tenant | ||
| - | | SSPI-Fallback | Kein NTLM-Fallback. 2026 wird Kerberos vorausgesetzt. | ||
| - | | Offline-Modus | PFX als Offline-Credential. Dauer bis PFX-Ablauf oder Gateway-Reconnect. | ||
| - | | PFX-Speicher | ||
| - | | SSO | Out-of-the-box via Kerberos. Kein Benutzereingriff bei Corpnet. | ||
| - | | CA | WvdS-interne CA. Root-Cert im Shell-Binary gebündelt. | ||
Zuletzt geändert: den 05.03.2026 um 14:21