← Alle Artikel

JWT dekodieren und seine Claims lesen

Ein JWT besteht aus drei Base64url-Sektionen. Lerne, Header und Payload in JavaScript und Python zu dekodieren — und warum ein Token zu dekodieren nicht dasselbe ist wie es zu verifizieren.

Ein JWT (JSON Web Token) besteht aus drei Base64url-kodierten Abschnitten, die durch Punkte verbunden sind. Einen Token zu dekodieren, um seine Claims zu lesen, erfordert einen einzigen Funktionsaufruf und keinen geheimen Schlüssel —— genau deshalb ist die Nutzlast eines JWT kein sicherer Ort für sensible Daten. Dieser Guide erklärt, was ein JWT ist, wie jeder Teil dekodiert wird, und den entscheidenden Unterschied zwischen Dekodieren und Verifizieren eines Tokens.

Was ist ein JWT?

Ein JWT ist ein kompakter, URL-sicherer Token zum Transport von Claims —— typischerweise Identität und Berechtigungen eines Nutzers —— zwischen Parteien. Er ist als RFC 7519 standardisiert. Ein Token sieht so aus:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0IiwibmFtZSI6IkFkYSJ9.dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk

Die beiden Punkte teilen ihn in drei Teile: Header, Payload und Signature.

Die drei Teile

  • Header —— ein kleines JSON-Objekt, das den Signaturalgorithmus beschreibt, z. B. {"alg":"HS256","typ":"JWT"}.
  • Payload —— ein JSON-Objekt mit Claims wie sub (Subject), exp (Ablauf) und beliebigen benutzerdefinierten Feldern.
  • Signature —— eine kryptographische Signatur über Header und Payload zur Erkennung von Manipulation. Nicht für Menschen lesbar und kein JSON.

Header und Payload sind Base64url-kodiertes JSON. Die Signatur wird mit JWS erzeugt (RFC 7515).

Wie man ein JWT in JavaScript dekodiert

Teilen Sie an den Punkten und dekodieren Sie die ersten beiden Teile Base64url. Beachten Sie, dass JWT Base64url verwendet (mit - und _ anstelle von + und /, ohne Padding), also vor dem Dekodieren konvertieren:

function decodeJwt(token) {
  const [headerB64, payloadB64] = token.split('.');

  const decode = (b64url) => {
    const b64 = b64url.replace(/-/g, '+').replace(/_/g, '/');
    const json = atob(b64);
    return JSON.parse(json);
  };

  return { header: decode(headerB64), payload: decode(payloadB64) };
}

Für volle Unicode-Sicherheit dekodieren Sie das Base64 in Bytes und leiten diese durch TextDecoder, anstatt nur atob zu verwenden.

Wie man ein JWT in Python dekodiert

import base64, json

def decode_jwt(token):
    header_b64, payload_b64, _sig = token.split('.')
    def decode(part):
        padded = part + '=' * (-len(part) % 4)
        return json.loads(base64.urlsafe_b64decode(padded))
    return decode(header_b64), decode(payload_b64)

Dekodieren ist nicht Verifizieren

Das ist der wichtigste Punkt zu JWTs. Jeder kann einen Token dekodieren und seine Nutzlast lesen —— kein Schlüssel nötig. Dekodieren sagt Ihnen, was der Token behauptet; es sagt Ihnen nicht, ob diese Claims vertrauenswürdig sind.

Um einem Token zu vertrauen, müssen Sie die Signatur verifizieren gegen den geheimen oder öffentlichen Schlüssel des Servers, mit einer geprüften Bibliothek —— niemals selbst implementieren:

import jwt from 'jsonwebtoken';

// Verifiziert Signatur UND prüft Ablauf; wirft, wenn ungültig
const claims = jwt.verify(token, process.env.JWT_SECRET);

// jwt.decode(token) —— verifiziert NICHT; nur zur Inspektion

Die serverseitige Verifizierung ist es, was ein JWT zu einem Credential macht. Eine dekodierte Nutzlast als vertrauenswürdig zu behandeln, ohne die Signatur zu verifizieren, ist ein klassischer Authentifizierungs-Bug.

Die Nutzlast eines JWT ist nicht verschlüsselt

Da die Nutzlast nur Base64url-kodiertes JSON ist, bietet sie null Vertraulichkeit. Es ist dasselbe Missverständnis, das in Base64 ist keine Verschlüsselung behandelt wird: die Kodierung kann jeder rückgängig machen.

Stecken Sie nie Passwörter, vollständige Kartennummern oder sensible Personendaten in eine JWT-Nutzlast. Wenn Sie wirklich einen verschlüsselten Token brauchen, verwenden Sie JWE (JSON Web Encryption, RFC 7516) —— ein separater und wesentlich weniger gebräuchlicher Standard. Und vermeiden Sie es, echte Token in unzuverlässige Online-Decoder zu kleben; siehe warum Sie sensibles JSON nicht in Online-Tools einfügen sollten.

Validierungsreihenfolge: Signatur zuerst, Claims danach

