Przejdź do treści

Tokeny JWT a Zarządzanie Sesją ✔

JWT został opublikowany pod koniec 2010 roku i bardzo szybko zyskał na popularności. Dziś, JWT jest używane przez większość serwisów a brak pojęcia o działaniu tokenów powinien być szybko nadrobiony przez każdego świadomego programistę.


Cześć 🙂

Dziś opiszę działanie JWT oraz dlaczego nie powinniśmy używać go zamiast sesji po stronie serwera. O mechanizmie działania sesji wspominałem już w jednym z wcześniejszych artykułów z którym możesz się zapoznać tutaj.

Niestety, klątwą programisty (i ogólnie nauki) jest to, że chcąc wyjaśnić coś dokładnie, ten artykuł musiałby być mini-książką. Artykuł ten jest tylko wierzchem góry lodowej. Jeżeli potrzebujesz zanurzyć się głębiej w tematy tu poruszane – szukaj w Internecie. Na każdy temat jest dużo informacji i ciekawostek.

W dzisiejszym artykule:


Czym jest token JWT?

JSON Web Token czyli tytułowy JWT jest to standard (RFC 7519) definiujący przesyłanie informacji między stronami w postaci obiektu JSON. JWT gwarantuje, że przesyłane dane są prawdziwe (nikt ich nie zmodyfikował po drodze) i są przesłane przez ich właścicela (pomijam fakt ukradnięcia tokenu i podszywania się pod właściciela). Gwarancja ta wynika z faktu, że token jest podpisywany sygnaturą cyfrową (używając secretów lub pary klucza publicznego/prywatnego).

Warto zapamiętać, JWT gwarantuje prawo własności danych (data ownership) ale nie gwarantuje ich szyfrowania! Dane przechowywane w tokenie mogą być widoczne dla każdego kto je przechwyci ponieważ token jest serializowany a nie zaszyfrowany. Z tego też powodu nie powinno umieszczać się tam danych, które są wrażliwe.

Struktura JWT

JWT jest zwięzły i składa się z trzech części oddzielonych kropkami:

  • header
  • payload
  • signature

Nie będę w tym artykule przytaczał opisu każdej z części. W Internecie jest dużo informacji na ten temat a najlepsze wprowadzenie znajdziesz na stronie jwt.io.

Koniec końców token przyjmuje format tekstowy kodowany przy użyciu Base64Url i w swojej końcowej postaci może wyglądać następująco:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJodHRwczovL2JkYWJlay5wbC8iLCJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6ImJkYWJlay5wbCIsImlhdCI6MTUxNjIzOTAyMn0.Vw6MAJ-ovTKFHKIdaqPFR7Uj8EUeN9DedhYaNAgEUSk.

Jak działa JSON Web Token?

Najważniejszą informacją w tokenie jest payload (zwany również claims). Payload przechowuje dane przesyłane w tokenie, czyli to co najbardziej nas interesuje. Token jest generowany po stronie serwera a następnie przesyłany do klienta. Klient używa później tokena jako klucza, który uprawnia go do używania zasobów po stronie serwera. Token po stronie klienta może być przechowywany w ciasteczku (należy pamiętać o tym aby był przechowywany jako HttpOnly) lub w local storage. Obie metody przechowywania mają swoje wady w postaci ataków CSRF lub XSS. Preferowane jest jednak przechowywanie tokena w ciasteczku. JWT jest przesyłany do serwera przy pomocy nagłówków HTTP (Bearer token) lub ciasteczka. Należy jednak pamietać, że ciasteczko wysyłane będzie przy każdym requeście a nagłówek HTTP tylko wtedy gdy go dodamy 🙂


Do czego używać tokenów JWT?

Tokeny sprawdzą się dobrze w przypadku

  • Autoryzacji (Authorization) / Wymiany informacji (Information Exchange)
  • Uwierzytelnienia API (API Authentication)

Tokeny mogą się wydawać dobrym wyborem również jako zastępca sesji po stronie serwera (więcej o tym w kolejnym akapicie).

W przypadku uwierzytelniania API flow wygląda jak na obrazku poniżej. Rejestrujemy swoją aplikację po stronie serwera, gdzie generowany jest JWT/klucz, który możemy pobrać. Następnie, gdy wysyłamy żądanie do serwera, wysyłamy je razem z tokenem w żądaniu, który sprawdzany jest po stronie serwera.

