Dies ist eine alte Version des Dokuments!


Gateway.Service — Auth-Erweiterungen für WvdS.Shell

Stand: 2026-03-05

Übergeordnet: Auth-Architektur — Gesamtübersicht Verwandt: 2. WvdS.Shell | 4. Datenschicht | 5. Migration

Ausgangslage

Gateway.Service hat eine vollständige Middleware-Pipeline und ein Auth-Enum mit allen benötigten Modi — jedoch ist nur ein Teil davon implementiert.

Aktuell implementiert

Auth-Modus Status Anmerkung
amNone ✓ Aktiv Nur für DEV ($IFDEF DEBUG)
amBasic ✓ Aktiv ConstantTimeEqual, CWE-208
amApiKey ✓ Aktiv ConstantTimeEqual, Header konfigurierbar
amBearer — Reserviert Interface vorhanden, nicht implementiert
amCertificate — Reserviert Interface vorhanden, nicht implementiert
amWindows — Reserviert Interface vorhanden, nicht implementiert

Benötigt für WvdS.Shell

Für die Shell-Integration müssen folgende Komponenten neu implementiert werden:

  1. PFX Install-ID Validierung (amCertificate)
  2. Kerberos/SSPI Handler (amWindows)
  3. JWT Ausstellung und Validierung (amBearer)
  4. TOTP Service (neu — für externen MFA-Flow)
  5. Refresh Token Management (neu)
  6. Feature-Flags Endpoint (neu — ENIVERSASYS-Anbindung)

Neue Endpoints

Alle neuen Auth-Endpoints unter /api/v1/auth/. Ein neuer Controller WvdS.Data.Gateway.Controller.Auth wird benötigt.

Übersicht

Verb Route Auth erforderlich Beschreibung
POST /api/v1/auth/kerberos Nein (ist der Auth-Schritt selbst) Kerberos Negotiate-Handshake
POST /api/v1/auth/external Nein Username/Passwort → TOTP-Challenge
POST /api/v1/auth/totp/verify Nein (Challenge-ID statt Token) TOTP-Code einlösen → JWT
POST /api/v1/auth/token/refresh Refresh Token Access Token erneuern
GET /api/v1/auth/totp/enroll JWT Bearer TOTP Enrollment-URI + QR generieren
DELETE /api/v1/auth/totp/enroll JWT Bearer TOTP-Enrollment zurücksetzen
GET /api/v1/features JWT Bearer Feature-Flags für aktuelle Session

POST /api/v1/auth/kerberos

Kerberos Negotiate-Handshake (mehrstufig, wie HTTP Negotiate definiert):

Request:
  POST /api/v1/auth/kerberos
  Authorization: Negotiate <Base64-SPNEGO-Token>
  X-WvdS-Install-Id: ENIVERS-2026-001

Response (ggf. mehrstufig):
  HTTP 401  Authorization: Negotiate <Base64-Challenge>   ← Server-Challenge
  HTTP 200  { "access_token": "...", "refresh_token": "...", "expires_in": 900 }

POST /api/v1/auth/external

Erster Schritt des externen MFA-Flows. Gibt bei gültigem Username/Passwort eine challenge_id zurück — noch kein Token.

Request:
  { "username": "max.muster", "password": "...", "install_id": "ENIVERS-2026-001" }
 
Response 200:
  { "mfa_required": true, "challenge_id": "c7f3a..." }
 
Response 401:
  { "error": "invalid_credentials" }

Passwort wird nach Validierung sofort via FillChar zeroiert (CWE-316).

POST /api/v1/auth/totp/verify

Zweiter Schritt des externen MFA-Flows. Löst die challenge_id gegen den TOTP-Code ein und gibt bei Erfolg die Token-Pair aus.

Request:
  { "challenge_id": "c7f3a...", "code": "482910" }
 
Response 200:
  { "access_token": "...", "refresh_token": "...", "expires_in": 900 }
 
Response 401:
  { "error": "invalid_code", "attempts_remaining": 2 }

POST /api/v1/auth/token/refresh

Silent Token Refresh. Refresh-Token wird im Request-Body oder als Authorization: Refresh <token> übergeben.

Request:
  { "refresh_token": "..." }
 
Response 200:
  { "access_token": "...", "expires_in": 900 }
 
Response 401:
  { "error": "refresh_token_expired" }

GET /api/v1/features

Lädt die Feature-Flags für den authentifizierten User/die Installation. Liest aktuell aus ENIVERSCAFM (auth.*-Namespace), zukünftig aus ENIVERSASYS.

Response 200:
  { "features": ["grids", "charts", "scheduling", "docking"] }

