Zweryfikuj podpis JSON Web Token (JWT)

weryfikuje podpis JWT (HS256, HS384, HS512, RS256, RS384, RS512) używając sekretu lub klucza publicznego, oraz analizuje jego claims
Dla HS256 / HS384 / HS512: współdzielony ciąg sekretny. Dla RS256 / RS384 / RS512: klucz publiczny w formacie PEM.

Dlaczego weryfikować podpis JWT?

JSON Web Token (JWT) dzieli się na trzy części oddzielone kropkami: header.payload.signature. Dekodowanie JWT polega po prostu na odczytaniu dwóch pierwszych części (które są Base64URL). Każdy może to zrobić i każdy może zbudować JWT z wybranym payloadem. To, co czyni JWT godnym zaufania, to wyłącznie podpis: bez weryfikacji akceptowanie JWT równa się wpuszczaniu do siebie każdego, kto twierdzi, że jest kimś, bez sprawdzania dokumentu tożsamości.

To narzędzie weryfikuje podpis JWT na podstawie klucza. Nie ogranicza się do dekodowania: ponownie oblicza podpis z nagłówka, payloadu i twojego klucza, a następnie porównuje go z podpisem tokenu. Jeśli oba się zgadzają, token jest autentyczny. W przeciwnym razie został sfałszowany, zmodyfikowany lub podpisany innym kluczem.

Weryfikacja to kamień węgielny każdej architektury używającej JWT do uwierzytelnienia lub autoryzacji: bez prawidłowego podpisu payload może kłamać. Atakujący, który zmieniłby "role":"user" na "role":"admin", nie miałby żadnej trudności z zrobieniem tego, gdyby serwer weryfikował tylko format tokenu, a nie jego podpis.

Popularne algorytmy

Specyfikacja JWT (RFC 7518, JSON Web Algorithms) definiuje kilka rodzin algorytmów. Oto najczęściej używane w produkcji:

  • HMAC (HS256, HS384, HS512): symetryczny podpis oparty na HMAC-SHA. Ten sam sekretny klucz służy do podpisywania i weryfikacji. Łatwy do wdrożenia, wydajny, ale każda strona zdolna do weryfikacji tokenu jest też zdolna do jego emitowania. Odpowiedni dla scenariuszy, w których emitent i weryfikator to ten sam zespół lub usługa.
  • RSA (RS256, RS384, RS512): asymetryczny podpis. Klucz prywatny podpisuje, klucz publiczny weryfikuje. Idealny, gdy emitent i weryfikatorzy są odrębnymi podmiotami (OAuth2, OpenID Connect, federacja tożsamości). To algorytm preferowany przez większość publicznych dostawców tożsamości.
  • ECDSA (ES256, ES384): asymetryczny podpis na krzywych eliptycznych. Ta sama logika co RSA (klucz prywatny do podpisywania, klucz publiczny do weryfikacji), ale z bardziej kompaktowymi kluczami i podpisami przy równoważnym poziomie bezpieczeństwa. Coraz bardziej rozpowszechniony w nowoczesnych architekturach.

Jak dostarczyć klucz

Format oczekiwanego klucza zależy od algorytmu zadeklarowanego w nagłówku JWT:

  • HS256, HS384, HS512: klucz to sekretny ciąg (string). To sekret dzielony z emitentem, często przechowywany w zmiennej środowiskowej, takiej jak JWT_SECRET. Żadne specyficzne formatowanie, po prostu surowa wartość.
  • RS256, RS384, RS512: klucz to publiczny klucz RSA w formacie PEM, który zaczyna się od -----BEGIN PUBLIC KEY----- i kończy na -----END PUBLIC KEY-----. Zachowaj znaki nowej linii bez zmian, w przeciwnym razie OpenSSL odmówi sparsowania.
  • ES256, ES384: klucz to publiczny klucz ECDSA w formacie PEM, na odpowiedniej krzywej (P-256 dla ES256, P-384 dla ES384).

Przykład oczekiwanego klucza publicznego RSA

-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxe...
...vQIDAQAB
-----END PUBLIC KEY-----

Jak działa weryfikacja?

