Dowiedz się, czym jest JWT (JSON Web Token), jak działają jego trzy części, gdzie się go używa i jakie są kluczowe porady bezpieczeństwa, by uniknąć typowych błędów z tokenami.

JWT (JSON Web Token) to zwarty, bezpieczny dla URL-a ciąg znaków, który reprezentuje pewien zestaw informacji (zazwyczaj o użytkowniku lub sesji) w formie, którą można przekazywać między systemami. Często zobaczysz go jako długą wartość zaczynającą się od czegoś w stylu eyJ..., wysyłaną w nagłówku HTTP, np. Authorization: Bearer \u003ctoken\u003e.
Tradycyjne logowania często opierają się na sesjach po stronie serwera: po zalogowaniu serwer przechowuje dane sesji i daje przeglądarce cookie z ID sesji. Każde żądanie zawiera to cookie i serwer odczytuje sesję.
W uwierzytelnianiu opartym na tokenach serwer może uniknąć przechowywania stanu sesji dla każdego żądania. Zamiast tego klient trzyma token (np. JWT) i dołącza go do wywołań API. To popularne w przypadku API, ponieważ:
Ważna uwaga: „bezstanowość” nie znaczy „brak żadnych kontroli po stronie serwera”. W praktyce wiele systemów nadal weryfikuje tokeny względem statusu użytkownika, rotacji kluczy lub mechanizmów unieważniania.
JWT często zawierają dowód uwierzytelnienia (jesteś zalogowany) oraz podpowiedzi autoryzacyjne (role, uprawnienia, scope) — ale serwer nadal powinien egzekwować reguły autoryzacji.
JWT często używa się jako access tokenów w:
JWT to zwarty ciąg złożony z trzech części, każda zakodowana Base64URL i oddzielona kropkami:
header.payload.signature
Przykład (ocenzurowany):
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwiaWF0IjoxNzAwMDAwMDAwfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c…
Header opisuje, jak token został utworzony — najważniejszym polem jest algorytm podpisu (np. HS256, RS256/ES256) i typ tokena.
Częste pola:
typ: często "JWT" (w praktyce często ignorowane)alg: użyty algorytm podpisukid: identyfikator klucza pomagający weryfikatorowi wybrać właściwy klucz podczas rotacjiUwaga bezpieczeństwa: nie ufaj headerowi bez sprawdzenia. Wprowadź allowlistę algorytmów, których faktycznie używasz, i nie akceptuj alg: "none".
Payload zawiera „claims” (pola) o użytkowniku i kontekście tokena: dla kogo jest, kto go wystawił i kiedy wygasa.
Ważne: JWT nie są domyślnie szyfrowane. Kodowanie Base64URL sprawia, że token jest bezpieczny w URL, ale nie ukrywa danych. Każdy, kto ma token, może odszyfrować header i payload.
Dlatego unikaj wkładania sekretów (haseł, kluczy API) lub wrażliwych danych osobowych do JWT.
Signature powstaje przez podpisanie header + payload kluczem:
Podpis zapewnia integralność: pozwala serwerowi sprawdzić, że token nie został zmieniony i został wydany przez zaufanego podpisującego. Nie zapewnia poufności.
Ponieważ JWT zawiera header i payload przy każdym żądaniu, większe tokeny to więcej transferu i narzutów. Trzymaj claims oszczędnie i preferuj identyfikatory zamiast dużych danych.
Claims zwykle dzielą się na dwie grupy: zarejestrowane (standardowe nazwy) i własne (pola aplikacji).
iss (issuer): kto stworzył tokensub (subject): o kim jest token (zazwyczaj ID użytkownika)aud (audience): dla kogo jest token (np. konkretne API)exp (expiration time): kiedy token powinien przestać być akceptowanyiat (issued at): kiedy token został utworzonynbf (not before): token nie powinien być akceptowany przed tym czasemDołącz tylko to, czego serwis odbierający naprawdę potrzebuje do podjęcia decyzji autoryzacyjnej.
Dobre przykłady:
user_id)Unikaj „wygodnych” claims, które duplikują dużo danych profilu. Zwiększają rozmiar tokena, szybko się starzeją i powiększają skutki wycieku.
Ponieważ payload jest czytelny, nie przechowuj tam:
Jeśli potrzebujesz wrażliwych informacji, trzymaj je po stronie serwera i w tokenie umieść tylko referencję (np. ID) — lub użyj szyfrowanego formatu tokena (JWE), gdy to odpowiednie.
Podpisanie to nie szyfrowanie.
Kiedy JWT jest wystawiany, serwer podpisuje zakodowany header + payload. Gdy token jest przedstawiony później, serwer przelicza podpis i porównuje go. Jeśli ktoś zmieni choćby jeden znak (np. "role":"user" na "role":"admin"), weryfikacja nie przejdzie i token zostanie odrzucony.
JWT to format tokena. OAuth 2.0 i OpenID Connect (OIDC) to protokoły, które opisują, jak aplikacje żądają, wydają i używają tokenów.
OAuth 2.0 dotyczy głównie autoryzacji: pozwalania aplikacji na dostęp do API w imieniu użytkownika bez przekazywania hasła.
Access tokeny zwykle są krótkotrwałe (minuty). Krótkie życie ogranicza szkody w razie wycieku.
OIDC dodaje uwierzytelnianie (kim jest użytkownik) do OAuth 2.0 i wprowadza ID token, który jest zwykle JWT.
Zasada: nie używaj ID tokena do wywołań API.
Jeśli chcesz więcej kontekstu o praktycznych przepływach, zobacz /blog/jwt-authentication-flow.
Przykładowy flow wygląda tak:
Użytkownik loguje się (email/hasło, SSO itp.). Jeśli logowanie zakończy się sukcesem, serwer tworzy JWT (często access token) z niezbędnymi roszczeniami jak subject i expiration.
Serwer podpisuje token i zwraca go klientowi (aplikacja web, mobilna lub inny serwis).
Dla chronionych endpointów klient dołącza JWT w nagłówku Authorization:
Authorization: Bearer \u003cJWT\u003e
Zanim API obsłuży żądanie, zazwyczaj sprawdza:
exp (czy nie wygasł)iss (oczekiwany issuer)aud (czy token jest przeznaczony dla tego API)Jeśli wszystkie kontrole przejdą, API traktuje użytkownika jako uwierzytelnionego i stosuje reguły autoryzacji (np. uprawnienia do poziomu rekordu).
Ponieważ zegary systemowe driftują, wiele systemów dopuszcza niewielki clock skew przy weryfikacji roszczeń czasowych jak exp (i czasem nbf). Trzymaj ten przesunięcie małe, aby nie przedłużać niezamierzenie ważności tokena.
Wybór miejsca przechowywania determinuje, co atakujący może ukraść i jak łatwo może odtworzyć żądanie przy użyciu tokena.
Przechowywanie w pamięci (często rekomendowane dla SPA) trzyma access token w stanie JS. Czyszczony po odświeżeniu strony, zmniejsza ryzyko „kradzieży później”, ale błąd XSS nadal może go odczytać podczas działania strony. Łącz to z krótkimi access tokenami i mechanizmem odnawiania.
localStorage/sessionStorage są wygodne, ale ryzykowne: każde XSS pozwala na exfiltrację tokenów z pamięci przeglądarki. Jeśli ich używasz, zapobieganie XSS jest obowiązkowe (CSP, escapowanie wyjścia, higiena zależności) i trzymaj tokeny krótko żyjące.
Bezpieczne cookies (często najbezpieczniejszy domyślny wybór dla webu) przechowują tokeny w ciasteczku HttpOnly, tak że JavaScript nie może ich odczytać — zmniejsza to wpływ kradzieży tokena przez XSS. Wadą jest ryzyko CSRF, bo przeglądarki automatycznie dołączają cookies.
Jeśli używasz cookies, ustaw:
HttpOnlySecure (tylko HTTPS)SameSite=Lax lub SameSite=Strict (niektóre cross-site flowy mogą wymagać SameSite=None; Secure)Rozważ także tokeny CSRF dla żądań zmieniających stan.
Na iOS/Android przechowuj tokeny w bezpiecznym magazynie systemowym (Keychain / Keystore-backed storage). Unikaj zwykłych plików lub preferencji. Jeśli model zagrożeń obejmuje urządzenia z rootem/jailbreakiem, zakładaj, że ekstrakcja jest możliwa i polegaj na krótkotrwałych tokenach oraz kontrolach po stronie serwera.
Ogranicz możliwości tokena: używaj minimalnych scope'ów/claimów, trzymaj access tokeny krótkotrwałe i unikaj osadzania wrażliwych danych.
JWT są wygodne, ale wiele incydentów wynika z przewidywalnych błędów. Traktuj JWT jak gotówkę: kto go zdobędzie, zwykle może go użyć.
Jeśli token ważny jest dni lub tygodnie, wyciek daje atakującemu cały ten okres. Preferuj krótkotrwałe access tokeny (minuty) i odnawiaj je bezpiecznym mechanizmem. Jeśli potrzebujesz „zapamiętaj mnie”, zrób to za pomocą refresh tokenów i kontroli po stronie serwera.
Sam ważny podpis to za mało. Weryfikuj iss i aud, oraz waliduj roszczenia czasowe jak exp i nbf.
Dekodowanie to nie weryfikacja. Zawsze weryfikuj podpis po stronie serwera i egzekwuj uprawnienia po stronie serwera.
Unikaj umieszczania JWT w parametrach zapytania. Mogą trafić do historii przeglądarki, logów serwerów, narzędzi analitycznych i nagłówków referer.
Używaj Authorization: Bearer ... zamiast tego.
Zakładaj, że klucze i tokeny mogą wyciec. Rotuj klucze podpisujące, używaj kid by wspierać płynną rotację i miej strategię unieważniania (krótkie czasy życia + możliwość dezaktywacji kont/sesji). Dla wskazówek odnośnie przechowywania tokenów zobacz /blog/where-to-store-jwts-safely.
JWT są użyteczne, ale nie zawsze najlepsze. Pytanie brzmi: czy skorzystasz na samodzielnym tokenie, który można zweryfikować bez odpytywania bazy danych przy każdym żądaniu.
Dla tradycyjnych aplikacji renderowanych po stronie serwera, gdzie proste unieważnianie ma znaczenie, sesje po stronie serwera z HttpOnly cookies często są prostszym i bezpieczniejszym wyborem.
Wybierz JWT, jeśli potrzebujesz bezstanowej weryfikacji między usługami i możesz trzymać tokeny krótkotrwałe.
Unikaj JWT, jeśli potrzebujesz natychmiastowego unieważniania, planujesz przechowywać wrażliwe dane w tokenie, lub możesz użyć ciasteczek sesyjnych bez problemów.
Weryfikuj używając właściwego klucza i oczekiwanego algorytmu. Odrzucaj nieprawidłowe podpisy — bez wyjątków.
exp (wygaśnięcie)Upewnij się, że token nie wygasł.
nbf (not before)Jeśli obecne, upewnij się, że token nie jest używany zbyt wcześnie.
aud (audience)Potwierdź, że token był przeznaczony dla Twojego API/serwisu.
iss (issuer)Potwierdź, że token pochodzi od oczekiwanego issuer.
Waliduj format tokena, egzekwuj maksymalny rozmiar i odrzucaj nieoczekiwane typy roszczeń, aby zmniejszyć liczbę błędów brzegowych.
HS256 (klucz symetryczny): jeden wspólny sekret podpisuje i weryfikuje.
RS256 / ES256 (klucze asymetryczne): prywatny klucz podpisuje; publiczny weryfikuje.
Zasada: jeśli więcej niż jeden niezależny system musi weryfikować tokeny (albo nie ufasz każdemu weryfikatorowi), preferuj RS256/ES256.
iss, aud, identyfikator użytkownika tylko jeśli polityka na to pozwala).Czy JWT są szyfrowane?
Nie domyślnie. Większość JWT jest podpisana, nie szyfrowana, co oznacza, że zawartość można odczytać przez każdego, kto ma token. Użyj JWE lub trzymaj wrażliwe dane poza JWT.
Czy mogę unieważnić JWT?
Niełatwo, jeśli polegasz wyłącznie na samodzielnych access tokenach. Typowe podejścia to krótkotrwałe access tokeny, deny-listy dla wysokiego ryzyka lub refresh tokeny z rotacją.
Jak długo powinno trwać exp?
Tak krótko, jak na to pozwala UX i architektura. Wiele API używa minut dla access tokenów i łączy to z refresh tokenami dla dłuższych sesji.
Jeśli implementujesz uwierzytelnianie JWT w nowym API lub SPA, dużo pracy jest powtarzalne: podłączanie middleware, walidacja iss/aud/exp, ustawianie flag ciasteczek i wyłączanie logowania tokenów.
Z Koder.ai możesz szybko stworzyć aplikację web (React), serwisy backendowe (Go + PostgreSQL) lub aplikację mobilną Flutter przez chatowy workflow — potem iterować w trybie planowania, używać snapshotów i rollbacku przy dopracowywaniu bezpieczeństwa oraz eksportować kod źródłowy, gdy jesteś gotowy. To praktyczny sposób przyspieszający budowę przepływów autoryzacji JWT, zachowując kontrolę nad logiką weryfikacji, strategią rotacji kluczy i ustawieniami wdrożenia/hostingu (w tym niestandardowe domeny).
JWT (JSON Web Token) to zwarty, bezpieczny dla URL-a ciąg znaków, który przenosi roszczenia (pola z danymi) i może być weryfikowany przez serwer. Zwykle wysyła się go w żądaniach API za pomocą:
Authorization: Bearer \u003ctoken\u003eGłówna idea: serwer może zweryfikować integralność tokena (dzięki podpisowi) bez konieczności posiadania rekordu sesji dla każdego żądania.
Uwierzytelnianie sesyjne zwykle przechowuje stan po stronie serwera (rekord sesji identyfikowany przez cookie/ID sesji). W uwierzytelnianiu opartym na JWT klient przedstawia podpisany token przy każdym żądaniu, a API go weryfikuje.
JWT są popularne w przypadku API i architektur wieloserwisowych, ponieważ weryfikacja może odbywać się lokalnie, zmniejszając potrzebę współdzielenia przechowywania sesji.
„Bezustanowość” nadal często oznacza pewne kontrole po stronie serwera, takie jak listy unieważnień, sprawdzenie statusu użytkownika lub obsługa rotacji kluczy.
JWT składa się z trzech części kodowanych Base64URL i oddzielonych kropkami:
header.payload.signatureHeader opisuje sposób podpisania, payload zawiera roszczenia (np. sub, exp, aud), a signature pozwala serwerowi wykryć modyfikacje.
Nie. Standardowe JWT są zwykle podpisane, a nie szyfrowane.
Jeśli potrzebujesz poufności, rozważ JWE (zaszyfrowane tokeny) lub trzymaj wrażliwe dane po stronie serwera i umieszczaj w tokenie tylko identyfikator.
Podpis pozwala serwerowi zweryfikować, że token nie został zmieniony i został wydany przez podmiot posiadający klucz podpisujący.
Nie gwarantuje on jednak:
expTraktuj token jak poświadczenie: jeśli wycieknie, zwykle można go użyć do autoryzacji do czasu wygaśnięcia.
alg informuje weryfikatora, jakiego algorytmu użyto (np. HS256 vs RS256). kid to identyfikator klucza, który pomaga dobrać właściwy klucz podczas rotacji.
Zasady bezpieczeństwa:
Zacznij od standardowych zarejestrowanych roszczeń i ogranicz własne do minimum.
Częste zarejestrowane roszczenia:
JWT to format tokena; OAuth 2.0 i OpenID Connect to protokoły.
Typowe mapowanie:
Ważne: nie używaj ID tokena do wywołań API tylko dlatego, że wygląda jak JWT access token.
Dla aplikacji przeglądarkowych typowe opcje to:
Co najmniej zweryfikuj:
exp (nie wygasł)iss (oczekiwany issuer)aud (przeznaczony dla Twojego API)nbf (jeśli obecny)Dodaj praktyczne zabezpieczenia:
alg.alg: "none".kid prowadził do niebezpiecznego zachowania przy wyszukiwaniu klucza.iss (issuer)sub (subject / identyfikator użytkownika)aud (audience / docelowe API)exp (expiration)iat (issued at)nbf (not before)Unikaj umieszczania sekretów lub wrażliwych danych osobowych w payloadzie, bo są one czytelne w przypadku ujawnienia tokena.
Jeśli używasz cookies, ustaw:
HttpOnlySecure (HTTPS tylko)SameSite=Lax lub SameSite=Strict (niektóre cross-site flowy mogą wymagać SameSite=None; Secure)Rozważ też tokeny CSRF dla żądań zmieniających stan.