JWT? WTF?
JWT. JSON Web Token. Ako už názov napovedá, jedná sa o nejaký symbol, použiteľný na webe a navyše vo formáte JSON. Presne tak. A ešte viac.
- má predpísanú štruktúru
- je zakódovaný do jednoduchého reťazca
- dokáže so sebou niesť akúkoľvek informáciu
- vieme ho cryptovať, kódovať, rozkódovať a overiť jeho pravosť
JWT vyzerá približne takto:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJiYXJ0LnNrIiwiZGlzcGxheV9uYW1lIjoiTWljaGFsIEhyaWNpxaHDrW4iLCJ1c2VybmFtZSI6Im1pY2hhbC5ocmljaXNpbiIsImlkIjoiNTc0ODg1NTI4MThiMjg0Mjg0YTI4Y2Y1In0.AmG5D2b8kqlhuSsz3VW_V_ufuTPs7Cuc4Vl673mfa88
Token pozostáva z troch častí, ktoré sa oddeľujú bodkou:
- Header – teda hlavička, ktorá nesie informáciu o algoritme kódovania a type tokenu
- Payload – tada akékoľvek dáta
- Signature – niečo ako podpis celého tokenu, slúži na overenie jeho pravosti
Jedná sa vlastne o 3 sety údajov, ktoré sú zakódované pomocou base64 do jedného stringu, ktorý je jednoduché ďalej prenášať medzi systémami.
Tretia časť, teda „signature“ je nepovinná časť. Závisí od aplikácie, či ju použije, alebo nie, v závislosti na type prenášaných dát. Mojím odporúčaním však je aby boli všetky tokeny podpísané.
Dáta, ktoré sme zakódovali v našom príklade vyzerajú nasledovne:
Hlavička:
{
alg: „HS256“,
typ: „JWT“
}
Payload:
{
sub: „bart.sk“,
display_name: „Michal Hricišín“,
username: „michal.hricisin“,
id: „57488552818b284284a28cf5“
}
Signature je vypočítaná pomocou zvoleného algoritmu za použitia nejakého kódovacieho reťazca. Tento by mal poznať vydavateľ tokenu, napríklad server, ktorý by samozrejme mal token pri spracovaní aj overiť.
A čo teda s tým?
Veľa ?. Obrovskou výhodou je, že JWT spolu s rôznymi kódovaniami podporujú snáď všetky používané jazyky. Od JavaScriptu cez PHP až po Swift alebo Go. Takže sa netreba trápiť čítaním špecifikácie a rovno môžme ísť na vec ?. Stačí si vybrať.
Klientská session
Iste viete, že HTTP je bezstavový protokol. Každá aplikácia však potrebuje stav. Preto vznikli rôzne cookies, sessions a podobne, ktoré slúžia na to, aby uchovávali konkrétny stav. Podľa mňa je JWT ideálny na uchovávanie tohto stavu. Získate tým štrukturované dáta, ktoré sú navyše podpísané a server alebo klient si dokáže overiť ich pravosť.
OAuth 2.0 tokens
Prečo by náhodný a ťažko uhádnuteľný OAuth token, vydaný autorizačným servrom nemohol byť práve podpísaný JWT? Získate tým veľa. Jednak získate štandardný formát tokenu, ktorý so sebou nesie aj nejaké dáta a jednak máte k tomu „zadarmo“ celý proces podpisovania a overovania pravosti takéhoto tokenu.
Tiež cítite to čo ja? Menší počet requestov, zvýšený performance, overovanie oauth aplikáciou, vyššia dostupnosť služieb? Nie? Vysvetlím…
Ako vlastne funguje overovanie tokenu v OAuth aplikáciách?
- OAuth autorizačný server, po overení identity používateľa vystaví access token, prípadne aj refresh token, pre nejakú aplikáciu, napríklad eshop
- Webová aplikácia si access token, prípadne refresh token uložia na vhodné miesto a používajú ho pri volaní metód API, ktoré si vyžadujú overenie identity používateľa
- Každé volanie API musí overiť access token, a teda urobiť request na autorizačný server a zistiť, či je token platný
No a teraz si predstavte, že v tomto popise nahradíte access token za JWT. A môžte celý bod 3 vyškrtnúť.
A navyše, OAuth je na to perfektne pripravené. Ak máte na starosti aj OAuth server, aj množstvo aplikácií na ňom závislých (ako napríklad ja, na SportNet-e, kde udržziavame 18 aplikácií), môžte malou úpravou OAuth servra ihneď začať vydávať miesto access tokenov JWT tokeny. Aplikácie môžete prispôsobovať postupne, keďže vlastne JWT tiež dobre poslúži ako doterajší „náhodný“ reťazec.
Každá aplikácia má pridelený client_secret, ktorý pozná ako autorizačný server, tak samotná aplikácia. A už máte skvelého kandidáta na secret kľúč pre podpisovanie JWT.
Tokeny sa zrazu stanú samopopisné a nemusíte na ich overenie používať volanie autorizačného servra a hneď máte o polovicu nižšie nároky na počet requestov.
Samozrejme, musím spomenúť aj to, že pri tomto použití musíte myslieť aj na bezpečnosť takýchto tokenov, a teda jednak používať kryptovanie, skrátiť platnosť tokenov na minúty max hodiny. Zmeniť implicitný flow na authorization code flow a používať refresh tokeny. Áno, doteraz som tvrdil, že JS apka si nemá kam uložiť bezpečne client_secret, ale s použitím PKCE autorization flow to už neplatí. O tom ale nabudúce…