JSON Web Token jako forma autentykacji i autoryzacji

JSON Web Token (w skrócie: JWT) jest ustandaryzowaną (RFC-7519) metodą bezpiecznego przesyłania danych (z ang. claims – roszczenia/prawa) pomiędzy serwerem a klientem. JWT działa poprzez wygenerowanie i podpisanie po stronie serwera żetonu tekstowego złożonego z trzech części podzielonych kropkami. Następnie jest on przesyłany do klienta, dalej klient może na jego podstawie np. autentykować swoje zapytania do serwera i autoryzować żądania.

Token podpisany i zaszyfrowany

JSON Web Token może zostać podpisany przy użyciu znanego dwóm stronom klucza (secret) korzystając z algorytmu HMAC lub też przy pomocy pary kluczy prywatny/publiczny (algorytmy RSA lub ECDSA). Podpisany token (nazywany standardowo JSON Web Signature – JWS) możemy bezpiecznie wykorzystać do potwierdzenia integralności i autentyczności przenoszenego payloadu – nie można zmienić zawartości żetonu bez zepsucia podpisu. Zawartość może również opcjonalnie zostać zaszyfrowana tak, aby nikt poza nadawcą i odbiorcą nie mógł odczytać danych – ten standard to JSON Web Encryption (JWE)

Struktura żetonu JWT

Żeton składa się z trzech zasadniczych części. Pierwsza z nich to nagłówek, który zawiera metadane – rodzaj algorytmu używanego do wygenerowania żetonu oraz pole typ z wartością JWT, co jednoznacznie definiuje ciąg jako JSON Web Token. Drugą częścią żetonu jest jego zawartość merytoryczna (ang. payload). Możemy tam przesłać dowolne dane (claims), które potrzebne nam będą od strony biznesowej, np. takie, które pozwolą na autoryzację danego użytkownika w kontekście dostępu do wybranej usługi. Specyfikacja JWT zaleca dodanie wśród zawartości znaczników registered claims takich jak iat (ang. issued at) definiującego czas wygenerowania żetonu, exp (ang. expiring) – czas wygaśnięcia, czy też iss czyli określenie organizacji/aplikacji, która wygenerowała żeton. Pozostały fragment payloadu, definiowany przez nadawcę to tzw. private claims – możemy tam umieścić dowolne, potrzebne nam dane. Trzecia część to cyfrowy podpis serwera, generowany na bazie tajnego klucza oraz zawartości dwóch poprzednich części oraz kodowany w base64. Wszystkie trzy zakodowane części zostają połączone i w wyniku otrzymujemy żeton w formie aaaaaaaaa.bbbbbbbbb.ccccccccc

Uwaga! Pamiętaj, że dla podpisanych tokenów przesyłane informacje (mimo, że zabezpieczone przed ich zmianą) są jawne i widoczne dla każdego. Nie umieszczaj w payloadzie ani w nagłówki JWT wrażliwych danych, jeśli nie są one zaszyfrowane!

Przykład JSON Web Token
Przykład JWT przed i po kodowaniu. Źródło: debugger na stronie jwt.io

Przykładowy przebieg autentykacji przy użyciu JSON Web Token

Architektura procesu logowania użytkownika i autoryzowania jego żądań w architekturze serwer + klient REST może wyglądać następująco:

  1. Klient wysyła do serwera żądanie HTTP typu POST zawierające dane użytkownika do zalogowania
  2. W przypadku poprawnych danych serwer generuje żeton JWT korzystając z tajnego klucza i przesyła go do klienta w odpowiedzi na żądanie logowania. Zawiera on zakodowane dane dot. użytkownika, np. jego role (uprawnienia).
  3. Klient zapisuje otrzymany token. Przy każdym żądaniu wymagającym autentykacji/autoryzacji wysyłanym do serwera, token dołączany jest do nagłówka Authorization. Na serwerze działa middleware, które przechwytuje nagłówek tego typu, dekoduje go oraz uzupełnia żądanie o uprawnienia użytkownika.
  4. Żeton powinien mieć domyślnie ustawiony termin ważności (po upływie terminu serwer zwróci wyjątek, że żeton jest nieważny, co efektywnie będzie powodowało wylogowanie użytkownika z systemu). W przypadku poprawnie zautoryzowanych zapytań żeton jest odświeżany, tj. generowana jest jego nowa instancja, dzięki czemu termin zostaje przedłużony, a użytkownik aktywnie korzystający z aplikacji nie zostanie z niej nagle wylogowany.

Jeśli potrzebujesz gotowej biblioteki, która obsługą (de-)kodowania JWT zajmie się za Ciebie, lub chcesz zobaczyć w praktyce jak wygląda tworzenie JWT zobacz stronę jwt.io/ – zawiera ona spis sprawdzonych bibliotek do większości języków programowania jak i specjalny debugger pozwalający na zabawę i testowanie żetonów.

Leave a Comment

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *