JWT vs. Session: Welcher Authentifizierungsmechanismus ist die richtige Wahl?

Einen Nutzer zu authentifizieren bedeutet, bei jeder Anfrage zu wissen, wer er ist. Zwei große Ansätze stehen sich gegenüber: Server-Sessions, bei denen der Server den angemeldeten Nutzer verwaltet, und JSON Web Tokens (JWT), bei denen die Identität in einem signierten Token reist, das der Client mit sich führt. Die Wahl beeinflusst die Sicherheit, die Skalierbarkeit und die Leichtigkeit, einen Nutzer abzumelden. So entscheiden Sie je nach Kontext.

Server-Sessions (stateful)

Bei einer Session erzeugt der Server bei der Anmeldung eine Session-Kennung, speichert die zugehörigen Daten (Identität, Rollen, Warenkorb) serverseitig (Arbeitsspeicher, Redis, Datenbank) und schickt dem Browser ein Cookie zurück, das nur diese Kennung enthält. Bei jeder Anfrage liest der Server das Cookie, findet die Session wieder und weiß, wer spricht.

  • Serverseitiger Zustand: Die Quelle der Wahrheit bleibt auf dem Server, der Client trägt nur eine undurchsichtige Referenz.
  • Sofortiger Widerruf: Das Löschen der Session auf dem Server meldet den Nutzer augenblicklich ab.
  • Cookie: vom Browser automatisch übertragen, idealerweise mit HttpOnly, Secure und SameSite.

JSON Web Tokens (stateless)

Ein JWT ist ein selbsttragendes Token aus drei base64url-codierten und durch Punkte getrennten Teilen: einem Header, einem Payload (den Claims, zum Beispiel der Nutzerkennung und dem Ablaufdatum) und einer Signatur. Der Server signiert das Token bei der Anmeldung; danach genügt es ihm, die Signatur zu prüfen, um dem Inhalt zu vertrauen, ohne etwas zu speichern.

  • Zustandslos: Alle nötigen Informationen stecken im Token, der Server benötigt keinen gemeinsamen Speicher.
  • Überall prüfbar: Jeder Dienst, der den Schlüssel kennt, kann das Token validieren, praktisch für verteilte Architekturen und SSO.
  • Werkzeuge: Sie können ein Token mit unserem JWT-Decoder inspizieren, seine Signatur mit dem JWT-Verifizierer prüfen oder eines mit dem JWT-Generator erzeugen.

Vergleichstabelle

Kriterium Server-Session JWT
ZustandStateful (serverseitig gespeichert)Stateless (vom Client getragen)
Serverseitiger SpeicherErforderlich (Redis, Datenbank)Keiner
WiderrufSofortigSchwierig vor Ablauf
Horizontale SkalierbarkeitGemeinsamer Store nötigNativ
Übertragene GrößeKlein (eine Kennung)Größer (signierte Claims)
Domänenübergreifend / SSOUmständlichGeeignet
XSS-AngriffsflächeGering bei HttpOnly-CookieHoch bei Speicherung im localStorage

Sicherheit: XSS, CSRF und Widerruf

Beide Ansätze sind sicher, sofern sie korrekt implementiert werden, doch ihre Risiken unterscheiden sich.

  • XSS: Ein Session-Cookie mit HttpOnly ist für JavaScript unzugänglich und somit vor Diebstahl durch Injektion geschützt. Ein im localStorage gespeichertes JWT ist hingegen für jedes Skript lesbar, was es zu einem bevorzugten Ziel macht. Das JWT in einem HttpOnly-Cookie zu speichern, hebt diesen Vorteil des JWT auf, führt aber das CSRF-Risiko wieder ein.
  • CSRF: Cookies werden automatisch gesendet und sind daher ohne Schutz (Attribut SameSite, Anti-CSRF-Token) anfällig für CSRF. Ein JWT, das manuell im Authorization-Header gesendet wird, ist davon nicht betroffen.
  • Widerruf: Das ist die Schwachstelle des JWT. Da es selbsttragend ist, kann man es vor seinem Ablauf nicht ungültig machen, ohne wieder einen Serverzustand einzuführen (Widerrufsliste, Blacklist). Eine Session lässt sich augenblicklich löschen.

