Zum Inhalt

Tokens & API-Keys

Drei Token-Klassen, drei Speicher-Formen.

User-JWT

Standard-Login-Token nach erfolgreichem Login + 2FA.

Feld Wert
Format RS256-signierter JWT
Claims sub (User-ID), tenant_id, tenant_scope, permissions[], exp
Lebensdauer Default 24 h, refreshbar
Secret SECRET_KEY (RSA-Privatekey, eigentlich HMAC-Symmetric in default)
Speicherung im Browser (HttpOnly Cookie + localStorage), in der Mobile-App AsyncStorage

Refresh

Vor Ablauf wird automatisch ein neuer Token geholt — solange der Refresh-Token gültig ist (Default 7 Tage). Refresh-Token wird beim Logout invalidiert.

Invalidierung

Es gibt keinen serverseitigen JWT-Blocklist (kostet zu viel). Bei Logout: Frontend wirft den Token weg. Bei Account-Sperrung: users.active = false führt dazu, dass eine ResourceLookup auf den User in zukünftigen Requests fehlschlägt — der Token verfällt effektiv beim nächsten Request.

JWT-Token im Browser sind so sicher wie der Browser

XSS-Schutz ist Pflicht: CSP-Header strikt, keine User-Inhalte als HTML einbetten ohne Escape, Wiki-Markdown wird sanitized. Alles im Frontend.

Agent-Token

Für Agents auf überwachten Maschinen.

Feld Wert
Format vesana_agent_<32 url-safe Base64>
Speicherung Server SHA256-Hash in agent_tokens.token_hash
Speicherung Agent Klartext in /etc/vesana-agent/config.yaml (chmod 600)
Lebensdauer unbegrenzt
Bindung 1:1 an einen Host
Auth-Header X-Agent-Token: vesana_agent_xxxx

Generierung

Nur in der UI auf der Host-Detail-Seite. Klartext wird genau einmal angezeigt. Backend speichert nur den Hash.

Rotation

Host-Detail-Seite → Token widerrufen → neuer Token. Auf der Maschine muss die Config angepasst werden, sonst meldet sich der Agent mit 401.

Alternativ: Re-Install via One-Command-Installer mit neuem Token.

Collector-API-Key

Für Collectors im Kundennetz.

Feld Wert
Format vesana_<custom-prefix>_<32 Bytes>
Speicherung Server SHA256-Hash in api_keys.key_hash
Speicherung Collector Klartext in /etc/vesana/collector.env
Auth-Header X-API-Key: vesana_xxxxx
Bindung 1:1 an einen Collector

key_prefix wird seit v0.x für neue Keys nicht mehr geschrieben (nur leerer String). Lookup im Receiver erfolgt ausschließlich über key_hash.

Personal-Access-Tokens

Über /profile → API-Keys können auch User persönliche API-Keys generieren — für CLI-Scripts, eigene Integrationen.

Feld Wert
Scope read-only / read-write
Ablauf Pflicht (max 1 Jahr)
Tenant-Scope wie der User

Nutzung: Authorization: Bearer <pat>.

Rotation: alten Key widerrufen → neuen erzeugen. Empfehlung: Keys mindestens jährlich tauschen.

Hashing

Alle Tokens sind als SHA256-Hash in der DB. Vorteil:

  • DB-Leak verrät keinen funktionierenden Token
  • Vergleich auch mit gehashten Werten ist O(1) bei Index

Wir nutzen kein Salt, weil Tokens selbst zufällig genug sind (32 Bytes Entropie >> brute-forcebar).

TLS-Pflicht

Tokens werden ausschließlich über HTTPS akzeptiert. Bei HTTP-Requests antwortet der Server mit Redirect (Frontend) oder 426 Upgrade-Required (API). Self-Signed-Certs sind ok für Tests, in Production: Let's-Encrypt oder eigenes Cert.

Audit

Token-Operationen (Create / Revoke) landen im Audit-Log mit action = agent_token.create / .revoke / api_key.create / .revoke.

Diebstahl-Erkennung

Symptom Mögliche Ursache
Agent-Token meldet sich von zwei IPs Token kompromittiert oder Klon
API-Key wird plötzlich für ungewöhnliche Endpoints genutzt PAT vielleicht in Repo gepushed
User-JWT ist auf zwei Geräten aktiv normal — kein Problem

Für Agent- und Collector-Tokens: Multi-IP-Heuristik in der UI (Spalte „Letzte IP") hilft, Anomalien zu sehen.

Anschluss