⬡ Webtest – Übersicht
Webtest ist eine Webanwendung zum Testen von Proxy- und Authentifizierungsinfrastruktur in Unternehmensumgebungen. Sie ermöglicht die Analyse von HTTP-Proxy-Verhalten, TLS-Konfigurationen, WebSocket-Durchgängigkeit und Content-Filterung sowie die Integration von Identity Providern via OIDC und SAML 2.0.
- Prüfen ob ein Proxy HTTP-Header verändert oder entfernt
- Testen ob TLS korrekt terminiert und weitergeroutet wird
- Validieren von WebSocket-Verbindungen durch Firewalls
- Testen von Datei-Downloads gegen Content-Filter
- Debuggen von OIDC- und SAML-Token-Claims und Gruppen-Mappings
- Anbinden mehrerer Entra-ID-Tenants und Keycloak-Instanzen
Funktionsübersicht
| Funktion | Beschreibung | URL |
|---|---|---|
| HTTP-Header-Analyse | Zeigt alle Request-Header, erkennt Proxy-Indikatoren | /probe/headers |
| TLS-Informationen | Server-seitige und client-seitige TLS-Details | /probe/tls |
| WebSocket-Test | Echo-Test, Ping, Live-Log | /probe/websocket |
| Content-Filter-Test | Downloads, JS-Ausführung, Fetch-API | /probe/content |
| Profil & Claims | Token-Claims, Gruppen, OIDC-Endpunkte | /profile |
| Provider-Verwaltung | OIDC & SAML Provider anlegen/bearbeiten | /config |
Architektur
Webtest besteht aus einer Node.js-Anwendung hinter einem nginx-Reverse-Proxy:
Technologie-Stack
| Komponente | Technologie | Beschreibung |
|---|---|---|
| Webserver | nginx ≥ 1.25 | TLS-Terminierung, Reverse Proxy, statische Dateien |
| Application Server | Node.js 20 LTS + Express 4 | Routing, Session-Management, Auth-Flows |
| Datenbank | SQLite (better-sqlite3) | Provider-Konfiguration, Benutzer, Session-Log |
| Sessions | connect-sqlite3 | Session-Store in SQLite, 8h TTL |
| OIDC | openid-client v5 | PKCE-Flow, Discovery, Token-Validierung |
| SAML | passport-saml v3 | SP-initiierter SAML 2.0 Flow |
| Prozess-Management | systemd + nodemon | Auto-Restart bei Änderungen |
Verzeichnisstruktur
/opt/webtest/ ├── src/ │ ├── server.js # Express-Einstiegspunkt │ ├── db.js # Datenbank-Init & Seeding │ ├── auth/ │ │ ├── oidc.js # Dynamischer OIDC-Client-Manager │ │ ├── saml.js # Dynamischer SAML-Strategie-Manager │ │ └── graph.js # Microsoft Graph API (Gruppenauflösung) │ ├── middleware/ │ │ └── requireAuth.js # Auth-Guards │ ├── routes/ │ │ ├── auth.js # Login/Callback-Routen │ │ ├── config.js # Provider-Verwaltung (Admin) │ │ ├── index.js # Dashboard & Startseite │ │ ├── probe.js # Test-Funktionen │ │ └── profile.js # Profil & Claims │ └── views/ │ └── layout.js # HTML-Layout-Hilfsfunktionen ├── static/ # Statische Dateien (CSS, Docs) ├── downloads/ # Test-Downloads (via nginx) ├── data/ # SQLite-Datenbank ├── .env # Konfiguration (nicht im Repo) └── package.json
Erste Schritte
Nach der Installation ist die Anwendung unter https://dev1.boesls.de erreichbar.
Klicke auf Local Login oder gehe direkt zu /auth/local.
Der Benutzername ist config, das initiale Passwort steht in der
.env-Datei unter INITIAL_PASSWORD.
Gehe zu /config → Neuer Provider um einen OIDC- oder SAML-Provider anzulegen. Siehe Provider konfigurieren.
Ändere das initiale Passwort des Config-Users unter /config → Passwort ändern.
Nach der Anmeldung stehen alle Probe-Seiten über das Dashboard zur Verfügung.
Lokale Benutzer
| Benutzername | Rolle | Berechtigungen |
|---|---|---|
config |
admin | Vollzugriff: Login, alle Probe-Seiten, Profil, Provider-Verwaltung, Passwort ändern |
testuser |
user | Login, alle Probe-Seiten, Profil – kein Zugriff auf /config |
Das Passwort für testuser ist in INITIAL_TEST_PASSWORD in der .env-Datei konfiguriert.
Authentifizierung
Webtest unterstützt drei Authentifizierungsmethoden:
| Methode | Protokoll | Konfiguration | Startpunkt |
|---|---|---|---|
| Lokaler Login | Benutzername + Passwort | .env / /config |
/auth/local |
| OIDC | OpenID Connect (PKCE) | /config → Provider bearbeiten |
/auth/oidc/:name |
| SAML 2.0 | SAML SP-initiiert | /config → Provider bearbeiten |
/auth/saml/:name |
Lokaler Login
Der lokale Login verwendet Benutzername und Passwort. Passwörter werden mit
bcrypt (Cost 12) gehasht in SQLite gespeichert. Das Login-Formular ist
gegen CSRF-Angriffe gesichert (zufälliges Token pro Session, im Hidden-Field).
testuser eignet sich für Tests ohne Admin-Rechte.
OpenID Connect (OIDC)
Der OIDC-Flow verwendet Authorization Code Flow mit PKCE (Proof Key for Code Exchange). Es wird keine Implicit Flow oder Hybrid Flow verwendet.
Nach erfolgreichem Login werden alle Token-Claims, Gruppen und OIDC-Endpunkt-URLs in der Session gespeichert und unter /profile angezeigt.
Bei Microsoft Entra ID: Gruppen werden zusätzlich über die
Microsoft Graph API (/me/memberOf) aufgelöst, um
Anzeigenamen zu erhalten. Bei mehr als 200 Gruppen wird automatisch der Overage-Claim
behandelt.
SAML 2.0
Der SAML-Flow ist SP-initiiert (Service Provider initiates). Der SP schickt eine
AuthnRequest an den IdP, der Benutzer authentifiziert sich, und der IdP
postet die SAML-Assertion an den Assertion Consumer Service (ACS) des SP.
Attribut-Normalisierung: Die Anwendung erkennt automatisch verschiedene Namensformate (Microsoft-Schema-URIs, Keycloak-Kurzformen, Standard-Attribute).
Konto wechseln
Viele Browser und Identity Provider speichern die zuletzt verwendete Identität. Webtest bietet an zwei Stellen die Möglichkeit, einen anderen Account zu verwenden, ohne den Browser-Cache zu leeren:
Login-Seite
Jede Provider-Karte zeigt zwei Optionen: Anmelden (nutzt die bestehende IdP-Session) und Anderen Account verwenden → (erzwingt die Kontoauswahl beim IdP).
Profil-Seite (bereits angemeldet)
Direkt unter dem angemeldeten Benutzer erscheinen zwei Schaltflächen: ⇄ Anderen Account verwenden startet einen neuen Auth-Flow ohne vorherigen Logout — die Session wird nach erfolgreicher Re-Authentifizierung automatisch überschrieben. Abmelden zerstört die aktuelle Session.
| Protokoll | Mechanismus | URL-Parameter | Effekt |
|---|---|---|---|
| OIDC | OAuth prompt-Parameter |
?prompt=select_account |
IdP zeigt Account-Auswahl, auch bei aktiver Browser-Session |
| OIDC | OAuth prompt-Parameter |
?prompt=login |
IdP erzwingt vollständige Re-Authentifizierung (Passwort-Eingabe) |
| SAML | ForceAuthn="true" in AuthnRequest |
?force=1 |
IdP muss den Benutzer neu authentifizieren, ignoriert SSO-Session |
Provider konfigurieren
Provider werden über /config verwaltet (nur für den Admin-User zugänglich). Jeder Provider hat einen eindeutigen internen Namen (URL-sicherer Slug), der in den Login-URLs verwendet wird:
- OIDC:
https://dev1.boesls.de/auth/oidc/{name} - SAML:
https://dev1.boesls.de/auth/saml/{name}
Mehrere Provider desselben Typs sind möglich, z.B. zwei Entra-ID-Tenants
(contoso, fabrikam) und eine Keycloak-Instanz
(keycloak-prod).
Provider-Typen
| Typ | Protokoll | Typische IdPs |
|---|---|---|
| entra | OIDC (Authorization Code + PKCE) | Microsoft Entra ID (Azure AD) |
| keycloak | OIDC (Authorization Code + PKCE) | Keycloak, Okta, Auth0, jeder OIDC-konforme IdP |
| saml | SAML 2.0 (HTTP-POST Binding) | Entra ID SAML, ADFS, Keycloak SAML, Shibboleth, PingFederate |
Microsoft Entra ID (OIDC)
Für die OIDC-Integration mit Entra ID wird eine App Registration im Azure Portal benötigt.
Azure Portal → Microsoft Entra ID → App registrations → New registration
- Name: z.B.
Webtest - Supported account types: Accounts in this organizational directory only
- Redirect URI: Web →
https://dev1.boesls.de/auth/oidc/callback
Auf der Overview-Seite der App Registration:
- Application (client) ID → in Webtest als "Client ID" eintragen
- Directory (tenant) ID → in Webtest als "Tenant ID" eintragen
Der Issuer wird automatisch gebildet:
https://login.microsoftonline.com/{tenant_id}/v2.0
App Registration → Certificates & secrets → New client secret
Den angezeigten Value (nicht die Secret ID!) kopieren –
er wird nur einmal angezeigt!
App Registration → API permissions → Add a permission → Microsoft Graph → Delegated:
openid,profile,email(Standard)GroupMember.Read.All– für Gruppenauflösung via Graph API
Danach: Grant admin consent für die gesamte Organisation klicken.
App Registration → Token configuration → Add groups claim
- Typ: Security groups (oder All groups)
- Für ID-Token und Access-Token aktivieren
_claim_names.groups).
Webtest erkennt dies automatisch und lädt alle Gruppen über die Graph API.
/config → Neuer Provider: Typ Microsoft Entra ID wählen, Werte eintragen, Aktiviert ankreuzen und speichern. Der Status wechselt auf Verbunden, wenn die OIDC-Discovery erfolgreich war.
Mehrere Entra-ID-Tenants
Für jeden Tenant eine eigene App Registration erstellen und in Webtest als separater
Provider mit eindeutigem Namen anlegen (z.B. contoso, fabrikam).
Jeder Provider hat seine eigene Client ID, Client Secret und Tenant ID.
Keycloak (OIDC)
Keycloak und andere OIDC-konforme IdPs (Okta, Auth0, …) werden über den Typ Keycloak eingebunden. Anstelle der Tenant ID wird die Issuer URL angegeben.
Keycloak Admin → Realm → Clients → Create client
- Client type: OpenID Connect
- Client ID: z.B.
webtest - Client authentication: On (damit ein Secret erzeugt wird)
- Valid redirect URIs:
https://dev1.boesls.de/auth/oidc/callback
Client → Credentials → Client secret kopieren
Format: https://<keycloak-host>/realms/<realm-name>
Das Discovery-Dokument ist unter {issuer_url}/.well-known/openid-configuration erreichbar.
/config → Neuer Provider: Typ Keycloak, Issuer URL, Client ID und Secret eintragen.
SAML 2.0
Die SAML-Integration unterstützt jeden SAML 2.0-konformen Identity Provider (Entra ID SAML, ADFS, Keycloak SAML, Shibboleth, PingFederate, etc.).
SP-Informationen für den IdP
Beim Anlegen eines SAML-Providers werden folgende SP-Werte konfiguriert:
| Wert | Format | Beschreibung |
|---|---|---|
| ACS URL / Callback | https://dev1.boesls.de/auth/saml/{name}/callback |
Ziel des SAML-POST vom IdP (Assertion Consumer Service) |
| Entity ID / Issuer | https://dev1.boesls.de |
Eindeutiger Bezeichner des Service Providers |
| SP-Metadaten | https://dev1.boesls.de/auth/saml/{name}/metadata |
Automatisch generierte SP-Metadaten (XML) für den IdP |
/config → Neuer Provider:
Typ SAML 2.0 und internen Namen vergeben (z.B. adfs).
Die SP-Metadaten-URL (/auth/saml/{name}/metadata) im IdP eintragen,
oder die ACS URL und Entity ID manuell konfigurieren.
Das öffentliche Signaturzertifikat des IdP (PEM-Format) im Feld IdP-Signaturzertifikat eintragen. Wird zum Verifizieren der SAML-Antwort verwendet.
Die SSO/Single Sign-On URL des IdP im Feld IdP SSO URL eintragen:
- Entra ID:
https://login.microsoftonline.com/{tenant_id}/saml2 - Keycloak:
https://<host>/realms/<realm>/protocol/saml - ADFS:
https://adfs.example.com/adfs/ls/
Attribut-Normalisierung
Webtest erkennt automatisch verschiedene SAML-Attributformate und normalisiert sie:
| Webtest-Feld | Erkannte SAML-Attribute |
|---|---|
| Username / UPN |
nameID,
…/claims/upn,
…/claims/emailaddress,
email
|
| Anzeigename |
…/claims/name,
…/identity/claims/displayname,
displayName,
name,
cn
|
| Gruppen |
…/ws/2008/06/identity/claims/groups,
groups
|
Gruppen-Einschränkung
Jeder Provider kann optional auf bestimmte Gruppen eingeschränkt werden. Die Konfiguration erfolgt im Provider-Bearbeitungsformular unter /config → Provider → Bearbeiten, ganz unten im Abschnitt Erlaubte Gruppen.
Verhalten
| Konfiguration | Effekt beim Login |
|---|---|
| Kein Eintrag (leer) | Alle Benutzer dieses Providers dürfen sich anmelden |
| Eine oder mehrere Gruppen eingetragen | Nur Benutzer, die mindestens einer der aufgelisteten Gruppen angehören, erhalten Zugang |
| Benutzer nicht in einer erlaubten Gruppe | Login wird verweigert, Session sofort zerstört, Fehlermeldung auf der Startseite: „Zugriff verweigert: Sie sind nicht Mitglied einer berechtigten Gruppe." |
Format der Gruppen-IDs
Pro Zeile eine Gruppe. Groß-/Kleinschreibung wird ignoriert.
| Provider-Typ | Einzutragender Wert | Wo zu finden |
|---|---|---|
| entra OIDC | Object-ID (GUID) der Gruppexxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx |
Azure Portal → Groups → Group ID, oder nach Login unter /profile → Gruppen |
| keycloak OIDC | Gruppen-ID oder Gruppenname, je nach Token-Mapping | Keycloak Admin → Groups, oder nach Login unter /profile → Gruppen |
| saml SAML | Gruppen-GUID oder -Name, wie er in der SAML-Assertion erscheint | Nach Login unter /profile → SAML-Attribute → groups |
Ablauf bei verweigerten Zugriff
HTTP-Header-Analyse
Unter /probe/headers werden alle HTTP-Request-Header angezeigt, die der Server empfängt. Dies ermöglicht die Analyse des Verhaltens von HTTP-Proxies in Unternehmensumgebungen.
Was wird angezeigt?
- Alle Request-Header in einer Tabelle (Name + Wert)
- Proxy-Indikatoren werden farblich hervorgehoben (orange):
via,x-forwarded-for,x-forwarded-proto,x-forwarded-host,x-real-ip,forwarded,x-request-id,x-correlation-id
Typische Erkenntnisse
- Via: Welche Proxies wurden durchlaufen?
- X-Forwarded-For: Originale Client-IP (ggf. Proxy-Kette)
- User-Agent: Wurde der Browser-User-Agent durch den Proxy verändert?
- Fehlende Header: Hat der Proxy bestimmte Header entfernt?
- Zusätzliche Header: Fügt der Proxy eigene Header hinzu?
proxy_pass_request_headers on). Die Header
X-Forwarded-For, X-Forwarded-Proto und X-Real-IP
werden von nginx gesetzt.
TLS-Informationen
Unter /probe/tls werden TLS- und Verbindungsinformationen angezeigt.
Server-seitig (via nginx-Headern)
- TLS-Protokollversion (
X-SSL-Protocol) - Verwendete Cipher Suite (
X-SSL-Cipher) - Forwarded-Proto Header (Bestätigung HTTPS-Terminierung)
Client-seitig (via JavaScript)
- Detektiertes Protokoll aus Browser-Sicht (
window.location.protocol) - User-Agent und Browser-Informationen
- HTTP/2 vs. HTTP/1.1 Erkennung
WebSocket-Test
Unter /probe/websocket kann eine WebSocket-Verbindung interaktiv getestet werden.
Funktionen
- Verbinden / Trennen: WebSocket-Verbindung auf- und abbauen
- Echo-Test: Beliebige Nachrichten senden, Echo-Antwort empfangen
- Ping: Server sendet alle 10 Sekunden einen Ping
- Live-Log: Alle gesendeten und empfangenen Nachrichten mit Timestamp
- Status-Anzeige: Verbindungsstatus (Connecting / Connected / Error / Closed)
WebSocket-Endpunkt
Der WebSocket-Server läuft auf wss://dev1.boesls.de/ws.
nginx leitet das Upgrade-Protokoll transparent weiter.
Nachrichtenformat (JSON)
{ "type": "connected", "ts": "2026-01-01T12:00:00.000Z", "server": "Webtest" }
{ "type": "ping", "ts": "..." }
{ "type": "echo", "data": "Deine Nachricht", "ts": "..." }
Upgrade: websocket Header durchgelassen wird.
Content-Filter-Test
Unter /probe/content können verschiedene Content-Typen getestet werden, die von Unternehmens-Proxies häufig gefiltert oder blockiert werden.
Test-Downloads
Testdateien verschiedener Typen und Größen werden direkt von nginx ausgeliefert (kein Node.js beteiligt):
| Datei | Typ | Zweck |
|---|---|---|
test.txt | text/plain | Einfacher Textdatei-Download |
test.zip | application/zip | ZIP-Archiv (oft gefiltert) |
test.exe | application/octet-stream | Executable (häufig blockiert) |
test.js | application/javascript | JavaScript-Datei |
test.xml | text/xml | XML-Datei |
JavaScript-Ausführungstest
Prüft ob JavaScript im Browser ausgeführt wird. Wenn ein Content-Filter JavaScript-Dateien blockiert oder manipuliert, schlägt dieser Test fehl.
Fetch-API-Test
Führt einen asynchronen HTTP-Request via fetch() aus und zeigt
den Status und die empfangenen Header an. Testet ob der Proxy XMLHttpRequests
oder Fetch-Requests blockiert.
Profil & Claims
Unter /profile werden alle Informationen aus dem Authentifizierungs-Token bzw. der SAML-Assertion angezeigt.
Angezeigte Informationen
| Abschnitt | Inhalt | Verfügbar bei |
|---|---|---|
| Angemeldeter Benutzer | Anzeigename, Username/UPN, Auth-Methode | Alle Methoden |
| Token-Claims / SAML-Attribute | Alle Claims aus dem ID-Token oder SAML-Assertion als Key-Value-Tabelle | OIDC, SAML |
| Gruppen | Anzeigename + Object ID/GUID aller Gruppen; bei Entra ID via Graph API aufgelöst | OIDC, SAML |
| OIDC-Endpunkte | Authorization, Token, Userinfo, JWKS, End Session Endpoint URLs | OIDC |
GroupMember.Read.All-Berechtigung und Admin Consent.
Konto wechseln
Direkt unter dem angemeldeten Benutzer befinden sich zwei Schaltflächen:
-
⇄ Anderen Account verwenden — startet einen neuen Auth-Flow
beim gleichen Provider mit erzwungener Account-Auswahl
(
prompt=select_accountfür OIDC,ForceAuthn=truefür SAML). Kein vorheriger Logout nötig; die Session wird nach erfolgreicher Re-Authentifizierung überschrieben. - Abmelden — zerstört die aktuelle Session und leitet zur Startseite weiter.
Die Gruppen-IDs in der Gruppen-Tabelle können direkt für die Gruppen-Einschränkung in der Provider-Konfiguration verwendet werden.
Endpunkt-Referenz
Vollständige Liste aller HTTP-Endpunkte. Detaillierte Liste unter /endpoints.
Authentifizierung
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /auth/local | Login-Formular |
| POST | /auth/local | Login verarbeiten (CSRF-geschützt) |
| GET | /auth/oidc/:name | OIDC-Flow starten · ?prompt=select_account / ?prompt=login für Konto-Auswahl |
| GET | /auth/oidc/callback | OIDC-Callback (alle Provider) |
| GET | /auth/saml/:name | SAML SP-initiierter Flow · ?force=1 für ForceAuthn |
| POST | /auth/saml/:name/callback | SAML ACS (Assertion Consumer Service) |
| GET | /auth/saml/:name/metadata | SP-Metadaten XML |
| GET | /auth/logout | Logout (Session zerstören) |
Konfiguration (Admin)
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /config | Konfigurationsübersicht |
| GET | /config/providers/new | Neuen Provider anlegen |
| POST | /config/providers/new | Provider erstellen |
| GET | /config/providers/:name/edit | Provider bearbeiten |
| POST | /config/providers/:name/edit | Provider speichern |
| POST | /config/providers/:name/delete | Provider löschen |
| POST | /config/password | Passwort ändern |
Test-Funktionen & Sonstiges
| Methode | Pfad | Beschreibung |
|---|---|---|
| GET | /probe/headers | HTTP-Header-Analyse |
| GET | /probe/tls | TLS-Verbindungsinformationen |
| GET | /probe/websocket | WebSocket-Testseite |
| WS | /ws | WebSocket-Endpunkt (Echo + Ping) |
| GET | /probe/content | Content-Filter-Test |
| GET | /downloads/* | Test-Downloads (direkt via nginx) |
| GET | /profile | Profil, Claims, Gruppen |
| GET | /endpoints | Routen-Übersicht |
| GET | /docs | Diese Dokumentation |
Sicherheit
Implementierte Maßnahmen
| Maßnahme | Beschreibung |
|---|---|
| CSRF-Schutz | Alle zustandsändernden POST-Anfragen prüfen ein zufälliges Token aus der Session |
| OIDC PKCE | code_verifier/code_challenge verhindert Authorization-Code-Intercept |
| OIDC State & Nonce | State verhindert CSRF im OAuth-Flow, Nonce verhindert Replay-Angriffe |
| SAML-Signaturverifikation | Jede SAML-Response wird gegen das konfigurierte IdP-Zertifikat validiert |
| Secure Cookies | Session-Cookie mit HttpOnly, Secure, SameSite=Lax |
| Helmet.js | Setzt diverse Security-Header (HSTS, X-Frame-Options, X-Content-Type-Options, …) |
| bcrypt | Passwörter werden mit bcrypt Cost 12 gehasht, niemals im Klartext gespeichert |
| Trust Proxy | app.set('trust proxy', 1) ermöglicht korrekte Secure-Cookie-Setzung hinter nginx |
| HTML-Escaping | Alle Nutzerdaten werden vor der HTML-Ausgabe mit escapeHtml() escapet |
Hinweise
- OIDC Client Secrets und SAML-Zertifikate werden in der SQLite-Datenbank gespeichert
- Die Datenbankdatei sollte nur für den Service-User (
webtest) lesbar sein - Die
.env-Datei enthält das Session-Secret und sollte entsprechend geschützt sein - Session-Tokens haben eine Gültigkeit von 8 Stunden
Deployment
Voraussetzungen
- Debian/Ubuntu Linux
- Node.js 20 LTS
- nginx ≥ 1.25 (für
http2 on;-Direktive) - Certbot (für Let's Encrypt TLS-Zertifikat)
Umgebungsvariablen (.env)
| Variable | Beschreibung | Standard |
|---|---|---|
NODE_ENV | Laufzeitumgebung (production aktiviert Secure-Cookies) | development |
PORT | TCP-Port für den Express-Server | 3000 |
DOMAIN | Öffentliche Domain (wird für Callback-URLs verwendet) | localhost |
SESSION_SECRET | Geheimer Schlüssel für Session-Signierung (≥ 32 zufällige Bytes) | Zufällig generiert |
DB_PATH | Pfad zur SQLite-Datenbankdatei | /opt/webtest/data/webtest.db |
INITIAL_PASSWORD | Initiales Passwort für config-User | – |
INITIAL_TEST_PASSWORD | Initiales Passwort für testuser | – |
systemd-Service
Die Anwendung läuft als systemd-Service unter dem Benutzer webtest.
nodemon überwacht Änderungen in src/ und static/
und startet die Anwendung automatisch neu.
sudo systemctl status webtest sudo systemctl restart webtest journalctl -u webtest -f
Datenbankstruktur
| Tabelle | Inhalt |
|---|---|
users | Lokale Benutzer (username, bcrypt-Passwort, Rolle) |
providers | OIDC- und SAML-Provider-Konfiguration |
session_log | Protokoll aller Anmeldungen (Username, Methode, IP, Timestamp) |