Nasz serwer dokładnie odtwarza operację, którą wykonał emitent:

  1. Rozdziela JWT na nagłówek, payload i podpis.
  2. Konkatenuje base64url(header) + "." + base64url(payload).
  3. Dla HMAC oblicza HMAC-SHA-256/384/512 twoim sekretnym kluczem, a następnie porównuje z otrzymanym podpisem przez hash_equals (porównanie w stałym czasie, aby uniknąć ataków czasowych).
  4. Dla RSA wywołuje openssl_verify z twoim kluczem publicznym w formacie PEM.

Przypadki użycia

  • Debugowanie uwierzytelnienia API: otrzymujesz 401, weryfikuj, czy twój token jest dobrze podpisany oczekiwanym kluczem.
  • Walidacja tokenu otrzymanego od dostawcy: partner (Auth0, Keycloak, Cognito, Okta) wysyła ci JWT podpisane w RS256, chcesz potwierdzić, że pochodzą faktycznie od niego, jego kluczem publicznym.
  • Audyt bezpieczeństwa: weryfikacja, że usługa zewnętrzna poprawnie podpisuje swoje tokeny solidnym algorytmem, a nie w HS256 ze słabym sekretem.
  • Testy ręczne: weryfikacja, że JWT wygenerowany przez twój kod przechodzi weryfikację dostarczonym kluczem publicznym.
  • Szybka weryfikacja otrzymanego tokenu: podczas integracji SSO lub API partnerskiego, sprawdzenie w kilka sekund, że łańcuch podpis/klucz działa, zanim napisze się jakąkolwiek linię kodu.

Jak korzystać z narzędzia

  1. Wklej kompletny JWT (trzy części oddzielone kropkami).
  2. Wskaż klucz dopasowany do algorytmu nagłówka:
    • Dla HS256, HS384 lub HS512 klucz to sekretny ciąg dzielony z emitentem. To wolny ciąg, często przechowywany w zmiennej środowiskowej, takiej jak JWT_SECRET.
    • Dla RS256, RS384 lub RS512 klucz to publiczny klucz w formacie PEM, który zaczyna się od -----BEGIN PUBLIC KEY----- i kończy na -----END PUBLIC KEY-----.
  3. Uruchom weryfikację. Narzędzie wyświetla status (ważny lub nieważny) i zdekodowany payload.

Częste pułapki do uniknięcia

  • Algorytm „none": specyfikacja autoryzuje alg: none, co oznacza „brak podpisu". Klasyczna luka polega na zbudowaniu tokenu z tym nagłówkiem w nadziei, że serwer go zaakceptuje. Nasze narzędzie systematycznie odrzuca tokeny z alg: none.
  • Mylenie HMAC vs RSA (algorithm confusion): atakujący zmienia algorytm RS256 na HS256 i podpisuje payload kluczem publicznym RSA użytym jako sekret HMAC. Jeśli serwer nie kontroluje algorytmu, akceptuje token. Zawsze blokuj oczekiwany algorytm po stronie serwera.
  • Sekrety HMAC na sztywno w kodzie: sekret zacommitowany w repozytorium Git unieważnia całe zaufanie tokenów. Przechowuj sekrety w zmiennych środowiskowych lub aplikacyjnym skarbcu.
  • Klucz publiczny vs klucz prywatny: do weryfikacji JWT podpisanego w RSA lub ECDSA dostarcza się klucz publiczny, nigdy prywatny. Prywatny służy tylko do podpisywania i nigdy nie powinien opuszczać emitenta.
  • Zignorowane wygaśnięcie: prawidłowy podpis na wygasłym tokenie nigdy nie powinien być akceptowany. Pamiętaj o weryfikacji exp i nbf.
  • Niekontrolowana audiencja: token przeznaczony dla API A nie powinien być akceptowany przez API B. Sprawdź claim aud.

Claims czasowe: exp i nbf

Poza podpisem prawidłowy JWT musi też respektować swoje ograniczenia czasowe:

  • exp (expiration): token nie jest ważny po tej dacie.
  • nbf (not before): token nie jest jeszcze ważny przed tą datą.

Nasze narzędzie wyraźnie sygnalizuje, gdy token jest wygasły lub jeszcze nieważny, nawet jeśli jego podpis jest poprawny. To ważne: prawidłowy podpis na wygasłym tokenie nigdy nie powinien być akceptowany w produkcji.

