Co JSON Web Token vlastně obsahuje
JSON Web Token (JWT) jsou tři kusy textu spojené tečkami. Každý kus je zakódovaný v Base64url a první dva jsou prostě JSON. Kdokoli, kdo token má, si může přečíst, co je uvnitř. V běžném JWT není zašifrované nic.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 <- header
eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJBbGV4In0 <- payload
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFW <- signature
Spojené tečkami to je token, který vkládáte do požadavku. Dekódujte první dvě části a dostanete obyčejný JSON:
{ "alg": "HS256", "typ": "JWT" }
{ "sub": "12345", "name": "Alex" }
Skutečný payload obvykle nese také časová razítka a příjemce:
{
"iss": "https://auth.example.com",
"sub": "12345",
"aud": "api.example.com",
"iat": 1756000000,
"exp": 1756003600,
"roles": ["editor"]
}
Hlavička
Hlavička popisuje, jak je token podepsaný. Nejvíc záleží na dvou polích:
algpojmenovává podpisový algoritmus, napříkladHS256(HMAC se SHA-256, používá sdílené tajemství) neboRS256(podpis RSA se SHA-256, podepisuje se soukromým klíčem a ověřuje veřejným).kid, tedy ID klíče, je nepovinné a příjemci říká, který z několika klíčů byl použit, takže se klíče dají rotovat, aniž by se rozbily existující tokeny.
typ bývá jen JWT a nenese žádný bezpečnostní význam.
Payload a jeho claimy
Payload je objekt JSON tvořený claimy, což je prostě výraz, jakým specifikace označuje tvrzení o subjektu tokenu. Některá jména claimů registruje standard a všechna jsou krátká:
| Claim | Název | Co obsahuje |
|---|---|---|
iss | Vydavatel | Kdo token vytvořil, obvykle URL nebo název služby |
sub | Subjekt | Koho se token týká, obvykle stabilní ID uživatele |
aud | Příjemce | Komu je token určen, aby služba mohla odmítnout tokeny určené jiné službě |
exp | Čas vypršení | Okamžik, po kterém se token musí odmítnout |
nbf | Ne dříve než | Okamžik, před kterým se token musí odmítnout |
iat | Vydáno v | Kdy token vznikl |
jti | ID tokenu | Jedinečný identifikátor, užitečný pro sledování nebo blokování jednotlivých tokenů |
exp, nbf i iat jsou hodnoty typu NumericDate, tedy sekundy od 1. ledna 1970 UTC. Jsou to sekundy, ne milisekundy. Pokud se časové razítko dekóduje na datum v roce 57 000, čtete milisekundy a musíte je vydělit tisícem.
Všechno ostatní v payloadu je to, co tam vydavatel dal: role, oprávnění, e-mailová adresa, ID nájemce. Protože se soukromé jméno claimu může jednou srazit s registrovaným, dávají vydavatelé ta svá často do jmenného prostoru s prefixem podobným URL.
Podpis
Podpis se počítá nad přesným textem prvních dvou částí spojených tečkou, pomocí algoritmu z hlavičky a klíče. Změňte jediný znak hlavičky nebo payloadu a podpis už nesedí.
U HS256 totéž tajemství podepisuje i ověřuje, takže kdo dokáže token zkontrolovat, dokáže ho také vyrobit. U RS256 nebo ES256 podepisuje soukromý klíč a ověřuje veřejný, což je to, co poskytovateli identity umožňuje vydávat tokeny, které dokáže ověřit mnoho samostatných služeb, aniž by držely jakékoli tajemství.
Base64url není šifrování
Base64url je táž myšlenka jako Base64 se dvěma rozdíly: používá - a _ místo + a /, aby byl výsledek bezpečný v URL, a koncové doplnění znakem = se obvykle odstraňuje. Je to kódování, tedy vratný způsob zápisu bajtů jako textu. Neposkytuje vůbec žádnou důvěrnost.
Do payloadu JWT proto nikdy nedávejte nic citlivého: žádná hesla, žádná čísla karet, žádné interní poznámky o uživateli. Předpokládejte, že člověk, který token drží, i každý, kdo si ho přečte z logu nebo z úložiště prohlížeče, vidí každé pole.
Existuje samostatný formát JWE, který payload šifruje, a má pět částí místo tří. Pokud má váš token tři části, je podepsaný a čitelný.
Dekódování není ověření
Tohle je ten podstatný bod. Dekodér vám ukáže, co token říká. Neřekne vám, jestli je token pravý. Ověření je samostatný krok a potřebuje klíč.
Aby server tokenu skutečně věřil, musí:
- Ověřit podpis proti správnému klíči.
- Trvat na algoritmu, který očekává, místo aby věřil poli
algv tokenu. Z vynechání tohoto kroku plynou dva klasické útoky: nastavitalgnanonea podpis odstranit, a vzít veřejný klíč RSA dané služby a použít ho jako tajemství pro HMAC, takže je ověřovatelRS256podveden a spustíHS256. - Zkontrolovat
expa, pokud je přítomné,nbf, s tolerancí na malý rozdíl hodin. - Zkontrolovat, že
issaaudodpovídají tomu, co tato služba očekává.
Teprve pak claimy něco znamenají. Do té doby je payload neověřený řetězec, který dorazil po síti.
Praktické poznámky
- Tokeny se obvykle posílají v hlavičce HTTP jako
Authorization: Bearer <token>, takže payload držte malý. Každý claim, který přidáte, se posílá s každým požadavkem. - Podepsaný token zůstává platný, dokud nevyprší. Neexistuje vestavěný způsob, jak ho odvolat, a proto mívají přístupové tokeny krátkou životnost, často v řádu minut, a k získání nových se používá samostatný obnovovací token.
- Pokud token vypadá poškozeně, nejdřív spočítejte tečky. Dvě tečky a tři části jsou normální podepsaný JWT. Velmi častou příčinou hlášky „invalid signature“ je useknutý token vložený z terminálu.
- Dekódovat token při ladění, abyste si přečetli jeho expiraci, subjekt nebo role, je naprosto bezpečné a nevyžaduje to žádné tajemství. Přesně k tomu payload slouží.