JWT verstehen und selbst validieren
JSON Web Tokens sind überall. Viele nutzen sie ohne wirklich zu verstehen wie sie funktionieren.
Das rächt sich wenn man die Sicherheit falsch einschätzt.
Aufbau
Ein JWT besteht aus drei Base64url-kodierten Teilen getrennt durch Punkte.
header.payload.signature
Header enthält Algorithmus und Typ.
{"alg": "HS256", "typ": "JWT"}
Payload enthält die Claims.
{"sub": "42", "role": "admin", "exp": 1735689600}
Signatur ist HMAC über Header + Payload mit dem Secret.
Was ein JWT garantiert und was nicht
Die Signatur stellt sicher dass der Inhalt nicht verändert wurde.
Der Inhalt ist aber nur Base64-kodiert, nicht verschlüsselt — jeder kann ihn lesen.
Keine sensiblen Daten in den Payload.
In PHP validieren — ohne Bibliothek
function validateJwt(string $token, string $secret): ?array
{
$parts = explode('.', $token);
if (count($parts) !== 3) return null;
[$headerB64, $payloadB64, $sigB64] = $parts;
$expected = base64url_encode(hash_hmac('sha256', "$headerB64.$payloadB64", $secret, true));
if (!hash_equals($expected, $sigB64)) return null;
$payload = json_decode(base64url_decode($payloadB64), true);
if (!$payload) return null;
if (isset($payload['exp']) && $payload['exp'] < time()) return null;
return $payload;
}
function base64url_encode(string $data): string {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function base64url_decode(string $data): string {
return base64_decode(strtr($data, '-_', '+/'));
}
Wann JWT, wann Sessions
Sessions sind für Web-Apps mit Browser oft die bessere Wahl — serverseitig invalidierbar, kein Token im localStorage der per XSS gestohlen werden kann.
JWT macht Sinn für APIs die von mehreren Services genutzt werden und für mobile Clients.
Das alg:none Problem
Einige ältere Bibliotheken akzeptieren "alg": "none" und überspringen die Signaturprüfung.
Beim selbst Validieren immer den Algorithmus explizit prüfen — nie aus dem Header übernehmen.