API und Browser
JSON-API unter /v1 mit Access- und Refresh-Tokens, dazu serverseitig gerenderte Seiten mit Session-Anmeldung. OpenAPI-Doku unter /docs.
REST-API, Anmeldung mit zweitem Faktor, Passwort-Reset per E-Mail, Kontoverwaltung und Benutzerverwaltung in einem Projekt. Die Grundlagen sind abgesichert und getestet, dein Code beginnt bei der eigentlichen Aufgabe.
content-security-policy
default-src 'self';base-uri 'none';script-src 'self';script-src-attr 'none';style-src 'self';img-src 'self';font-src 'self';connect-src 'self';manifest-src 'self';media-src 'none';worker-src 'none';form-action 'self';frame-ancestors 'none';object-src 'none'
strict-transport-security
max-age=63072000; includeSubDomains; preload
cross-origin-opener-policy
same-origin
cross-origin-embedder-policy
require-corp
cross-origin-resource-policy
same-origin
x-frame-options
DENY
x-content-type-options
nosniff
referrer-policy
no-referrer
permissions-policy
accelerometer=(), camera=(), display-capture=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=(), browsing-topics=()
cache-control
no-store
Bevor dein Code eine Anfrage sieht, läuft sie durch sieben Stationen. Scroll mit.
Jede Anfrage bekommt eine ID, die in jedem Log-Eintrag und auf Fehlerseiten auftaucht. Was größer als 100 KB ist, lehnt der Server ab, bevor er es liest.
X-Request-Id: 7c1e…
Content Security Policy ohne Inline-Skripte, HSTS, COOP, COEP und eine Permissions-Policy, die Kamera, Mikrofon und Standort sperrt.
Content-Security-Policy: default-src 'self'
300 Anfragen pro 15 Minuten und IP, bei Anmeldung und Passwortformularen 10 Fehlversuche. Mit RATE_LIMIT_STORE=database teilen sich mehrere Instanzen die Zähler.
RateLimit-Policy: 300;w=900
Formulare tragen ein CSRF-Token, das bei jeder Ausgabe neu maskiert wird. Posts von fremden Seiten scheitern schon an der Fetch-Metadata-Prüfung.
Sec-Fetch-Site: same-origin
Joi prüft jedes Feld gegen ein Schema und lehnt unbekannte Felder ab. MongoDB-Operatoren und Prototype-Schlüssel werden vorher entfernt.
400 "email" must be a valid email
Session-Cookie oder JWT, die Rolle kommt aus der Datenbank, auf Wunsch mit zweitem Faktor. Nach einer Passwortänderung sind alte Tokens und Sessions ungültig.
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9…
Fehler verraten keine Interna, nur eine Fehler-ID. Laufzeit und Status landen als Metrik für Prometheus.
200 OK
JSON-API unter /v1 mit Access- und Refresh-Tokens, dazu serverseitig gerenderte Seiten mit Session-Anmeldung. OpenAPI-Doku unter /docs.
Registrierung, E-Mail-Bestätigung, Passwort vergessen, Zwei-Faktor mit Authenticator-App und Wiederherstellungscodes.
Profil, Passwort, angemeldete Geräte, Aktivitätsprotokoll, Datenexport und Löschung, wie es die DSGVO verlangt.
Benutzer suchen, Rollen vergeben und Konten löschen, im Browser und über die API mit denselben Rechten.
Oberfläche und E-Mails auf Deutsch und Englisch. Weitere Sprachen sind eine Datei mehr.
Docker, Health-Checks, Prometheus-Metriken, strukturierte Logs mit Request-ID und ein Lasttest für jeden Endpunkt.
Node.js 22 reicht. Die Daten landen in SQLite, bis DATABASE_URL auf MongoDB, PostgreSQL, MySQL oder einen anderen Server zeigt. Die Einrichtung erzeugt eine .env mit zufälligen Schlüsseln.
npm run setup.env mit eigenen Schlüsseln anlegennpm run create-adminErstes Administratorkonto erstellennpm run devServer mit Neustart bei Änderungen starten