Różnica w stosunku do naszego JWT decoder

Nasz JWT decoder ogranicza się do dekodowania części nagłówka i payloadu, aby uczynić je czytelnymi. Nie wykonuje żadnej weryfikacji podpisu i nie wymaga klucza. Użyj go do szybkiego sprawdzenia zawartości tokenu. Użyj JWT verifier (ta strona), gdy musisz udowodnić, że token jest autentyczny. Do produkcji podpisanego JWT do celów testowych użyj naszego JWT builder.

Najczęściej zadawane pytania

Dlaczego RS256 zamiast HS256?

Z HS256 emitent i weryfikator dzielą ten sam sekret: każdy weryfikator może więc emitować tokeny. Jest to zarządzalne, gdy kontroluje się oba końce. Gdy mówimy o jednym dostawcy tożsamości z wieloma konsumującymi usługami, przechodzimy na RS256: emitent zachowuje klucz prywatny, rozprowadza się klucz publiczny do wszystkich API, które muszą weryfikować. Żadne konsumujące API nie może wtedy sfałszować tokenów.

Jak pobrać klucz publiczny dostawcy tożsamości (IdP)?

Większość IdP udostępnia ustandaryzowany endpoint JWKS (na przykład https://exemple.com/.well-known/jwks.json). Ten endpoint zwraca JSON zawierający aktywne klucze publiczne. Możesz przekonwertować pozycję JWK odpowiadającą kid nagłówka twojego JWT na klucz PEM przez polecenie openssl lub bibliotekę JWKS swojego stacku (na przykład jose-jwt, jwks-rsa).

Co zrobić, jeśli weryfikacja nie powiedzie się?

Sprawdź najpierw algorytm: token podpisany w HS256 nie weryfikuje się kluczem RSA i odwrotnie. Następnie sprawdź klucz: nadmiarowy biały znak, brakujący znak nowej linii w kluczu PEM lub sekret HMAC nieco różny od używanego przez emitenta wystarczają, aby weryfikacja zawiodła. Jeśli IdP wykonał rotację klucza, twój kid może wskazywać na klucz, którego już nie masz.

JWKS, co to jest?

JWKS (JSON Web Key Set, RFC 7517) to format JSON, który opisuje zestaw kluczy publicznych. Każdy klucz jest identyfikowany przez kid (key ID), a JWT do weryfikacji odnosi się do tego kid w swoim nagłówku. Mechanizm pozwala IdP rotować swoje klucze bez psucia weryfikatorów: po prostu pytają endpoint JWKS, aby pobrać klucz odpowiadający kid otrzymanego tokenu.

Jak wygenerować parę kluczy RSA do podpisywania moich JWT?

Z OpenSSL: openssl genrsa -out private.pem 2048, a następnie openssl rsa -in private.pem -pubout -out public.pem. Klucz prywatny podpisuje po stronie emitenta, klucz publiczny weryfikuje po stronie konsumenta. Dla nowych usług preferuj 3072 lub 4096 bitów.

Czy trzeba szyfrować JWT oprócz podpisywania (JWE)?

Podpisany JWT (JWS) gwarantuje integralność i autentyczność, ale payload pozostaje czytelny dla każdego, kto go odzyska. Jeśli token zawiera wrażliwe dane (wewnętrzne identyfikatory, szczegółowe prawa, dane osobowe), rozważ format JWE (JSON Web Encryption), który szyfruje payload oprócz jego podpisywania.

Przykładowe zapytanie

curl -X POST https://cdrn.fr/api/v1/tools/jwt-verifier/execute \
  -H "Content-Type: application/json" \
  -d '{"token":"...","key":"..."}'

Schemat wejściowy

Pole Typ Wymagane Domyślnie
token text
key text

Punkty końcowe

  • GET https://cdrn.fr/api/v1/tools - lista wszystkich dostępnych narzędzi
  • GET https://cdrn.fr/api/v1/tools/jwt-verifier - zwraca schemat dla tego narzędzia
  • POST https://cdrn.fr/api/v1/tools/jwt-verifier/execute - uruchamia to narzędzie z payloadem JSON