Skalierbarkeit und Architektur

Auf einem einzelnen Server sind Sessions trivial. Sobald Sie die Last auf mehrere Instanzen verteilen, muss jede Instanz auf die Sessions zugreifen: Es braucht einen gemeinsamen Store (Redis) oder Sticky Sessions. Hier glänzt das JWT, denn jede Instanz validiert das Token ohne Netzwerkaufruf und ohne gemeinsamen Speicher.

  • Microservices: Ein JWT gibt die Identität von einem Dienst an den nächsten weiter, ohne zentrale Datenbank.
  • Öffentliche und mobile APIs: Das JWT erspart die Cookie-Verwaltung auf nativen Clients.
  • Klassischer Monolith: Die Session bleibt standardmäßig einfacher und sicherer.

Wann das eine, wann das andere wählen

Sessions wählen, wenn

  • Sie eine klassische Webanwendung mit serverseitigem Rendering entwickeln
  • der sofortige Widerruf entscheidend ist (Bank, Gesundheit, Back-Office)
  • Sie die standardmäßig sicherste Lösung mit den wenigsten Fallstricken wollen
  • Ihre Infrastruktur einen gemeinsamen Session-Store problemlos verträgt

JWT wählen, wenn

  • Sie eine API bereitstellen, die von SPAs, mobilen Apps oder Dritten konsumiert wird
  • Sie eine Microservices-Architektur oder domänenübergreifendes SSO haben
  • Sie horizontal skalieren müssen, ohne gemeinsamen Store
  • Sie bereit sind, die kurze Ablaufzeit und die Erneuerung der Token zu verwalten

Empfehlung

Für die meisten Webanwendungen bleiben Server-Sessions die sicherste und einfachste Wahl: sofortiger Widerruf, HttpOnly-Cookie und keinerlei Token-Verwaltung auf der Client-Seite. Reservieren Sie das JWT für Fälle, in denen seine Zustandslosigkeit echten Mehrwert bringt: zustandslose APIs, Mobile, Microservices, SSO.

Wenn Sie sich für das JWT entscheiden, halten Sie eine kurze Lebensdauer (einige Minuten) gekoppelt an ein Refresh-Token, das in einem HttpOnly-Cookie gespeichert wird, und sehen Sie für sensible Fälle eine Widerrufsliste vor. So vereinen Sie das Beste aus beiden Welten.

Häufige Fragen

Ist ein JWT verschlüsselt?

Nein, standardmäßig ist ein JWT nur signiert, nicht verschlüsselt. Sein Payload ist base64url-codiert und für jeden lesbar, der es abfängt. Legen Sie niemals sensible Daten im Klartext in ein JWT. Um den Inhalt zu verschlüsseln, muss man auf JWE (JSON Web Encryption) zurückgreifen.

Wo speichert man ein JWT auf der Client-Seite?

Am sichersten ist ein Cookie mit HttpOnly, Secure und SameSite, das vor Diebstahl durch XSS schützt. Der localStorage ist einfacher, setzt das Token aber jedem bösartigen Skript aus. Vermeiden Sie ihn für hochprivilegierte Token.

Wie meldet man einen Nutzer mit einem JWT ab?

Da das Token selbsttragend ist, erfordert die tatsächliche Abmeldung entweder das Abwarten seines Ablaufs oder das Führen einer Widerrufsliste auf dem Server. Deshalb verwendet man kurze Lebensdauern und ein Refresh-Token, das sich seinerseits widerrufen lässt.

Kann man Sessions und JWT kombinieren?

Ja, das ist eine gängige Praxis: ein JWT-Access-Token mit kurzer Lebensdauer für die API-Aufrufe und ein Refresh-Token, das wie eine Session verwaltet wird (serverseitig gespeichert und widerrufbar), um das Access-Token zu erneuern.