Die Realität von Token-Speicherung im Browser
Ein praktischer Blick auf JWT-Speicherung im Browser, XSS, CSRF, Cookies, localStorage, Service Worker und Threat Models.
Debatten über Token-Speicherung im Browser enden oft in Parolen: localStorage ist schlecht, Cookies sind gut, oder umgekehrt. Reale Anwendungen brauchen ein Threat Model. Ein JWT in localStorage ist für injiziertes JavaScript leicht zu lesen. Ein JWT in einem HttpOnly-Cookie ist vor direktem Script-Zugriff geschützt, wird aber automatisch mit Requests gesendet und braucht CSRF-Kontrollen. Keine Option rettet eine App mit breitem XSS und privilegierten APIs ohne zusätzliche Prüfungen.
Was ein Angreifer will
Bei XSS fragt der Angreifer zuerst, ob er das Token stehlen kann oder den Browser des Opfers als verwirrten Stellvertreter nutzt. Liegt das Token in localStorage, ist localStorage.getItem("access_token") der klare Weg. Liegt es in einem HttpOnly-Cookie, ist direkter Diebstahl schwieriger, aber der Angreifer kann weiterhin same-origin APIs von der Seite aus aufrufen, sofern CSP, Request-Validierung und Bestätigungen für sensible Aktionen den Schaden nicht begrenzen.
Die Token-Lebensdauer verändert die Rechnung. Ein fünf Minuten gültiges Access Token im Speicher mit Refresh-Cookie verhält sich völlig anders als ein dreißig Tage gültiges JWT in localStorage. Browser-Erweiterungen, gemeinsam genutzte Rechner, Crash Dumps, Logs und Support-Screenshots zählen ebenfalls. Die Speicherentscheidung ist nicht von Operations getrennt.
Häufige Muster und Kosten
Access Tokens nur im Speicher zu halten reduziert dauerhaften Diebstahl, erschwert aber Reloads, mehrere Tabs und Offline-Flows. HttpOnly Secure SameSite Cookies sind für viele Web-Apps stark, doch Cross-Site-API-Domains und eingebettete Kontexte können SameSite-Konfiguration schwierig machen. localStorage ist einfach und vorhersehbar, aber jedes XSS wird zur Token-Extraktion, wenn das Token nicht kurzlebig und eng gescoped ist.
Defensive Details
Setze Secure, HttpOnly und einen bewusst gewählten SameSite-Wert auf Cookies. Nutze CSP mit Nonces oder Hashes, nicht eine Policy, die jede Analytics-Domain Script ausführen lässt. Lege Tokens nicht in URLs, denn sie lecken über Verlauf, Referrer, Proxy-Logs und Screenshots. Schreibe Bearer Tokens nicht in Frontend-Telemetrie. Entferne Authorization-Header, bevor sie Session-Replay-Tools erreichen.
Speicherentscheidungen testen
Simuliere im Review den Angreifer, nicht das Architekturdiagramm. Kann injiziertes Script ein Token lesen? Kann es /api/export oder /api/billing mit ambienten Cookies aufrufen? Widerruft Logout den Refresh-Pfad oder löscht es nur Client-State? Öffne DevTools, prüfe Storage, löse Fehler aus und kontrolliere Telemetrie-Payloads. Das beste Design ist das, dessen Fehlermodus du wirklich getestet hast.