JWT — Ausstellung und Validierung

Signaturalgorithmus

JWT wird mit ML-DSA-65 signiert — die Bibliothek ist im Gateway bereits vorhanden (WvdS.Security.Cryptography). Kein externer Abhängigkeitsbedarf.

Standard-Header: jwt

Payload-Struktur

{
  "sub":        "max.muster@corp.example.com",
  "install_id": "ENIVERS-2026-001",
  "auth_method": "windows",
  "mfa":        false,
  "iat":        1741132800,
  "exp":        1741133700,
  "jti":        "a3f9..."
}

Feature-Flags werden nicht im JWT mitgeführt — sie werden bei Bedarf frisch vom /api/v1/features-Endpoint geladen. Grund: Flags können sich ändern ohne dass ein neues Token ausgestellt werden muss.

Token-Lebensdauer

Token Lebensdauer Speicherort (Client)
Access Token 15 Minuten RAM (Shell SessionManager)
Refresh Token 30 Tage DPAPI SecretStorage
TOTP Challenge 5 Minuten Gateway-RAM (nach Ablauf gelöscht)

Validierung in Middleware

TWvdSGatewayAuthHandler wird erweitert: Bei amBearer wird der JWT-Header extrahiert, ML-DSA-Signatur geprüft, exp-Claim validiert und install_id gegen die PFX-Registrierung abgeglichen.

TOTP Service

Zuständigkeit

Die gesamte TOTP-Logik liegt im Gateway — die Shell liefert nur den Code (6 Ziffern). Details: 2. Shell-Doku: TOTP Aufgabenteilung.

Implementierungsdetails

Algorithmus: HMAC-SHA1 (RFC 6238) über OpenSSL (WvdS.Security.Cryptography) — kein neuer Crypto-Code nötig.

Shared Secret Speicherung:

  • Pro User ein Base32-kodiertes Secret
  • Gespeichert AES-256-GCM-verschlüsselt in der Gateway-Datenbank (CWE-256)
  • Kein Plaintext auf Disk

Validierungsfenster: ±1 Zeitfenster (30 s × 3 = 90 s Toleranz für Uhrabweichung)

Lockout-Policy: Bestehender FailedAuthPerMinute-Alert-Counter wird genutzt. Nach 5 Fehlversuchen: Challenge ungültig, neuer POST /api/v1/auth/external nötig.

Challenge-Lifetime: 5 Minuten. Challenges in Gateway-RAM (TDictionary<String, TChallengeEntry>), kein DB-Roundtrip.

Enrollment Flow

Admin-seitig:
  GET /api/v1/auth/totp/enroll   (JWT des Admin-Users)
  → { "otpauth_uri": "otpauth://totp/...", "qr_base64": "..." }
  → Admin zeigt QR dem User (oder schickt URI per E-Mail)

Self-Service (Shell öffnet WebView):
  Shell navigiert zu: https://gateway/auth/enroll?token=<JWT>
  → Gateway zeigt HTML-Seite mit QR-Code
  → User scannt mit MS Authenticator
  → Enrollment-Bestätigung (User gibt ersten Code ein zum Verifizieren)

PFX Install-ID Validierung

Das Gateway prüft bei jedem Auth-Request ob die install_id aus dem PFX registriert und aktiv ist.

Header-Konvention

X-WvdS-Install-Id: ENIVERS-2026-001

Dieser Header wird von der Shell bei jedem Request mitgesendet — nicht nur beim Auth-Request.

Validierungslogik

  1. X-WvdS-Install-Id Header vorhanden?
  2. install_id in Deployment-Tabelle (DB) vorhanden und aktiv?
  3. Zugehöriges Ablaufdatum noch nicht überschritten?
  4. → Validierung OK: weiter mit Auth-Flow
  5. → Validierung FAIL: HTTP 403 "unlicensed installation"

Eine neue Tabelle (z. B. WVDS_DEPLOYMENTS) in der Gateway-Datenbank speichert:

Spalte Typ Beschreibung
INSTALL_ID VARCHAR(64) PK — z. B. ENIVERS-2026-001
TENANT_NAME VARCHAR(256) Anzeigename
LICENSE_TIER VARCHAR(32) professional / enterprise
VALID_UNTIL DATE Ablaufdatum (aus PFX synchronisiert)
DOMAINS VARCHAR(512) Erlaubte AD-Domänen (Komma-getrennt)
ACTIVE BIT Manuell deaktivierbar

Kerberos/SSPI Handler

Standalone-Modus

