Böngészős tárolás és tokenek
Célok
A lecke végére meg tudod különböztetni a böngészős tárolási lehetőségeket (cookie, Web Storage, IndexedDB), el tudod magyarázni, mi a token és mi a JWT, és érted, hogy a token fogalma és a tárolása két külön döntés.
Miért két külön fogalom?
A cookie, a localStorage és az IndexedDB tárolási hely: hova teszünk adatot. A token ezzel szemben egy érték, amelyet egy protokoll meghatározott célra ad át és ellenőriz: hozzáférést vagy azonosítást képvisel. Egy token tárolható cookie-ban, localStorage-ban vagy memóriában, és a döntés a biztonságra is hat. Aki a kettőt összekeveri, rossz kérdést tesz fel: nem az a kérdés, hogy „cookie vagy token”, hanem az, hogy mit akarunk igazolni, és hol őrizzük, hogyan továbbítjuk.
Kurzusoldal, vázlat és hozzáférés
A hallgató nyelvi beállítást választ, félbehagy egy helyi vázlatot, és bejelentkezik. A három adat eltérő célú:
| Adat |
Természetes hely |
Miért? |
| Nyelvi beállítás (kicsi) |
Cookie vagy localStorage |
Egyszerű, nem érzékeny. |
| Félbehagyott vázlat (strukturált, nagyobb) |
IndexedDB |
Strukturált adat (3.6). |
| A bejelentkezés igazolása |
Munkamenet-cookie vagy token |
Érzékeny; a kezelését biztonsági szempontok határozzák meg. |
flowchart TD
A[Alkalmazási igény] --> C[Cookie: a HTTP-kéréshez magától csatolódhat]
A --> W[Web Storage: kulcs–érték]
A --> I[IndexedDB: strukturált adat]
T[Token: igazolás vagy hozzáférési érték] -. külön tárolási döntés .-> C
T -. külön tárolási döntés .-> W
Az ábra nem javasolja, hogy érzékeny tokent automatikusan Web Storage-ban tároljunk; csak azt mutatja, hogy a token fogalma és a tárolás helye külön döntés.
A tárolók összehasonlítása
|
Cookie |
localStorage |
sessionStorage |
IndexedDB |
| Hatókör |
domain és útvonal szerint |
eredet (3.6) |
eredet + böngészőlap |
eredet |
| Kéréssel együtt megy? |
igen, ha a hatókör egyezik |
nem |
nem |
nem |
| JavaScript olvashatja? |
nem, ha HttpOnly |
igen |
igen |
igen |
| Méret |
kb. 4 kilobájt / cookie |
kb. 5 MiB / eredet |
kb. 5 MiB / eredet |
böngésző kezeli, nagy |
| Élettartam |
Max-Age / Expires |
a böngésző törlésig |
a lap bezárásáig |
a böngésző törlésig |
(A méretadatok az MDN oldalai alapján: cookie kb. 4 kilobájt, a Web Storage eredetenként kb. 5 MiB.) Két következmény:
- A cookie magától csatolódik a kéréshez, ami kényelmes (a munkamenet-azonosítónak ez kell), de azt is jelenti, hogy más oldalról indított kérésekhez is csatolódhat, ha a
SameSite ezt nem akadályozza (8. fejezet).
- A
localStorage és az IndexedDB tartalmát bármely, az oldalon futó JavaScript olvashatja. Ha egy támadó szkriptet tud beszúrni az oldalba (XSS, 8. fejezet), elolvashatja az itt tárolt tokent is. A HttpOnly cookie-t a JavaScript nem látja.
A helyi tárolás nem megbízható szerveroldali nyilvántartás és nem szinkronizál a felhasználó többi eszközére. Egy elfogadott jelentkezés hivatalos állapotát a szervernek kell kezelnie.
Mi a token?
A token olyan érték, amelyet egy protokoll meghatározott célra ad át és ellenőriz. Egy hozzáférési token (access token) például egy API-erőforráshoz való hozzáférést képviseli. A szerveroldali munkamenet-azonosító (7.2) is hordozó érték, de más mechanizmushoz kapcsolódik. Az API-k tokent gyakran az Authorization fejlécben fogadnak, Bearer sémával:
GET /jelentkezesek/anna HTTP/1.1
Host: kurzuspont.example
Authorization: Bearer <token>
Az RFC 6750 szerint a „bearer token” birtokosa (a hordozó) használhatja a tokent az erőforráshoz, kriptográfiai kulcs bizonyítása nélkül: a birtoklás maga a jogosultság. Ezért a tokent csak TLS-en szabad továbbítani (az RFC kötelezővé teszi), az URL-be tenni nem tanácsos (az RFC is ellenzi), mert az URL naplókba kerül, és az élettartama legyen rövid.
Nem minden token JWT, és egy JWT sem automatikusan biztonságos. A JWT (JSON Web Token) az RFC 7519 szerint kompakt, URL-biztos formája állítások (claim) továbbításának két fél között. A token három, pontokkal elválasztott, base64url kódolású részből áll: fej (header), tartalom (payload) és aláírás. Kipróbáltuk (Node.js crypto modul, HS256, vagyis HMAC SHA-256 aláírás egy közös titokkal):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbm5hIiwic3plcmVwIjoiaGFsbGdhdG8iLCJleHAiOjE3OTE3NDE2MDB9._x4fXjw_K5A-qpXUeTODT1aTOQfqua55_Rd0XqhWsSg
fej : {"alg":"HS256","typ":"JWT"}
tartalom : {"sub":"anna","szerep":"hallgato","exp":1791741600}
eredeti token : ÉRVÉNYES aláírás
módosított token (szerep=oktato): ÉRVÉNYTELEN aláírás
Három tanulság:
- A tartalom nem titkos. A JWT tartalma bárki által dekódolható (base64url nem titkosítás). Az RFC szerint a JWT lehet aláírt (JWS), titkosított (JWE) vagy akár védetlen. Titkos adatot nem szabad aláírt, de nem titkosított JWT-be tenni.
- Az aláírás a sértetlenséget védi. Ha valaki átírja a
szerep mezőt, az aláírás már nem egyezik, ezért a szerver elutasítja. A módosítás tehát észrevehető.
- A lejárat a tartalomban van (
exp, másodperc a Unix-időszámítás kezdetétől), de a szervernek ellenőriznie kell. Ha egy tokent vissza akarunk vonni a lejárat előtt, ahhoz a szerver oldalán is nyilvántartás kell.
A JWT jellemzően „önálló” token: a szerver az aláírásból el tudja dönteni az érvényességét, nem kell hozzá munkamenet-tábla. Ez kényelmes, de a visszavonás nehezebb. A formátum választása a kliens típusától, a hozzáférési határtól és a biztonsági modelltől függ.
Cookie, munkamenet és token együtt
Egy webhely küldhet cookie-ban szerveroldali munkamenet-azonosítót. Egy API elfogadhat hozzáférési tokent az Authorization fejlécben. OAuth 2.0 és OpenID Connect környezetben többféle token jelenhet meg, eltérő célra (7.5). A „cookie vagy token” tehát hamis, túl egyszerű választás: a cookie továbbítási és tárolási mechanizmus, a token pedig protokollbeli érték.
Végigvezetett példa: a Kurzuspont belépési tokenje
A Kurzuspontnak van egy mobilalkalmazása is. A böngészős felület munkamenet-cookie-t használ, a mobilalkalmazás hozzáférési tokent küld az Authorization fejlécben.
| Kliens |
Igazolás |
Tárolás |
Indok |
| Böngésző |
munkamenet-cookie (HttpOnly) |
a böngésző cookie-tárolója |
A JavaScript nem éri el, magától csatolódik. |
| Mobilalkalmazás |
hozzáférési token |
az operációs rendszer biztonságos tárolója |
Nincs cookie-modell; rövid élettartam. |
Mindkettőnél a szerver ellenőrzi a jogosultságot (7.4), és az igazolás visszavonható.
Gyakori tévhitek
| Állítás |
Pontosítás |
| „A token egy böngészős tárhely neve.” |
Érték; a tárolása külön tervezési döntés. |
| „Minden token JWT.” |
Több formátum létezik, köztük átláthatatlan token is. |
„A localStorage adatai automatikusan mennek a szervernek.” |
A cookie-val ellentétben nem csatolódnak a kérésekhez. |
| „A böngészőben tárolt sikeres jelentkezés a hivatalos eredmény.” |
A szerveroldali állapot a mérvadó. |
| „A JWT-ben titkolt az adat.” |
Az aláírt JWT tartalma bárki számára olvasható. |
Röviden
- A cookie, a Web Storage és az IndexedDB tárolók; a token egy érték, amelynek tárolása külön döntés.
- A cookie magától csatolódik és lehet
HttpOnly; a localStorage tartalmát bármely oldalon futó szkript olvashatja.
- A bearer token birtoklás alapján működik: TLS, rövid élettartam, URL-ben nem tanácsos küldeni.
- A JWT aláírt formátum: a tartalom olvasható, de nem módosítható észrevétlenül.
Ellenőrző kérdések
- Miért veszélyesebb egy tokent
localStorage-ban tartani egy XSS-sebezhető oldalon, mint HttpOnly cookie-ban?
- Mit jelent az, hogy a bearer token birtoklása a jogosultság?
- Miért olvasható bárki számára egy aláírt JWT tartalma?
- Mit véd az aláírás, és mit nem?
Tanulási források
Böngészős tárolás és tokenek
Célok
A lecke végére meg tudod különböztetni a böngészős tárolási lehetőségeket (cookie, Web Storage, IndexedDB), el tudod magyarázni, mi a token és mi a JWT, és érted, hogy a token fogalma és a tárolása két külön döntés.
Miért két külön fogalom?
A cookie, a
localStorageés az IndexedDB tárolási hely: hova teszünk adatot. A token ezzel szemben egy érték, amelyet egy protokoll meghatározott célra ad át és ellenőriz: hozzáférést vagy azonosítást képvisel. Egy token tárolható cookie-ban,localStorage-ban vagy memóriában, és a döntés a biztonságra is hat. Aki a kettőt összekeveri, rossz kérdést tesz fel: nem az a kérdés, hogy „cookie vagy token”, hanem az, hogy mit akarunk igazolni, és hol őrizzük, hogyan továbbítjuk.Kurzusoldal, vázlat és hozzáférés
A hallgató nyelvi beállítást választ, félbehagy egy helyi vázlatot, és bejelentkezik. A három adat eltérő célú:
localStorageflowchart TD A[Alkalmazási igény] --> C[Cookie: a HTTP-kéréshez magától csatolódhat] A --> W[Web Storage: kulcs–érték] A --> I[IndexedDB: strukturált adat] T[Token: igazolás vagy hozzáférési érték] -. külön tárolási döntés .-> C T -. külön tárolási döntés .-> WAz ábra nem javasolja, hogy érzékeny tokent automatikusan Web Storage-ban tároljunk; csak azt mutatja, hogy a token fogalma és a tárolás helye külön döntés.
A tárolók összehasonlítása
localStoragesessionStorageHttpOnlyMax-Age/Expires(A méretadatok az MDN oldalai alapján: cookie kb. 4 kilobájt, a Web Storage eredetenként kb. 5 MiB.) Két következmény:
SameSiteezt nem akadályozza (8. fejezet).localStorageés azIndexedDBtartalmát bármely, az oldalon futó JavaScript olvashatja. Ha egy támadó szkriptet tud beszúrni az oldalba (XSS, 8. fejezet), elolvashatja az itt tárolt tokent is. AHttpOnlycookie-t a JavaScript nem látja.A helyi tárolás nem megbízható szerveroldali nyilvántartás és nem szinkronizál a felhasználó többi eszközére. Egy elfogadott jelentkezés hivatalos állapotát a szervernek kell kezelnie.
Mi a token?
A token olyan érték, amelyet egy protokoll meghatározott célra ad át és ellenőriz. Egy hozzáférési token (access token) például egy API-erőforráshoz való hozzáférést képviseli. A szerveroldali munkamenet-azonosító (7.2) is hordozó érték, de más mechanizmushoz kapcsolódik. Az API-k tokent gyakran az
Authorizationfejlécben fogadnak, Bearer sémával:Az RFC 6750 szerint a „bearer token” birtokosa (a hordozó) használhatja a tokent az erőforráshoz, kriptográfiai kulcs bizonyítása nélkül: a birtoklás maga a jogosultság. Ezért a tokent csak TLS-en szabad továbbítani (az RFC kötelezővé teszi), az URL-be tenni nem tanácsos (az RFC is ellenzi), mert az URL naplókba kerül, és az élettartama legyen rövid.
JWT: egy elterjedt tokenformátum
Nem minden token JWT, és egy JWT sem automatikusan biztonságos. A JWT (JSON Web Token) az RFC 7519 szerint kompakt, URL-biztos formája állítások (claim) továbbításának két fél között. A token három, pontokkal elválasztott, base64url kódolású részből áll: fej (header), tartalom (payload) és aláírás. Kipróbáltuk (Node.js
cryptomodul, HS256, vagyis HMAC SHA-256 aláírás egy közös titokkal):Három tanulság:
szerepmezőt, az aláírás már nem egyezik, ezért a szerver elutasítja. A módosítás tehát észrevehető.exp, másodperc a Unix-időszámítás kezdetétől), de a szervernek ellenőriznie kell. Ha egy tokent vissza akarunk vonni a lejárat előtt, ahhoz a szerver oldalán is nyilvántartás kell.A JWT jellemzően „önálló” token: a szerver az aláírásból el tudja dönteni az érvényességét, nem kell hozzá munkamenet-tábla. Ez kényelmes, de a visszavonás nehezebb. A formátum választása a kliens típusától, a hozzáférési határtól és a biztonsági modelltől függ.
Cookie, munkamenet és token együtt
Egy webhely küldhet cookie-ban szerveroldali munkamenet-azonosítót. Egy API elfogadhat hozzáférési tokent az
Authorizationfejlécben. OAuth 2.0 és OpenID Connect környezetben többféle token jelenhet meg, eltérő célra (7.5). A „cookie vagy token” tehát hamis, túl egyszerű választás: a cookie továbbítási és tárolási mechanizmus, a token pedig protokollbeli érték.Végigvezetett példa: a Kurzuspont belépési tokenje
A Kurzuspontnak van egy mobilalkalmazása is. A böngészős felület munkamenet-cookie-t használ, a mobilalkalmazás hozzáférési tokent küld az
Authorizationfejlécben.HttpOnly)Mindkettőnél a szerver ellenőrzi a jogosultságot (7.4), és az igazolás visszavonható.
Gyakori tévhitek
localStorageadatai automatikusan mennek a szervernek.”Röviden
HttpOnly; alocalStoragetartalmát bármely oldalon futó szkript olvashatja.Ellenőrző kérdések
localStorage-ban tartani egy XSS-sebezhető oldalon, mintHttpOnlycookie-ban?Tanulási források