Technische Referenz¶
Zielgruppe: Provider (ISN Systems) — Deployment, Architektur, Debugging
Architektur¶
Browser → Traefik (443)
↓
auth-check Middleware (ForwardAuth)
↓
GET http://auth-service:8091/verify
↓
Auth-Service (PHP 8.4 + SQLite)
├── Route in protected_routes?
│ ├── Nein → 200 OK (durchlassen)
│ └── Ja → Cookie pruefen
│ ├── Gueltig → 200 OK + X-Auth-* Header
│ └── Ungueltig → 302 → auth.xynap.tech/login
↓
Backend-Service
Komponenten¶
| Komponente | Technologie | Speicherort |
|---|---|---|
| Auth-Service | PHP 8.4 (Built-in Server) | /usr/local/xynap/auth-service/ |
| Datenbank | SQLite 3 | /var/lib/xynap/auth-service/auth.db (Volume) |
| CSRF-Secret | Datei | /var/lib/xynap/auth-service/auth.db.csrf_secret |
| Templates | HTML | /usr/local/xynap/auth-service/templates/ |
| Container | Docker | auth-service (Port 8091 intern) |
Datenbank-Schema¶
Tabelle: users¶
| Spalte | Typ | Beschreibung |
|---|---|---|
id |
INTEGER PK | Auto-Increment |
email |
TEXT UNIQUE | Login-Email (lowercase) |
password |
TEXT | bcrypt Hash (cost=12) |
name |
TEXT | Anzeigename |
status |
TEXT | pending / active / blocked |
role |
TEXT | user / admin |
created_at |
DATETIME | Registrierungsdatum |
approved_at |
DATETIME | Freischaltdatum |
last_login |
DATETIME | Letzter Login |
Tabelle: sessions¶
| Spalte | Typ | Beschreibung |
|---|---|---|
token |
TEXT PK | 64-Zeichen Hex-Token (Session-ID) |
user_id |
INTEGER FK | Referenz auf users.id |
ip |
TEXT | IP des Logins |
user_agent |
TEXT | Browser User-Agent |
created_at |
DATETIME | Session-Start |
expires_at |
DATETIME | Ablaufzeit (TTL: 24h) |
Tabelle: protected_routes¶
| Spalte | Typ | Beschreibung |
|---|---|---|
id |
INTEGER PK | Auto-Increment |
host |
TEXT | Domain (z.B. ai.xynap.tech) |
path |
TEXT | URL-Pfad (z.B. /) |
description |
TEXT | Kurzbeschreibung |
required_role |
TEXT | user oder admin |
enabled |
INTEGER | 1 = aktiv, 0 = inaktiv |
created_at |
DATETIME | Erstelldatum |
Tabelle: login_attempts¶
| Spalte | Typ | Beschreibung |
|---|---|---|
ip |
TEXT | Quell-IP |
attempted_at |
DATETIME | Zeitpunkt des Fehlversuchs |
Traefik-Integration¶
Middleware-Definition¶
In der Docker-Compose (/etc/xynap/stack/docker-compose.yml) am auth-service Container:
labels:
- "traefik.http.middlewares.auth-check.forwardauth.address=http://auth-service:8091/verify"
- "traefik.http.middlewares.auth-check.forwardauth.trustForwardHeader=true"
- "traefik.http.middlewares.auth-check.forwardauth.authResponseHeaders=X-Auth-User,X-Auth-Name,X-Auth-Role"
Middleware einbinden¶
Um einen Service zu schuetzen, auth-check in die Middleware-Chain aufnehmen:
labels:
- "traefik.http.routers.mein-service.middlewares=crowdsec@file,security-headers@file,rate-limit-standard@file,auth-check"
Response-Header¶
Bei erfolgreicher Authentifizierung setzt der Auth-Service folgende Header, die an das Backend weitergereicht werden:
| Header | Inhalt | Beispiel |
|---|---|---|
X-Auth-User |
E-Mail des Benutzers | admin@xynap.tech |
X-Auth-Name |
Anzeigename | Admin |
X-Auth-Role |
Benutzerrolle | admin |
Backend-Services koennen diese Header auswerten, um benutzerbasierte Logik umzusetzen.
Cookie-Details¶
| Eigenschaft | Wert |
|---|---|
| Name | __xynap_auth |
| Domain | .xynap.tech |
| Path | / |
| Secure | true (nur HTTPS) |
| HttpOnly | true (kein JavaScript-Zugriff) |
| SameSite | Lax |
| Max-Age | 86400 Sekunden (24 Stunden) |
Cookie-Domain beachten
Der Cookie gilt nur fuer *.xynap.tech. Dienste unter anderen Domains (z.B. xynap.cloud, xynap.eu) koennen den Cookie nicht lesen und muessen die Route-Protection in der SQLite-DB nutzen, um bei /verify als geschuetzt erkannt zu werden. Der Login-Redirect funktioniert, aber der Cookie wird nach dem Login nur fuer .xynap.tech gesetzt — der Benutzer wird bei Diensten unter anderen Domains erneut zum Login weitergeleitet.
Endpoints¶
| Pfad | Methode | Beschreibung |
|---|---|---|
/verify |
GET | ForwardAuth-Endpoint (Traefik ruft diesen auf) |
/login |
GET/POST | Login-Seite und Formular-Verarbeitung |
/register |
GET/POST | Registrierungs-Seite |
/logout |
GET | Session beenden, Cookie loeschen |
/admin |
GET/POST | Admin-Panel (nur role=admin) |
Deployment¶
Container-Konfiguration¶
Der Auth-Service laeuft als Docker-Container im xynap-Stack:
# Container-Status pruefen
sudo docker ps --filter "name=auth-service"
# Logs anzeigen
sudo docker compose -f /etc/xynap/stack/docker-compose.yml logs -f auth-service
# Neustart
sudo docker compose -f /etc/xynap/stack/docker-compose.yml restart auth-service
# Rebuild (nach Code-Aenderungen)
sudo docker compose -f /etc/xynap/stack/docker-compose.yml up -d --build auth-service
Umgebungsvariablen¶
| Variable | Default | Beschreibung |
|---|---|---|
AUTH_COOKIE_DOMAIN |
.xynap.tech |
Cookie-Domain |
AUTH_SESSION_TTL |
86400 |
Session-Dauer in Sekunden |
AUTH_DB_PATH |
/data/auth.db |
Pfad zur SQLite-Datenbank |
AUTH_FIRST_USER_ADMIN |
true |
Erster User wird Admin |
Datenbank-Zugriff (Debugging)¶
Da der Container kein sqlite3 CLI hat, Zugriff via PHP:
# Alle Benutzer auflisten
sudo docker exec auth-service php -r "
\$db = new PDO('sqlite:/data/auth.db');
foreach(\$db->query('SELECT id, email, status, role, last_login FROM users') as \$r)
echo implode(' | ', \$r) . PHP_EOL;
"
# Alle geschuetzten Routen anzeigen
sudo docker exec auth-service php -r "
\$db = new PDO('sqlite:/data/auth.db');
foreach(\$db->query('SELECT host, path, required_role, enabled FROM protected_routes ORDER BY host') as \$r)
echo implode(' | ', \$r) . PHP_EOL;
"
# Aktive Sessions zaehlen
sudo docker exec auth-service php -r "
\$db = new PDO('sqlite:/data/auth.db');
echo \$db->query(\"SELECT COUNT(*) FROM sessions WHERE expires_at > datetime('now')\")->fetchColumn() . ' aktive Sessions' . PHP_EOL;
"
Troubleshooting¶
Login-Redirect-Schleife
Symptom: Nach Login wird man sofort wieder zum Login weitergeleitet.
Ursachen:
- Cookie-Domain stimmt nicht: Dienst laeuft nicht unter
*.xynap.tech - Session abgelaufen: TTL pruefen (
AUTH_SESSION_TTL) - HTTPS-Problem: Cookie ist
Secure=true, funktioniert nur ueber HTTPS
Diagnose:
403 Forbidden trotz Login
Ursache: Die Route erfordert admin, der Benutzer hat aber nur user.
Loesung: Route im Admin-Panel auf user umstellen oder dem Benutzer die Admin-Rolle zuweisen.
Dienst ist oeffentlich obwohl er geschuetzt sein sollte
Checkliste:
- Hat der Dienst
auth-checkin seiner Traefik-Middleware-Chain? - Existiert eine aktive Route in
protected_routesfuer die Domain? - Ist die Route
enabled = 1?
Wenn nur die Traefik-Middleware fehlt, wird /verify zwar nie aufgerufen — aber wenn nur die DB-Route fehlt, gibt /verify automatisch 200 OK zurueck (durchlassen).
Beide muessen konfiguriert sein: Traefik-Middleware und DB-Route.
Rate-Limiting greift zu frueh
Symptom: Benutzer wird nach wenigen Versuchen gesperrt.
Ursache: Mehrere Benutzer teilen sich eine oeffentliche IP (NAT/VPN).
Loesung: Rate-Limit-Einstellungen in config.php anpassen: