Authentifizierung
Zwei Wege führen hinein. Für einen Menschen im Browser das Zugangs-Token, für ein Programm der API-Schlüssel.
Anmelden
curl -X POST https://zeit.example.de/api/v1/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@example.de","password":"…"}'
Die Antwort enthält accessToken und expiresIn. Das Erneuerungs-Token steht nicht darin — es kommt als Cookie.
Ist dieselbe E-Mail in mehreren Mandanten vergeben, wird das Passwort gegen alle Kandidaten geprüft und nur angemeldet, wenn genau einer passt. Passen mehrere, muss tenantSlug mitgegeben werden. Über nicht passende Konten wird dabei nichts preisgegeben.
Nach fünf Fehlversuchen wird das Konto für fünfzehn Minuten gesperrt.
Das Zugangs-Token benutzen
curl https://zeit.example.de/api/v1/time-entries \
-H "Authorization: Bearer $TOKEN"
Es gilt 900 Sekunden (einstellbar über JWT_ACCESS_TTL). Die Rechte werden bei jeder Anfrage aus den Rollen des Benutzers aufgelöst; ein gesperrtes oder gelöschtes Konto kommt nicht durch, auch wenn sein Token noch gültig wäre.
Das Erneuerungs-Cookie
Es heißt wt_refresh und trägt httpOnly, SameSite=Strict und — im Produktivbetrieb — secure. Gültig ist es 30 Tage (JWT_REFRESH_TTL).
Warum ein Cookie und nicht der Speicher des Browsers. Zuvor lag es wie das Zugangs-Token im localStorage. Jede Cross-Site-Scripting-Lücke wäre damit sofort eine Kontoübernahme gewesen, und zwar eine dauerhafte: dreißig Tage lang. Als httpOnly-Cookie ist es für Skripte unerreichbar; SameSite=Strict verhindert, dass es bei fremden Anfragen mitgeschickt wird, und macht damit zugleich ein CSRF-Token entbehrlich.
Daraus folgt: Oberfläche und API müssen unter derselben Herkunft laufen — an eine fremde schickt der Browser das Cookie gar nicht erst.
Erneuern
curl -X POST https://zeit.example.de/api/v1/auth/refresh \
-b cookies.txt -c cookies.txt
Das Cookie ist der Regelfall; ein im Rumpf mitgeschicktes refreshToken bleibt zulässig, damit bestehende Zugänge über die API weiter funktionieren.
Bei jeder Erneuerung wird das Token rotiert: Das alte verliert seine Gültigkeit, ein neues kommt zurück. Das gerade rotierte gilt noch dreißig Sekunden weiter — lang genug für einen abgebrochenen Seitenwechsel auf einer lahmen Mobilverbindung, kurz genug, dass ein entwendetes Token daraus keinen Nutzen zieht.
Abmelden
curl -X POST https://zeit.example.de/api/v1/auth/logout -b cookies.txt -c cookies.txt
Das Cookie wird in jedem Fall gelöscht — wer sich abmeldet, soll abgemeldet sein, auch wenn das Token serverseitig schon abgelaufen war.
API-Schlüssel
Für Programme. Kein Anmelden, kein Erneuern:
curl https://zeit.example.de/api/v1/time-entries \
-H "X-API-Key: wt_1a2b3c4d.e5f6…"
Die Rechte ergeben sich aus den Geltungsbereichen des Schlüssels, nicht aus der Rolle des ausstellenden Benutzers: Ein Schlüssel soll weniger dürfen als der Mensch, der ihn erzeugt hat, nie mehr. Siehe API-Schlüssel.
Öffentlich erreichbar
Ohne Anmeldung: Registrierung, Anmeldung, Erneuerung, Abmeldung, Passwort vergessen und zurücksetzen, GET /api/v1/health, GET /api/v1/ready und GET /api/v1/license/status. Alles andere ist geschützt.
Eigene Angaben
curl https://zeit.example.de/api/v1/auth/me -H "Authorization: Bearer $TOKEN"
Liefert Benutzer, Mandant, Rollen und Rechte. PATCH /auth/me ändert die eigenen Stammdaten, PATCH /auth/me/locale die Anzeigesprache (de, en, ru, pl, tr, ro, uk, hr), POST /auth/change-password das eigene Passwort.