JWT (JSON Web Token): hlavička, payload, podpis

JWT přenáší tvrzení v obálce JWS nebo JWE. Rozkódování Base64url pouze zpřístupní obsah; teprve ověření a kontrola pravidel aplikace rozhodne, zda mu věřit.

Autor: Aktualizováno

Tři části podpisové obálky

Kompaktní zápis podepsaného JWS má tři části oddělené tečkami: header.payload.signature. Hlavička (header) uvádí algoritmus, obsah (payload) nese údaje tokenu, například o uživateli a době platnosti; poslední část je podpis. Šifrovaný JWE má pět částí. Počet částí tedy závisí na způsobu ochrany tokenu.

Tři části podpisové obálky
{"alg":"HS256","typ":"JWT"}

{"sub":"uzivatel-123","iss":"https://example.cz","aud":"moje-api","exp":2000000000}

Kontrola claims

Exp a nbf používají NumericDate v sekundách od epochy, nikoli milisekundy. Ověř očekávaného vydavatele a publikum, časovou platnost i účel tokenu podle svého profilu. Název sub není automaticky databázový identifikátor ve všech systémech.

Povol algoritmy z konfigurace

Neber seznam dovolených algoritmů ze samotného tokenu. Ověř podpis správným důvěryhodným klíčem a odděl pravidla pro různé druhy tokenů. Kid pomáhá vybrat klíč, ale nedává oprávnění načíst libovolný soubor nebo URL.

Diagnostika a soukromí

Obsah podepsaného JWS bývá čitelný každému, kdo token získá; podpis není šifrování. JWT nástroj může dekódovat a podle zvoleného režimu ověřit podpis, ale zelená syntax nenahrazuje kontrolu údajů tokenu, jeho platnosti a důvěryhodnosti vydavatele. Reálné přístupové tokeny nesdílej v logu ani odkazu.

Vytvoření a ověření výukového tokenu v Node.js

jwt-demo.mjs — npm install jose, potom node jwt-demo.mjs
import {SignJWT, jwtVerify, decodeJwt} from "jose";
const key = new TextEncoder().encode("pouze-vyukovy-klic-32-bajtu-nebo-delsi");
const token = await new SignJWT({role: "ctenar"})
  .setProtectedHeader({alg: "HS256", typ: "JWT"})
  .setSubject("uzivatel-123")
  .setIssuer("https://example.cz")
  .setAudience("moje-api")
  .setIssuedAt()
  .setExpirationTime("5m")
  .sign(key);
console.log("Pouze dekódováno:", decodeJwt(token).sub);
const {payload} = await jwtVerify(token, key, {
  algorithms: ["HS256"],
  issuer: "https://example.cz",
  audience: "moje-api"
});
console.log("Ověřeno:", payload.sub, payload.role);
try {
  await jwtVerify(token, key, {algorithms:["HS256"], audience:"jine-api"});
  throw new Error("Token neměl být přijat");
} catch (error) {
  console.log("Odmítnuto pro jiné publikum:", error.code);
}

Výstup nejdřív ukáže dekódovaný subjekt, potom ověřený subjekt a roli. Poslední kontrola odmítne jiné publikum. Pevný veřejný klíč slouží pouze k reprodukovatelné demonstraci: HS256 v aplikaci potřebuje důvěrný dostatečně náhodný sdílený klíč, ne heslo z článku. Kdokoli zná klíč HS256, může token také podepsat.

Asymetrický podpis umožní distribuovat veřejné ověřovací klíče bez soukromého podepisovacího klíče. Výběr algoritmu a klíče ale musí odpovídat serverové konfiguraci. JWK/JWKS jsou reprezentace klíčů; klíče načítej jen z předem určeného důvěryhodného zdroje a počítej s jejich výměnou.

Diagnostika v online nástroji a typické chyby

  1. Vlož pouze výukový token do JWT nástroje a prohlédni header a payload.
  2. Ověř podpis se stejným výukovým klíčem a povoleným algoritmem.
  3. Změň klíč: podpis musí selhat. Úspěšné dekódování se tím nezmění.
  4. V aplikaci navíc ověř iss, aud, časovou platnost a očekávaný druh tokenu.

Exp je čas v sekundách; při tvorbě relativně od nynějška se vyhneš trvale expirované kopii článku. Token s budoucím nbf zatím není použitelný. JWT neposkytuje automatické odvolání: aplikace potřebuje politiku doby života, obnovy či seznamu odvolání. Claims role jsou důvěryhodné až po ověření správného vydavatele a stále nenahrazují oprávnění pro konkrétní záznam.

Pravidla bezpečného použití popisuje JWT Best Current Practices, API ukázky oficiální jose dokumentace. Pro autentizaci celého API pokračuj OpenAPI.