Ein JWT ist unterschrieben, nicht verschlüsselt
Inhalt
Ein JSON Web Token sieht verschlüsselt aus. Es ist eine lange Zeichenfolge ohne lesbare Wörter, es steht in einem Authorization-Header, und es wird wie ein Geheimnis behandelt. Was es tatsächlich ist: zwei JSON-Objekte in Base64, dazu eine Signatur – und Base64 ist eine Kodierung, kein Schloss.
Die Folge ist kurz. Alles im Rumpf liest jeder, der das Token hat: der Browser, an den es ging, der Proxy, durch den es lief, die Protokolldatei, die die Adresse festhielt, und das Ticket, in das es jemand hineinkopiert hat. Das ist kein Mangel, sondern die Bauart des Formats. Zum Problem wird es erst, wenn der Rumpf geschrieben wird, als läse niemand mit.

Die drei Teile und was jeder leistet
Ein Token besteht aus drei durch Punkte getrennten Abschnitten. Der erste nennt das Verfahren und oft den verwendeten Schlüssel. Der zweite trägt die Ansprüche – über wen das Token spricht, was es erlaubt, wie lange es gilt. Der dritte ist die Signatur über die ersten beiden.
Allein der dritte schützt etwas, und er schützt genau eine Eigenschaft: dass die ersten beiden seit dem Unterschreiben unverändert sind. Er verbirgt sie nicht, und es braucht ihn nicht zu verstehen, um sie zu lesen. Ein Token in einen beliebigen Decoder eingefügt gibt seinen Inhalt sofort preis.
Was im Rumpf nichts zu suchen hat
Jedes Feld im Rumpf ist ein Feld, das dem Besitzer des Tokens ausgehändigt wird. Eine E-Mail-Adresse, ein vollständiger Name, ein Geburtsdatum – damit wird aus einem Ausweis eine Datenweitergabe, und sie landet an Orten, die Ausweise erreichen und personenbezogene Daten nicht sollten: Proxy-Protokolle, Browserspeicher, Fehlerberichte.
Die zweite Sorte ist innere Struktur. Eine Rollenliste wie billing_admin oder eine Mandantennummer verrät, was hinter der Schnittstelle existiert und wie es geordnet ist – genau das, was ein Angreifer zuerst aufzählt. Ein knapper Betreff und ein Bereich genügen meist; der Rest gehört in die Abfrage, die der Server ohnehin macht.
Die dritte ist alles, was nur für den Aussteller gedacht war. Tokens werden in Tickets kopiert, und ein Rumpf mit einer internen Kundennummer wandert mit.
exp ist das Einzige, das ein Token beendet
Ein Token gilt, weil es das von sich behauptet. Es gibt keinen Zustand auf dem Server, der es beendet: einmal ausgestellt, wirkt es, bis der Anspruch exp verstrichen ist, und ein Token ohne exp wirkt für immer.
Deshalb macht das Abmelden nichts ungültig. Der Client verwirft das Token, das Token bleibt gültig, und wer eine Kopie behalten hat, behält den Zugang. Ein Token vor seiner Zeit zu beenden verlangt eine Sperrliste, die jeder Dienst prüft – womit genau der gemeinsame Zustand zurückkommt, den das Format vermeiden sollte.
Die brauchbare Anordnung ist ein kurzlebiges Zugriffstoken und ein zentral widerrufbares Auffrischungstoken. Minuten für das erste und für das zweite eine Laufzeit, die tatsächlich jemand im Blick hat: ein Auffrischungstoken mit einem Jahr Gültigkeit ist ein Passwort mit Zwischenschritten.
Wo Lesen mit Prüfen verwechselt wird
Ein Token zu lesen und ihm zu trauen sind verschiedene Vorgänge, und der Unterschied ist ein Bibliotheksaufruf. Ein Decoder zeigt die Ansprüche jedes Tokens, auch eines, das vor drei Sekunden von Hand geschrieben wurde. Die Prüfung rechnet die Signatur gegen einen Schlüssel nach, und erst sie beantwortet, ob die Ansprüche von jemandem stammen, der sie ausstellen durfte.
Aus der Verwechslung folgen zwei Fehlerbilder. Das erste ist alg: none – ein Token, das erklärt, es habe keine Signatur. Ein Prüfer, der das Verfahren aus dem Token liest und sich daran hält, nimmt alles an; das Verfahren muss die Anwendung festlegen und nicht das Token. Das zweite ist derselbe Fehler mit einem Schlüssel: ein Dienst, der RS256 erwartet und ein HS256-Token bekommt, lässt sich dazu bringen, es mit dem öffentlichen Schlüssel als gemeinsamem Geheimnis zu prüfen – und der öffentliche Schlüssel ist öffentlich.
Was in jedes Token gehört
Auf drei Ansprüche lohnt es zu bestehen. exp, weil ohne ihn nichts endet. iss, damit ein Dienst erkennt, von welchem Aussteller ein Token kommt, statt alles anzunehmen, was sich prüfen lässt. Und aud – jener Anspruch, der verhindert, dass ein für die Berichtsschnittstelle ausgestelltes Token von der Abrechnungsschnittstelle angenommen wird; eine Prüfung, die sich leicht auslassen und schwer vermissen lässt.
Für nichts davon braucht es Werkzeug im großen Stil. Ein Token an seinen Punkten zu teilen und den mittleren Teil zu entschlüsseln dauert Sekunden und beantwortet die Fragen, die sonst durch Annahme beantwortet werden: wie lange das gilt, was es erlaubt und was es jedem verrät, der es liest.