Bei der Verifizierung eines Tokens in Produktion zählt die Reihenfolge. Eine sichere Checkliste:

  1. Algorithmus-Whitelist —— alles außerhalb Ihres erwarteten Sets ablehnen (z. B. ['RS256']). Akzeptieren Sie niemals none.
  2. Signatur —— mit dem richtigen Schlüssel verifizieren (über kid in Ihrem JWKS nachschlagen).
  3. exp —— der Token darf nicht abgelaufen sein.
  4. nbf (not-before) —— darf nicht zu früh verwendet werden.
  5. iat —— Sanity-Check, dass die Ausstellung nicht absurd in der Zukunft liegt (Uhren-Drift berücksichtigen).
  6. iss —— der Issuer muss der erwarteten vertrauenswürdigen Autorität entsprechen.
  7. aud —— die Audience muss Ihren Service einschließen.

Die meisten JWT-Bibliotheken erledigen 1–4 standardmäßig und verlangen Opt-in für 6–7. Bis iss und aud geprüft sind, könnte ein für einen anderen Service in Ihrem Ökosystem gültiger Token gegen Ihren wiedergespielt werden.

Häufige Standard-Claims

ClaimBedeutung
issIssuer —— wer den Token erstellt hat
subSubject —— um wen es im Token geht (oft eine User-ID)
audAudience —— für wen der Token bestimmt ist
expExpiration —— Unix-Timestamp, nach dem der Token ungültig ist
iatIssued-at —— Unix-Timestamp der Erstellung
nbfNot-before —— der Token ist erst ab diesem Zeitpunkt gültig

Der Header kid und die Falle alg: none

Zwei Header-Felder tauchen oft genug in echten JWTs auf, dass es sich lohnt, sie auf den ersten Blick zu erkennen:

  • kid (key ID) —— ein Hinweis, der dem Verifizierer sagt, welcher Schlüssel aus einem Set (JWKS) diesen Token signiert hat. Es lebt im Header, damit der Verifizierer den richtigen Schlüssel auswählen kann, bevor er die Signatur prüft. Behandeln Sie kid als nicht vertrauenswürdige Eingabe: schlagen Sie ihn in einer festen Whitelist (oder einem abgerufenen JWKS) nach, niemals als Dateipfad, SQL-Parameter oder URL.
  • alg: "none" —— ein legaler, aber historisch gefährlicher Algorithmus, der „keine Signatur“ bedeutet. Decoder dekodieren ihn bereitwillig, und ein laxer Verifizierer kann ihn akzeptieren, was jede gefälschte Nutzlast zu einem „gültigen“ Token macht. Lehnen Sie alg: none explizit ab und konfigurieren Sie Ihre Bibliothek mit dem exakten erwarteten Algorithmus (z. B. ['RS256']), anstatt auf das zu vertrauen, was der Token-Header selbst behauptet.

Ein JWT im Browser dekodieren

Um die Claims eines Tokens schnell zu inspizieren, fügen Sie einen der Base64url-Abschnitte in den Base64-Decoder von fixjson ein —— er dekodiert lokal zum darunterliegenden JSON, ohne etwas an einen Server zu senden. Für nicht-sensible Token können Sie auch einen dedizierten Debugger verwenden, aber für alles mit echten Nutzerdaten ist ein Local-First-Tool die sichere Wahl.

Häufig gestellte Fragen

Wie dekodiere ich ein JWT?

Teilen Sie den Token an seinen Punkten und dekodieren Sie die ersten beiden Teile (Header und Payload) Base64url zu JSON. Der dritte ist die Signatur und nicht für Menschen lesbar. Zum Dekodieren ist kein Schlüssel nötig.

Ist Dekodieren eines JWT dasselbe wie Verifizieren?

Nein. Dekodieren liest nur die Claims; das kann jeder. Verifizieren prüft die Signatur gegen einen geheimen oder öffentlichen Schlüssel, um zu bestätigen, dass der Token authentisch ist und nicht manipuliert wurde. Verifizieren Sie immer auf dem Server, bevor Sie einem Token vertrauen.

Kann jeder die Daten eines JWT lesen?

Ja. Die Nutzlast ist Base64url-kodiert, nicht verschlüsselt —— sie ist Klartext für jeden mit dem Token. Speichern Sie nie Geheimnisse in einer JWT-Nutzlast. Siehe Base64 ist keine Verschlüsselung.

Was ist der Unterschied zwischen JWT, JWS und JWE?

Ein signiertes JWT verwendet JWS (RFC 7515) —— Payload lesbar, Manipulationsschutz. JWE (RFC 7516) verschlüsselt die Nutzlast für Vertraulichkeit. Die üblichen JWTs, die Sie täglich sehen, sind JWS.

Wofür wird der kid-Claim verwendet?

kid ist ein Header-Feld (kein Payload-Claim), das identifiziert, welcher Schlüssel aus dem JWKS den Token signiert hat, damit der Verifizierer den richtigen wählt. Schlagen Sie ihn gegen ein festes, von Ihnen kontrolliertes Schlüssel-Set nach —— vertrauen Sie ihm nicht als Pfad oder URL.

Warum ist alg: "none" gefährlich?

Es bedeutet „keine Signatur“. Ein laxer Verifizierer, der den vom Token selbst deklarierten Algorithmus respektiert, akzeptiert jede gefälschte Nutzlast. Konfigurieren Sie Ihre Bibliothek immer mit dem exakten erwarteten Algorithmus (z. B. ['RS256']) und lehnen Sie none explizit ab.

Token lokal inspizieren