- JWT steht für JSON Web Tokens und ist ein Standard für signierte Tokens.
- Ein JWT besteht aus Header, Payload und Signatur oder Message Authentication Code.
- Jeder mit dem Verifizierungsschlüssel kann die Echtheit der Payload überprüfen.
Übliche Verwendungsmuster von JWT
- JWT enthält Informationen wie Aussteller, Empfänger, Betreff und Ablaufzeit.
- Nach der Prüfung der Echtheit des Tokens kontrolliert der Empfänger, ob die Ablaufzeit noch nicht überschritten ist, und betrachtet den Betreff als authentifizierten Benutzer.
Vorteile von JWT
- Der wichtigste Vorteil von JWT ist, dass der Empfänger die Echtheit des Tokens überprüfen kann, ohne sich mit der Benutzerdatenbank zu verbinden.
- In großen Installationsumgebungen kann der Authentifizierungsdienst der einzige Dienst sein, der auf die zentrale Benutzerdatenbank zugreift.
Probleme mit Logout und Sitzungsinvalidierung
- Die Lebensdauer von Authentifizierungs-Tokens sollte kurz sein, zum Beispiel maximal 5 Minuten.
- Der Client erhält zusätzlich ein Refresh-Token, mit dem neue Authentifizierungs-Tokens angefordert werden können.
- Das Refresh-Token übernimmt faktisch die Rolle des eigentlichen Session-Tokens.
Fälle, in denen JWT nicht nötig ist
- Um Logout zu implementieren, muss eine Allowlist gültiger JWT oder eine Denylist widerrufener JWT gepflegt werden.
- Um Benutzer zu sperren, muss in der Datenbank ein Flag wie "Benutzer aktiv" geprüft werden.
- Es werden zusätzliche Beziehungen zwischen dem Benutzerobjekt und anderen Objekten benötigt.
- Es werden datenbankbezogene Operationen durchgeführt.
Fazit
- Wenn auch nur eine dieser Bedingungen zutrifft, wird JWT nicht benötigt.
- Es ist besser, ein gewöhnliches undurchsichtiges Session-Token zu verwenden und in der Datenbank zu speichern.
- So lassen sich die Nachteile von JWT vermeiden und die Komplexität reduzieren.
Meinung von GN⁺
- JWT eignet sich für große Dienste, kann aber für die meisten kleineren Dienste unnötige Komplexität verursachen.
- Gewöhnliche Mechanismen zur Sitzungsverwaltung reichen für die meisten Webanwendungen aus.
- Mit JWT kann es schwierig sein, Funktionen wie Logout und Sitzungsinvalidierung umzusetzen.
- Um die Vorteile von JWT sinnvoll zu nutzen, sollten Größe und Anforderungen des Dienstes sorgfältig abgewogen werden.
- Als weitere Alternative kommen Authentifizierungs-Frameworks wie OAuth2 infrage.
8 Kommentare
Wenn eine Authentifizierung für verschiedene Clients erforderlich ist, brachte der Einsatz von JWT viele Vorteile.
Da Skalierbarkeit und Sicherheit jedoch immer in unterschiedliche Richtungen zielen, halte ich es für besser, eine andere Methode zu verwenden, wenn Sicherheit besonders wichtig ist.
Ich persönlich finde, JWT-Token sollte man eher dann verwenden, wenn man temporäre Daten, bei denen es kein Problem ist, wenn sie offengelegt werden, über den Browser zwischen Systemen austauscht.
Für Token, die personenbezogene Daten enthalten und zur Authentifizierung verwendet werden, halte ich opaque Token für die bessere Wahl..
Aus meiner persönlichen Erfahrung hatte JWT Vorteile, wenn man ein MVP baut.
Wenn es sich zum Beispiel um einen Service handelt, den man allein entwickelt und betreibt, dachte ich, dass sich dadurch die Planungskosten bei plötzlich aufkommenden Anforderungen senken lassen. Da sich die anfänglich aufgesetzten Datenbeziehungen nach ein oder zwei Monaten oft komplett verändern, konnte man in einem Zustand, in dem die Planung noch nicht klar war, zumindest bei allem rund um
auth, Features lieber mit optionalen Feldern in der JWT-Payload umsetzen. So konnte man, auch ohne dass das Planungsteam die Arbeit zur Domänentrennung und Service-Aufteilung erledigt hatte, zunächst im monolithischen Service nur die Domäne leicht trennbar implementieren und danach einen Markttest durchführen. (Und später dann den nächsten Schritt zur Aufteilung des Services gehen. Oder es wieder verwerfen.)Trotzdem hängt das wahrscheinlich auch von den Domänen des jeweiligen Services ab. Das betreffende Projekt war selbst unter Echtzeitdiensten eines mit hoher Kopplung an Third-Party-Dienste, daher habe ich es wohl auch mit dem Gedanken so umgesetzt, dass bei einer schnellen Implementierung enorme Mengen an Dokumenten/Rows in der Datenbank anfallen könnten und dadurch die Betriebskosten steigen würden.
Wenn der Fokus allerdings darauf liegt, schnell etwas zu bauen, halte ich ein Session-Modell für besser. (Am Anfang ist die Kopplung zwischen mehreren Services noch nicht so stark, daher ist es auch einfacher, alles umzuwerfen und neu zu bauen.) Auch die Übergabekosten sind geringer, wenn später weitere Teammitglieder dazukommen.
Damals habe ich mir darüber zwar eine Zeit lang auf die eine oder andere Weise Gedanken gemacht, aber rückblickend glaube ich, dass die Auswirkungen auf das Projekt wohl nicht gravierend gewesen wären, egal für welche Umsetzung ich mich entschieden hätte.
Ich persönlich denke, dass man bei der Nutzung eines API Gateway Vorteile hat, wenn man Auth mit JWT implementiert. Mich würde aber interessieren, welche Vorteile JWT bei einem Service im kleinen Maßstab hat. Meinen Sie Fälle, in denen die in JWT enthaltenen Benutzerinformationen häufig geändert werden?
Im Großen und Ganzen ist es so, wie Sie gesagt haben. Es war nur eher so, dass sich nicht das Modeling des Users selbst so änderte, dass Informationen häufig angepasst werden mussten, sondern dass optionale Zusatzinformationen hinzukamen, wenn neue Features ergänzt wurden oder ein neuer Service durch die Nutzung von Third-Party-Tools zusätzliche Informationen benötigte. (Etwas weiter gedacht ging es auch um die leicht heikle Frage, ob man
authpotenziell mit etwas wie einem API Gateway verwaltungstechnisch abtrennen sollte oder nicht, beziehungsweise ob es einen Server geben sollte, der eine vergleichbare Rolle übernimmt...)Um ein etwas konkreteres Beispiel zu geben: Es gab eine Situation, in der der Service A der Hauptdienst war. Da es sich noch um ein MVP handelte, enthielt die User-Tabelle nur Zahlungsinformationen und die Information, ob es sich um einen verifizierten User handelt. Dann kam die Anforderung auf, zusätzlich die Services B und C bereitzustellen, die jeweils unterschiedliche Authentifizierungsinformationen pro User benötigen, damit sie genutzt werden können. Dabei war noch nicht einmal entschieden, ob B überhaupt in den Service A integriert wird, und bei C wollte man nur leichtgewichtig testen, weil der Service auch wieder verschwinden könnte. (Und eine Plan-Management-Funktion hätte man ohnehin besser gleich ergänzt, um späteren Ärger zu vermeiden.) Hinzu kam, dass man B und C zunächst gemeinsam auf der bestehenden Web-Service-Seite von A nutzbar machen wollte. Aufgrund der Eigenschaften des bereits laufenden Dienstes waren mehrere Tabellenabfragen (oder Collection-Abfragen) praktisch unvermeidlich, solange noch keine Plan-Management-Tabelle (oder allgemeine Auth-bezogene Tabelle) erstellt und die Domain-Beziehungen pro Service modelliert und gemappt waren. Wenn es in dem Projekt jemanden gegeben hätte, der die Dinge sauber ordnet, hätte man wohl ein paar Meetings gemacht und klar herausgearbeitet, welches Problem eigentlich gelöst werden soll und welche Features wirklich gewünscht sind, aber das war nicht garantiert. Außerdem war unklar, wann man solche technischen Schulden überhaupt würde abbauen können. Und weil sich schon vor dem Launch von Service A abgezeichnet hatte, dass so etwas passieren könnte, dachte ich bei der ersten Architektur daran, beim Auth möglichst sowohl die Abfragekosten als auch die späteren Wartungskosten gering zu halten, und habe mich deshalb für JWT entschieden. Darüber hinaus gab es wohl auch viele kleinere, ähnliche Fälle.
Wie ich aber schon im letzten Teil des Kommentars erwähnt habe, hätte die konkrete Implementierung vermutlich ohnehin keinen besonders großen Einfluss auf das Projekt insgesamt gehabt. Auch wenn es per Session umgesetzt worden wäre, hätten wir dafür wohl auf die eine oder andere Weise eine Lösung gefunden. Viel gravierender war vermutlich, dass Entwickler ständig Situationen ausgesetzt waren, in denen sie Aufgaben anderer Rollen übernehmen mussten oder die Kommunikationskosten aufbrachen.
Auch wenn es für eine monolithische Struktur geeignet sein mag, zeigen JWT und sitzungsbasierte Logik deutliche Unterschiede, sobald einzelne Services ausgegliedert werden oder man an einem Punkt der Erweiterung steht. Es geht dabei nicht nur um das Authentifizierungsverfahren; auch bei der Nutzbarkeit der internen Logik werden sich die Methoden unterscheiden, mit denen man die Quelle der Daten behandelt. Mir ist nicht ganz klar, nach welchen Kriterien man den Kontext eines kleinen Services als passend beurteilen sollte. Ob dabei vorausgesetzt wird, dass alle Services zwangsläufig klein bleiben. Oder dass große Services schwer umzusetzen sind. Dennoch denke ich, dass die Services, die wir entwickeln, zumindest in minimalem Umfang eine Struktur mitbringen sollten, die Kontexte unterstützt, deren konkrete Ausprägung wir zwar nicht kennen, die aber weiterhin nützlich sind. Die Annahme eines kleinen Services scheint nur dazu zu führen, dass er immer klein bleibt.
Hacker-News-Meinung
Zusammenfassung der Hacker-News-Kommentare