O autoryzacji nie będę wspominał w tym artykule (choć uwierzytelnienie też zostało bardzo biednie opisane). Jeżeli chcesz doczytać / zapoznać się z flow w przypadku autoryzacji to poszukaj informacji o OAuth – uważaj tylko, żeby za bardzo nie wsiąknąć bo jest to duża dawka informacji.


Dlaczego JWT nie nadaje się do sesji?

Zanim odpowiem na pytanie dlaczego moim zdaniem JWT nie powinien być używany jako token sesji, zadajmy inne pytanie – dlaczego wydaje się on być dobrym wyborem?

  • Token może przechowywać dowolny rodzaj informacji o użytkowniku
  • Serwer może ufać klientowi bo JWT jest podpisany a dzięki temu serwer nie musi uderzać do bazy danych po dodatkowe informacje

Te dwie korzyści brzmią kusząco bo przyśpieszają działanie aplikacji internetowych redukując dodatkowe zapytania do bazy danych. Mimo, iż użycie JWT jako mechanizmu sesji wydaje się być kuszące to nie jest ono wskazane.

Jedną z podstawowych wad jest rozmiar tokena. Jako przykład weźmy przechowywanie identyfikatora użytkownika. Niech będzie, że jego identyfikator to user123. Używając standardowego mechanizmu i przechowując identyfiaktor w ciasteczku będzie on miał wielkość 7 bajtów. Przechowując ten sam identyfikator w tokenie jego rozmiar wyniesie około 300 bajtów – to jest ponad 40x więcej. Teraz za każdym razem nasz serwer będzie przyjmował 40x więcej danych żeby zrobić to samo.

Jedną z najważniejszych zalet używania tokena jako mechanizmu sesji jest uniknięcie wywołań bazy danych aby pobrać informacje o użytkowniku. Jak się okazuje, używając JWT tak czy inaczej prawdopodobnie nie unikniemy odwołań do bazy! Używając tokenów w taki sposób sprawiamy, że sesja staje się bezstanowa. To całkiem fajne… tylko, że w dobie dzisiejszych wymagań jako taka stanowość jest potrzebna. Aplikacje są dynamiczne i bardzo często nie uda nam się umieścić wszystkich niezbędnych informacji w tokenie przez co i tak będziemy musieli odwołać się do bazy / cache’u.

Jeżeli na siłę będziesz chciał pchać wszystko do tokenów to wpadniesz w kolejną pułapkę… a nawet dwie. Raz – tokeny są tylko serializowane, nie są szyfrowane co oznacza, że jeżeli umieścisz w nich zbyt poufne dane to ktoś może je wykraść. Drugim problemem o którym była już mowa jest wielkość tokenu. Token powinien być zwięzły/zwarty (compact). Umieszczając do środka tokenu wszystko co popadnie będzie on zawierał dodatkowe bajty, które muszą wędrować z każdym żądaniem w kierunku serwera a to jest raczej słaba opcja.

Kolejnym problemem jest przechowywanie tokena po stronie klienta. Tak jak pisałem wcześniej, JWT może być przechowywany np. w ciasteczku lub w Local Storage. Wybierając pierwszą opcję jesteśmy ograniczeni do maksymalnego rozmiaru ciasteczka (około 4 KB – więcej o tym w artykule o ciasteczkach). Druga opcja natomiast jest po prostu niebezpieczna, otwierając możliwość ataku XSS.


Podsumowanie

JSON Web Token z pewnością jest przydatny i należy z niego korzystać. Istnieją przypadki, gdzie jego użycie jest wręcz wskazane, np. autoryzacja server-to-server czy też uwierzytelnianie API. Moim zdaniem nie należy używać tokenów jako zamiennika sesji. Nie jest to sprawdzone rozwiązanie i nie zostało tak dobrze przetestowane w boju jak sesja po stronie serwera. Kto wie, może z czasem coś się zmieni i JWT znajdzie swoje przypadki użycia jako zamiennik sesji 🙂

Źródła:


Za tydzień

Spróbuję przekonać Cię dlaczego powinieneś stosować wzorzec strategii wszędzie tam gdzie masz wątpliwości co do implementacji oraz jak zrobić to dobrze.

0 0 votes
Article Rating
Subscribe
Powiadom o
guest
0 komentarzy
najnowszy
najstarszy oceniany
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x