Vad en JSON Web Token faktiskt innehåller
En JSON Web Token (JWT) är tre textblock hopfogade med punkter. Varje block är Base64url-kodat, och de två första är helt vanlig JSON. Vem som helst som har token kan läsa vad som finns inuti den. Ingenting i en vanlig JWT är krypterat.
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 <- header
eyJzdWIiOiIxMjM0NSIsIm5hbWUiOiJBbGV4In0 <- payload
dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFW <- signature
Hopfogat med punkter är det den token du klistrar in i en begäran. Avkoda de två första delarna så får du vanlig JSON:
{ "alg": "HS256", "typ": "JWT" }
{ "sub": "12345", "name": "Alex" }
En verklig nyttolast bär oftast tidsstämplar och en mottagare också:
{
"iss": "https://auth.example.com",
"sub": "12345",
"aud": "api.example.com",
"iat": 1756000000,
"exp": 1756003600,
"roles": ["editor"]
}
Huvudet
Huvudet beskriver hur token är signerad. Två fält spelar störst roll:
algnamnger signeringsalgoritmen, till exempelHS256(HMAC med SHA-256, med en delad hemlighet) ellerRS256(RSA-signatur med SHA-256, signerad med en privat nyckel och kontrollerad med en publik).kid, nyckel-ID:t, är valfritt och talar om för mottagaren vilken av flera nycklar som användes, så att nycklar kan roteras utan att befintliga tokens slutar fungera.
typ är oftast bara JWT och har ingen säkerhetsmässig betydelse.
Nyttolasten och dess anspråk
Nyttolasten är ett JSON-objekt med anspråk, vilket helt enkelt är specifikationens ord för påståenden om tokens subjekt. Vissa anspråksnamn är registrerade av standarden, och de är alla korta:
| Anspråk | Namn | Vad det innehåller |
|---|---|---|
iss | Utfärdare | Vem som skapade token, oftast en URL eller ett tjänstenamn |
sub | Subjekt | Vem token handlar om, oftast ett stabilt användar-ID |
aud | Mottagare | Vem token är avsedd för, så att en tjänst kan avvisa tokens avsedda för en annan |
exp | Utgångstid | Tidpunkten efter vilken token måste avvisas |
nbf | Inte före | Tidpunkten före vilken token måste avvisas |
iat | Utfärdad vid | När token skapades |
jti | JWT-ID | En unik identifierare, användbar för att spåra eller blockera enskilda tokens |
exp, nbf och iat är alla NumericDate-värden, alltså sekunder sedan 1 januari 1970 UTC. Det är sekunder, inte millisekunder. Om en tidsstämpel avkodas till ett datum år 57 000 läser du millisekunder och behöver dividera med tusen.
Allt annat i nyttolasten är vad utfärdaren nu har lagt dit: roller, behörigheter, en e-postadress, ett tenant-ID. Eftersom ett privat anspråksnamn en dag skulle kunna krocka med ett registrerat, sätter utfärdare ofta en URL-liknande prefixnamnrymd på sina egna.
Signaturen
Signaturen beräknas över den exakta texten i de två första delarna hopfogade med en punkt, med algoritmen från huvudet och en nyckel. Ändra ett enda tecken i huvudet eller nyttolasten och signaturen stämmer inte längre.
Med HS256 signerar och verifierar samma hemlighet, så vem som helst som kan kontrollera en token kan också utfärda en. Med RS256 eller ES256 signerar en privat nyckel och en publik nyckel verifierar, vilket är det som låter en identitetsleverantör dela ut tokens som många separata tjänster kan validera utan att hålla något hemligt.
Base64url är inte kryptering
Base64url är samma idé som Base64, med två skillnader: den använder - och _ i stället för + och / så att resultatet är säkert i URL:er, och den avslutande =-utfyllnaden tas oftast bort. Det är en kodning, ett vändbart sätt att skriva bytes som text. Den ger ingen konfidentialitet över huvud taget.
Lägg därför aldrig något känsligt i en JWT-nyttolast: inga lösenord, inga kortnummer, inga interna anteckningar om användaren. Utgå från att den som håller token, och alla som läser den ur en loggfil eller en webbläsarlagring, kan se varje fält.
Det finns ett separat format, JWE, som faktiskt krypterar nyttolasten, och det har fem delar i stället för tre. Om din token har tre delar är den signerad och läsbar.
Att avkoda är inte att verifiera
Det är den här punkten som betyder något. En avkodare visar dig vad en token säger. Den talar inte om för dig om token är äkta. Verifiering är ett separat steg och kräver nyckeln.
För att verkligen lita på en token måste en server:
- Kontrollera signaturen mot rätt nyckel.
- Kräva den algoritm den förväntar sig, i stället för att lita på fältet
algi token. Två klassiska angrepp kommer av att man hoppar över detta: att sättaalgtillnoneoch ta bort signaturen, och att ta en tjänsts publika RSA-nyckel och använda den som HMAC-hemlighet så att enRS256-verifierare luras att köraHS256. - Kontrollera
expoch, om det finns,nbf, med en liten tillåten klockavvikelse. - Kontrollera att
issochaudstämmer med vad den här tjänsten förväntar sig.
Först då betyder anspråken något. Fram till dess är nyttolasten en overifierad sträng som kom in över nätverket.
Praktiska anmärkningar
- Tokens skickas oftast i ett HTTP-huvud som
Authorization: Bearer <token>, så håll nyttolasten liten. Varje anspråk du lägger till skickas vid varje begäran. - En signerad token förblir giltig tills den går ut. Det finns inget inbyggt sätt att återkalla en, vilket är varför åtkomsttokens tenderar att ha korta livslängder, ofta minuter, med en separat uppdateringstoken som används för att hämta nya.
- Om en token ser felformad ut, räkna punkterna först. Två punkter och tre delar är en normal signerad JWT. En avhuggen token som klistrats in från en terminal är en mycket vanlig orsak till "invalid signature".
- Att avkoda en token för att läsa dess utgångstid, dess subjekt eller dess roller under felsökning är helt ofarligt och kräver ingen hemlighet. Det är precis vad nyttolasten är till för.