Ist JWT sicher oder verwundbar?
Von Evren BalVeröffentlicht Aktualisiert · 5 Min. Lesezeit

Seite kopieren
💡 Kurzfassung:
- Ein JWT kann ungültig gemacht werden, aber Sperrlisten, Introspektion oder Sitzungsstatusprüfungen nehmen einem zustandslosen Token einen Teil seiner Einfachheit.
- Eine Signatur schützt Integrität, nicht Vertraulichkeit oder die aktuelle Berechtigung. Die Anwendung muss das erwartete Token prüfen und den Zugriff weiterhin entscheiden.
- Kurzlebige Access-Tokens und geschützte Refresh-Tokens können passen. Hängt jede Anfrage ohnehin von serverseitigem Sitzungsstatus ab, ist ein herkömmliches Sitzungs-Cookie oft die einfachere Lösung.
JWT steht für JSON Web Token. Dieser Beitrag erklärt nicht, wie JWT Sicherheit erhöht, sondern wie ein unvorsichtiger Einsatz sie schwächen kann.
JWT ist ein offener Standard für Access-Tokens. Der Server erstellt ein Token und sendet es oft an den Client. Ein integritätsgeschütztes JWT kann ein gemeinsames Secret mit HMAC oder eine asymmetrische Signatur wie RSA oder ECDSA nutzen. Im asymmetrischen Fall signiert der Aussteller mit einem privaten Schlüssel, der Empfänger prüft mit einem öffentlichen. Ein JWT ist also nicht immer „mit dem privaten Schlüssel des Servers signiert“.
Wenn die Signatur gültig ist, weiß der Empfänger, dass keine unbefugte Person das Token verändert hat und dass es von einem Inhaber des passenden Schlüssels stammt. Ein signiertes JWT ist dadurch nicht verschlüsselt. Wer es lesen kann, kann normalerweise auch seine Nutzdaten lesen; Geheimnisse gehören nicht hinein. Eine gültige Signatur sagt ebenso wenig aus, ob ein Konto noch aktiv ist, seine Berechtigungen unverändert sind oder der Nutzer diese Ressource in dieser Anfrage nutzen darf. Das sind weiter Anwendungsentscheidungen.
Was JWT nicht ist
JWT ist kein magisches Sicherheitsmittel. Signaturprüfung ersetzt keine Autorisierung bei einer kritischen Aktion.
„Die Informationen im JWT sind signiert und zuverlässig. Im Token steht der Benutzername
evrenbal, der Server hat ihn bei der Anmeldung geprüft. Was kann schon schiefgehen?“
Stellen Sie sich vor, einem Nutzer wird sein Passwort gestohlen oder er hat sich an einem öffentlichen Computer nicht abgemeldet. Er ändert sein Passwort und nimmt an, das Problem sei gelöst. Prüft das Backend aber nur Struktur und Ablaufzeit des Tokens, bleibt das aktive Token auf diesem Computer gültig, bis es abläuft oder die Anwendung Widerrufszustand prüft.
Zwei Prüfungen sind zu unterscheiden: erstens die kryptografische Validierung, zweitens die Entscheidung der Anwendung über diese Anfrage. Lassen Sie nicht den Token-Header Algorithmus oder Schlüssel wählen. Konfigurieren Sie erlaubte Algorithmen und binden Sie jeden Schlüssel an seinen vorgesehenen Algorithmus. Prüfen Sie kryptografische Operationen, erwarteten Aussteller, Zielgruppe, Zweck und gegebenenfalls Tokentyp. Prüfen Sie anschließend Claims im Anwendungskontext und treffen Sie die aktuelle Autorisierungsentscheidung. RFC 8725 beschreibt diese Praktiken, einschließlich Schutz gegen alg: "none" und Schlüsselverwechslung.
Ablaufzeit und Refresh-Token-Dilemma
„Dann setze ich eben eine sehr kurze Ablaufzeit für das JWT.“
Ein kurzlebiges Access-Token mit länger lebendem Refresh-Token kann angemessen sein. Die Ausgabe eines Refresh-Tokens ist jedoch eine Risikoentscheidung, kein Standard. Es erlaubt, ein gestohlenes Access-Token rasch wirkungslos werden zu lassen, ohne eine erneute Anmeldung zu erzwingen.
Um das langlebige Refresh-Token zu prüfen und rasch widerrufen zu können, braucht das Autorisierungssystem aber Zustand in einer Datenbank oder einem Cache wie Redis. Stimmt ein eingehendes Refresh-Token mit dem gespeicherten überein, kann ein neues Access-Token entstehen. Bei Passwortänderung können aktive Refresh-Tokens gelöscht oder widerrufen und Sitzungen ungültig gemacht werden. Für öffentliche Clients empfiehlt die aktuelle OAuth-Leitlinie Refresh-Token-Rotation oder absendergebundene Refresh-Tokens sowie Ablauf und Widerruf. RFC 9700 erläutert die risikobasierte Ausgabe und beide Ansätze zur Erkennung von Wiederverwendung.
Das löst nicht alles. Während ein gestohlenes kurzlebiges Access-Token aktiv ist, bleibt seine Übernahme unentdeckt. Wird die Lebensdauer auf ein oder zwei Minuten verkürzt, erneuert der Client häufiger. Das kann richtig sein. Prüft aber jede Anfrage zusätzlich Datenbank oder Cache, ist der zustandslose Vorteil deutlich kleiner.
Sicherere Muster
Muster 1: Passwortalter prüfen
Vergleichen Sie beim Prüfen eines JWT dessen Erstellungszeit (iat) mit last_password_change des Nutzers in einem schnellen Cache wie Redis. Wurde das Passwort nach Ausstellung geändert, verweigern Sie die Anfrage.
- Ergebnis: Bei Passwortänderung wird der Nutzer sofort auf allen Geräten abgemeldet; das betrifft auch seine legitimen Sitzungen.
Muster 2: Sitzungen pro Anmeldung nachverfolgen
Erzeugen Sie bei jeder Anmeldung eine eindeutige Sitzungs-ID, etwa "ABCDE", speichern Sie sie in Redis und betten Sie sie in die JWT-Nutzdaten ein. Vergleichen Sie sie bei jeder Anfrage mit den aktiven Sitzungen. IP-Adresse, User Agent und Betriebssystemdetails können Nutzern helfen, eine Sitzung zu erkennen oder eine ungewöhnliche Änderung zu markieren. Sie sind unterstützende Signale, keine kryptografische Gerätebindung oder verlässlicher Identitätsnachweis.
- Ergebnis: Bei einer Passwortänderung können alle aktiven Sitzungen aus Redis entfernt und damit alle ausgegebenen JWTs sofort ungültig werden. Eine Seite „Geräte“ kann einzelne Sitzungen widerrufbar machen.
Browser-Speicher ist eine eigene Entscheidung
Ein JWT in localStorage ist für JavaScript derselben Origin verfügbar. Ein XSS-Fehler kann das Token daher preisgeben. HttpOnly-, Secure- und passend gewählte SameSite-Cookies oder eine BFF-Architektur für den Browser können dieses Risiko senken. Sie lassen den Browser Zugangsdaten aber auch automatisch senden; CSRF-Schutz und der übrige Sitzungsentwurf bleiben nötig. SameSite ist Defense in Depth, nicht die gesamte CSRF-Strategie. Das OWASP Cheat Sheet für Sitzungsverwaltung erläutert diese Grenze.
Ist JWT überhaupt nötig?
Speichern Sie Sitzungs-IDs wie ABCDE in einem Cache, fragen ihn bei jeder Anfrage ab und verwalten Sitzungslebensdauern serverseitig, haben Sie ein zustandsbehaftetes System gebaut.
Warum dann den Aufwand großer Base64-codierter JWT-Nutzdaten und JWT-Bibliotheken tragen? In den meisten klassischen monolithischen oder Single-Domain-Webanwendungen ist ein schlankes, sicheres Cookie mit Sitzungs-ID oft die einfachere, sicherere und bewährte Wahl.
JWT ist nützlich, aber nicht automatisch der beste Standard. Fragen Sie vor der Integration, ob es für diesen Client, diese Vertrauensgrenze und diesen Widerrufsbedarf wirklich besser ist als ein herkömmliches Sitzungs-Cookie.
Das ist auch eine wichtige Leitplanke, wenn ein KI-Agent beim Bau einer API hilft. JWT sollte nicht durch einen Prompt zum Standard werden. Der Agent sollte Clienttyp, Widerrufsbedarf, Vertrauensgrenze und den Grund erklären, weshalb JWT einer Serversitzung vorzuziehen ist. Wie diese Entscheidungen erhalten bleiben, behandle ich in KI-gestützter REST-API-Entwicklung.
Wenn dieser Artikel hilfreich war
Ein Link von einer passenden Seite Ihrer Website oder das Teilen in sozialen Medien hilft diesem Artikel, mehr Menschen zu erreichen. Vielen Dank.
Hinweise zu Links und Marke →Über diesen Artikel
Änderungsverlauf
- · Inhaltliche Aktualisierung — Bereinigte Überbleibsel aus der türkisch-englischen Übersetzung, ergänzte verbreitete JWT-Fehlerbilder und korrigierte Variablen- und Verbverwendung.
- · Inhaltliche Aktualisierung — Aktualisierte Hinweise zu Signierung, Validierung, Refresh-Tokens, Widerruf, Browser-Speicher und Gerätesignalen; ergänzte den Entscheidungslink zur API-Entwicklung.