Wenn Gateway als Windows Service läuft (nicht hinter IIS/NGINX):

  • AcceptSecurityContext aus Secur32.dll (Windows SSPI API)
  • HTTP Authorization: Negotiate Header — mehrstufiger Handshake
  • Nach Erfolg: Identität via QueryContextAttributes(SECPKG_ATTR_NAMES) lesen
  • → JWT für diese Identität ausstellen

FastCGI-Modus (hinter IIS)

IIS übernimmt Windows Auth vollständig:

  • IIS sendet LOGON_USER als CGI-Umgebungsvariable
  • Gateway-FastCGI-Adapter (WvdS.Data.Gateway.FastCGI.Adapter) liest LOGON_USER
  • Kein AcceptSecurityContext im Gateway nötig — IIS hat bereits validiert
  • Direkt JWT ausstellen
Empfehlung: FastCGI hinter IIS für Corpnet-Deployments.
Standalone SSPI für Self-hosted Szenarien (kleinere Installationen).

Middleware-Änderungen

Bestehende Pipeline (9 Stufen)

1. TWvdSMetricsMiddleware
2. TWvdSLoggingMiddleware
3. TWvdSHttpsEnforcementMiddleware
4. TWvdSRequestSizeMiddleware
5. TWvdSRateLimitMiddleware
6. TWvdSGatewayAuthHandler          ← Erweiterung: amBearer + amWindows
7. TWvdSPayloadEncryptionMiddleware
8. TWvdSCompressionMiddleware
9. MapControllers

Geplante Erweiterungen

Stufe Komponente Änderung
3.5 TWvdSInstallIdMiddleware (neu) X-WvdS-Install-Id prüfen, vor Auth
6 TWvdSGatewayAuthHandler amBearer: JWT ML-DSA validieren + Claims extrahieren
6 TWvdSGatewayAuthHandler amWindows: SSPI Negotiate oder LOGON_USER (FastCGI)

TWvdSInstallIdMiddleware greift vor der eigentlichen Auth — ein Request ohne gültige Install-ID wird mit HTTP 403 abgelehnt, bevor Credentials geprüft werden.

Neue Units

src/
  controllers/
    WvdS.Data.Gateway.Controller.Auth.pas       ← /api/v1/auth/*, /api/v1/features
  core/
    WvdS.Data.Gateway.Auth.JwtService.pas       ← JWT Ausstellung (ML-DSA-65), Validierung
    WvdS.Data.Gateway.Auth.TotpService.pas      ← Shared Secret, Challenge, HMAC-SHA1 (OpenSSL)
    WvdS.Data.Gateway.Auth.KerberosHandler.pas  ← SSPI AcceptSecurityContext (Windows-only)
    WvdS.Data.Gateway.Auth.CertValidator.pas    ← Install-ID gegen DB prüfen
    WvdS.Data.Gateway.Auth.RefreshStore.pas     ← Refresh Token (gehashed, DB-backed)
  middleware/
    WvdS.Data.Gateway.Middleware.InstallId.pas  ← X-WvdS-Install-Id Middleware

Alle neuen Units im src/core/ und src/middleware/ — passend zur bestehenden Schichtenstruktur.

Security — CWE-Ergänzungen

Zusätzlich zu den bestehenden 22 CWEs kommen durch die Auth-Erweiterung:

CWE Beschreibung Implementierung
CWE-287 Improper Authentication Kerberos-Ticket muss vollständig validiert sein (nicht nur Presence-Check)
CWE-290 Token Spoofing JWT-Signatur (ML-DSA-65) wird bei jedem Request geprüft
CWE-613 Insufficient Session Expiration Refresh Token: 30 Tage, serverseitig revokierbar
CWE-620 Unverified Password Change TOTP-Enrollment erfordert bestätigten ersten Code
CWE-384 Session Fixation jti (JWT ID) einmalig, Replay via jti-Blacklist

Design-Entscheidungen (protokolliert)

Thema Entscheidung
JWT-Signatur ML-DSA-65 — Bibliothek bereits vorhanden, kein neuer Crypto-Code
TOTP-Crypto HMAC-SHA1 via OpenSSL — kein neuer Crypto-Code
Kerberos Standalone Secur32.dll SSPI direkt; FastCGI-Modus bevorzugt hinter IIS
Install-ID Transport HTTP-Header X-WvdS-Install-Id bei jedem Request
Feature-Flags Nicht im JWT — separater Endpoint, frisch laden
Refresh Token Storage Gehashed (SHA-256) in DB — nie im Klartext gespeichert
TOTP Enrollment Admin-seitig (primär) oder Self-Service WebView (BYOD)
Zuletzt geändert: den 05.03.2026 um 14:22