JWT vs. session: hvilken godkendelsesmekanisme skal du vælge?
At godkende en bruger betyder at vide ved hver forespørgsel, hvem brugeren er. To store familier står over for hinanden: serversessioner, hvor serveren holder styr på den loggede bruger, og JSON Web Tokens (JWT), hvor identiteten rejser i et signeret token båret af klienten. Valget påvirker sikkerheden, evnen til at skalere op og letheden ved at logge en bruger ud. Sådan afgør du det efter din kontekst.
Serversessioner (stateful)
Med en session opretter serveren et session-id ved login, gemmer de tilknyttede data (identitet, roller, kurv) på serversiden (hukommelse, Redis, database) og returnerer en cookie til browseren, der kun indeholder dette id. Ved hver forespørgsel læser serveren cookien, finder sessionen og ved, hvem der taler.
- Tilstand på serversiden: kilden til sandhed forbliver på serveren, klienten bærer kun en uigennemsigtig reference.
- Øjeblikkelig tilbagekaldelse: at slette sessionen på serversiden logger brugeren ud øjeblikkeligt.
- Cookie: overført automatisk af browseren, ideelt med
HttpOnly,SecureogSameSite.
JSON Web Tokens (stateless)
Et JWT er et selvbærende token sammensat af tre dele kodet i base64url og adskilt af punktummer: et header, et payload (claims, for eksempel bruger-id og udløb) og en signature. Serveren signerer tokenet ved login; derefter er det nok at verificere signaturen for at stole på indholdet uden at gemme noget.
- Tilstandsløs: al nødvendig information er i tokenet, serveren har ikke brug for delt hukommelse.
- Verificerbar overalt: enhver tjeneste, der kender nøglen, kan validere tokenet, praktisk for distribuerede arkitekturer og SSO.
- Værktøjer: du kan inspicere et token med vores JWT-afkoder, kontrollere dets signatur med JWT-verifikatoren eller smede et med JWT-generatoren.
Sammenligningstabel
| Kriterium | Serversession | JWT |
|---|---|---|
| Tilstand | Stateful (gemt på server) | Stateless (båret af klienten) |
| Serverlagring | Påkrævet (Redis, database) | Ingen |
| Tilbagekaldelse | Øjeblikkelig | Vanskelig før udløb |
| Horisontal skalerbarhed | Delt lager nødvendigt | Indbygget |
| Overført størrelse | Lille (et id) | Større (signerede claims) |
| På tværs af domæner / SSO | Besværligt | Velegnet |
| XSS-overflade | Lav med HttpOnly-cookie | Høj hvis gemt i localStorage |
Sikkerhed: XSS, CSRF og tilbagekaldelse
Begge tilgange er sikre, hvis de er korrekt implementeret, men deres risici er forskellige.
- XSS: en session-cookie med
HttpOnlyer utilgængelig for JavaScript, altså beskyttet mod tyveri via injektion. Et JWT gemt ilocalStorageer derimod læsbart for ethvert script, hvilket gør det til et oplagt mål. At gemme JWT i enHttpOnly-cookie ophæver denne fordel ved JWT, men genindfører CSRF-risikoen. - CSRF: cookies sendes automatisk og er derfor sårbare over for CSRF uden beskyttelse (
SameSite-attribut, anti-CSRF-token). Et JWT sendt manuelt iAuthorization-headeren er ikke berørt. - Tilbagekaldelse: det er JWT's svage punkt. Da det er selvbærende, kan det ikke ugyldiggøres før udløb uden at genindføre en servertilstand (tilbagekaldelsesliste, sortliste). En session slettes øjeblikkeligt.
Skalerbarhed og arkitektur
På en enkelt server er sessioner trivielle. Så snart du fordeler belastningen på flere instanser, skal hver instans have adgang til sessionerne: der kræves et delt lager (Redis) eller sticky sessions. Her skinner JWT, fordi enhver instans validerer tokenet uden netværkskald eller fælles lager.
- Mikrotjenester: et JWT formidler identiteten fra én tjeneste til en anden uden en central database.
- Offentlige og mobile API'er: JWT undgår håndtering af cookies på den native klientside.
- Klassisk monolit: sessionen forbliver enklere og sikrere som standard.
Hvornår skal du vælge det ene eller det andet
Vælg sessioner, når
- Du udvikler en klassisk webapplikation med serverrendering
- Øjeblikkelig tilbagekaldelse er kritisk (bank, sundhed, back-office)
- Du vil have den sikreste løsning som standard med færrest faldgruber
- Din infrastruktur klarer et delt sessionslager uden besvær
Vælg JWT, når
- Du eksponerer et API, der forbruges af SPA'er, mobil eller tredjeparter
- Du har en mikrotjenestearkitektur eller SSO på tværs af domæner
- Du skal skalere horisontalt uden et delt lager
- Du accepterer at håndtere kort udløb og fornyelse af tokens
Anbefaling
For de fleste webapplikationer forbliver serversessioner det sikreste og enkleste valg: øjeblikkelig tilbagekaldelse, HttpOnly-cookie og nul tokenhåndtering på klientsiden. Reserver JWT til de tilfælde, hvor dens tilstandsløshed giver reel værdi: stateless API, mobil, mikrotjenester, SSO.
Hvis du vælger JWT, så hold en kort levetid (nogle minutter) koblet med et refresh-token gemt i en HttpOnly-cookie, og indfør en tilbagekaldelsesliste til følsomme tilfælde. Så kombinerer du det bedste fra begge verdener.
Ofte stillede spørgsmål
Er et JWT krypteret?
Nej, som standard er et JWT kun signeret, ikke krypteret. Dets payload er kodet i base64url og læsbart for enhver, der opfanger det. Placér aldrig følsomme data i klartekst i et JWT. For at kryptere indholdet skal man ty til JWE (JSON Web Encryption).
Hvor skal man gemme et JWT på klientsiden?
Det sikreste er en HttpOnly-, Secure- og SameSite-cookie, der beskytter mod tyveri via XSS. localStorage er enklere, men eksponerer tokenet for ethvert ondsindet script. Undgå det til tokens med høje privilegier.
Hvordan logger man en bruger ud med et JWT?
Da tokenet er selvbærende, kræver reel udlogning enten at vente på dets udløb eller at vedligeholde en tilbagekaldelsesliste på serversiden. Derfor bruger man korte levetider og et refresh-token, som man til gengæld kan tilbagekalde.
Kan man kombinere sessioner og JWT?
Ja, det er en udbredt praksis: et access-token JWT med kort levetid til API-kald og et refresh-token håndteret som en session (gemt og tilbagekaldeligt på serversiden) til at forny access-tokenet.