Zweryfikuj podpis JSON Web Token (JWT)
- Panel
- Dokumentacja
- API
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:
- Rozdziela JWT na nagłówek, payload i podpis.
- Konkatenuje
base64url(header) + "." + base64url(payload). - 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). - Dla RSA wywołuje
openssl_verifyz 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
- Wklej kompletny JWT (trzy części oddzielone kropkami).
- 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-----.
- 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
- 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 zalg: none. - Mylenie HMAC vs RSA (algorithm confusion): atakujący zmienia algorytm
RS256naHS256i 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
expinbf. - 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ędziGET https://cdrn.fr/api/v1/tools/jwt-verifier- zwraca schemat dla tego narzędziaPOST https://cdrn.fr/api/v1/tools/jwt-verifier/execute- uruchamia to narzędzie z payloadem JSON