Co to jest JSON Web Token (JWT)?
Zrozum podstawy JSON Web Token (JWT) w 5 minut.
JSON Web Token (JWT) jest szeroko stosowany we współczesnych aplikacjach internetowych i otwartych standardach, takich jak OpenID Connect, ułatwiając uwierzytelnianie i autoryzację. Chociaż oficjalny RFC 7519 służy jako niezbędne źródło informacji, może być trudny do zrozumienia dla początkujących. W tym artykule skupimy się na podstawowych koncepcjach JWT i przedstawimy je w przystępny sposób, z przykładami.
Dlaczego potrzebujemy JWT?
Obecnie dość powszechnym jest korzystanie z JSON do wymiany danych między dwiema stronami. Rozważmy obiekt JSON reprezentujący użytkownika:
sub
to skrót od "subject", który jest standardowym roszczeniem w OpenID Connect, reprezentującym identyfikator użytkownika (ID użytkownika).
Jak możemy zagwarantować integralność tego obiektu JSON? Innymi słowy, jak możemy upewnić się, że dane nie zostały sfałszowane podczas transmisji? Powszechnym rozwiązaniem jest użycie cyfrowych podpisów. Na przykład możemy skorzystać z kryptografii z kluczem publicznym: serwer podpisuje obiekt JSON prywatnym kluczem, a klient może zweryfikować podpis za pomocą publicznego klucza serwera.
W skrócie, JWT oferuje standaryzowany sposób reprezentowania obiektu JSON i jego podpisu.
Format JWT
Ponieważ istnieje wiele algorytmów tworzenia podpisów cyfrowych, konieczne jest określenie algorytmu używanego do podpisania JWT. Jest to możliwe dzięki utworzeniu obiektu JSON:
alg
to skrót od "algorithm", atyp
to skrót od "type".
Zazwyczaj typ
jest ustawiany na JWT
wielkimi literami. W naszym przykładzie alg
to HS256
, co oznacza HMAC-SHA256 (wkrótce tego wyjaśnimy), i wskazuje, że używamy tego algorytmu do utworzenia podpisu.
Teraz mamy wszystkie składniki JWT:
- JSON nagłówka: algorytm i typ
- JSON ładunku: rzeczywiste dane
- Podpis: podpis obejmujący nagłówek i ładunek
Jednak niektóre znaki, takie jak spacje i znaki nowej linii, nie są przyjazne dla transmisji sieciowej. Dlatego nagłówek i ładunek muszą być zakodowane w Base64URL. Typowy JWT wygląda tak:
.
służy jako separator.
Połączmy wszystko razem i utworzymy JWT:
Nagłówek
JSON: {"alg":"HS256","typ":"JWT"}
Zakodowany w Base64URL: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
Ładunek
JSON: {"sub":"foo","name":"John Doe"}
Zakodowany w Base64URL: eyJzdWIiOiJmb28iLCJuYW1lIjoiSm9obiBEb2UifQ
Podpis
W HMAC-SHA256, podpis jest tworzony za pomocą sekretu:
Na przykład, z sekretem some-great-secret
, podpis staje się: XM-XSs2Lmp76IcTQ7tVdFcZzN4W_WcoKMNANp925Q9g
.
JWT
Ostateczny JWT to:
Ten ważny JWT może być zweryfikowany przez dowolną stronę posiadającą sekret.
Wybierz algorytm podpisu
Jak wcześniej wspomniano, istnieje wiele algorytmów do tworzenia podpisów cyfrowych. Użyliśmy HS256
jako przykładu, ale może nie być wystarczająco silny, ponieważ sekret musi być udostępniony między stronami (np. klientem i serwerem).
W rzeczywistych scenariuszach klienci mogą obejmować publiczne aplikacje, takie jak aplikacje React, które nie mogą zapewnić bezpieczeństwa sekretu. W związku z tym preferowanym podejściem jest wykorzystanie kryptografii z kluczem publicznym (tj. kryptografii asymetrycznej) do podpisywania JWT. Zacznijmy od najpopularniejszego algorytmu: RSA.
RSA
RSA, czyli algorytm asymetryczny, korzysta z pary kluczy: klucza publicznego i klucza prywatnego. Klucz publiczny służy do weryfikacji podpisu, a klucz prywatny do podpisywania.
JSON nag łówka dla RSA wygląda tak:
RS256
oznacza RSA-SHA256, co oznacza, że podpis jest tworzony za pomocą algorytmu RSA i funkcji skrótu SHA256. Można również użyćRS384
iRS512
do tworzenia podpisów za pomocą funkcji skrótu SHA384 i SHA512, odpowiednio.
Podpis jest tworzony za pomocą klucza prywatnego:
Znowu możemy złożyć te części, aby utworzyć JWT, a ostateczny JWT wygląda tak:
Teraz klient może zweryfikować podpis bez znajomości klucza prywatnego.
ECDSA
Chociaż RSA jest szeroko stosowany, cierpi na większy rozmiar podpisów, czasami przekraczający łączną wielkość nagłówka i ładunku. Elliptic Curve Digital Signature Algorithm (ECDSA) to inny algorytm asymetryczny, który może tworzyć bardziej kompaktowe podpisy i jest bardziej wydajny.
Aby wygenerować klucz prywatny dla ECDSA, musimy wybrać krzywą. Jest to poza zakresem tego artykułu, ale więcej informacji znajdziesz tutaj.
JSON nagłówka dla ECDSA wygląda tak:
ES256
oznacza ECDSA-SHA256, co oznacza, że podpis jest tworzony za pomocą algorytmu ECDSA i funkcji skrótu SHA256. Można również użyćES384
iES512
do tworzenia podpisów za pomocą funkcji skrótu SHA384 i SHA512, odpowiednio.
Podpis jest tworzony za pomocą klucza prywatnego:
Ostateczny JWT zachowuje tę samą strukturę co RSA, ale z znacznie krótszym podpisem:
Weryfikacja JWT
Weryfikacja JWT jest prosta, jako proces odwrotny do tworzenia JWT:
- Podziel JWT na trzy części (nagłówek, ładunek i podpis) przy użyciu separatora
.
. - Odkoduj nagłówek i ładunek za pomocą Base64URL.
- Zweryfikuj podpis za pomocą algorytmu określonego w nagłówku i klucza publicznego (dla algorytmów asymetrycznych).
Istnieje wiele bibliotek, które są dostępne do pomocy w weryfikacji JWT, takich jak jose dla Node.js i przeglądarek internetowych.
Podsumowanie
W tym artykule krótko wyjaśniliśmy podstawowe koncepcje JWT, oraz przedstawiliśmy, jak go tworzyć i weryfikować. Wiele szczegółów pozostało niezbadanych i omówimy je w przyszłych artykułach.
Logto wykorzystuje otwarte standardy, takie jak JWT i OpenID Connect, aby zabezpieczyć twoje aplikacje i API z uproszczonymi przepływami pracy dla każdego programisty. Jeśli jesteś zainteresowany, możesz go wypróbować za darmo (bez potrzeby podawania numeru karty kredytowej).