Buduję interfejs API RESTful, który korzysta z tokenów JWT do uwierzytelniania użytkowników (wydawanych przez login
punkt końcowy i wysyłanych we wszystkich nagłówkach później), a tokeny należy odświeżyć po ustalonym czasie (wywoływanie renew
punktu końcowego, który zwraca odnowiony token ).
Możliwe jest, że sesja API użytkownika utraci ważność przed wygaśnięciem tokena, dlatego wszystkie moje punkty końcowe zaczynają się od sprawdzenia, czy: 1) token jest nadal ważny i 2) sesja użytkownika jest nadal ważna. Nie ma możliwości bezpośredniego unieważnienia tokena, ponieważ klienci przechowują go lokalnie.
Dlatego wszystkie moje punkty końcowe muszą sygnalizować moim klientom dwa możliwe warunki: 1) że nadszedł czas na odnowienie tokena lub 2) że sesja stała się nieważna i nie mają już dostępu do systemu. Mogę wymyślić dwie alternatywy dla moich punktów końcowych, aby zasygnalizować swoim klientom, gdy wystąpi jeden z dwóch warunków (zakładamy, że klienci mogą być dostosowani do dowolnej opcji):
- Zwróć kod http 401 (nieautoryzowany), jeśli sesja stała się nieprawidłowa, lub zwróć kod 412 (warunek wstępny nie powiódł się) po wygaśnięciu tokena i czas zadzwonić do
renew
punktu końcowego, który zwróci kod 200 (ok). - Zwraca 401 za zasygnalizowanie, że sesja jest nieprawidłowa lub token wygasł. W takim przypadku klient natychmiast wywoła
renew
punkt końcowy, jeśli zwróci 200, token zostanie odświeżony, ale jeślirenew
również zwróci 401, oznacza to, że klient jest poza systemem.
Którą z dwóch powyższych alternatyw poleciłbyś? Który z nich byłby bardziej standardowy, prostszy do zrozumienia i / lub bardziej RESTful? A może poleciłbyś w ogóle inne podejście? Czy widzisz jakieś oczywiste problemy lub zagrożenia bezpieczeństwa związane z którąkolwiek z tych opcji? Dodatkowe punkty, jeśli Twoja odpowiedź zawiera odniesienia zewnętrzne, które potwierdzają Twoją opinię.
AKTUALIZACJA
Chłopaki, proszę skoncentrować się na prawdziwym pytaniu - która z dwóch alternatywnych kodów HTTP sygnalizujących przedłużenie / unieważnienie sesji jest najlepsza? Nie przejmuj się faktem, że mój system korzysta z JWT i sesji po stronie serwera, to jest swoiste dla mojego API dla bardzo specyficznych reguł biznesowych, a nie tej części, której szukam pomocy;)
źródło
Odpowiedzi:
To brzmi jak przypadek uwierzytelnienia kontra autoryzacja .
JWT są kryptograficznie podpisanymi oświadczeniami o inicjatorze żądania. JWT może zawierać oświadczenia takie jak „To żądanie dotyczy użytkownika X”, a „Użytkownik X ma role administratora”. Uzyskanie i dostarczenie tego dowodu za pomocą haseł, podpisów i TLS jest domeną uwierzytelniania - udowadniając, że jesteś tym, za kogo się podajesz.
Jakie roszczenia te myśli z serwerem - jakie konkretne role użytkowników i są dopuszczone do zrobienia - jest problem autoryzacji . Różnicę między tymi dwoma można opisać za pomocą dwóch scenariuszy. Załóżmy, że Bob chce wejść do sekcji magazynu ograniczonego w magazynie swojej firmy, ale najpierw musi poradzić sobie ze strażnikiem o imieniu Jim.
Scenariusz A - Uwierzytelnianie
Scenariusz B - Autoryzacja
Czasy wygaśnięcia JWT to urządzenie uwierzytelniające, które zapobiega kradzieży ich przez innych. Jeśli wszystkie twoje JWT mają pięciominutowy okres ważności, nie będzie to aż tak wielka sprawa, jeśli zostaną skradzione, ponieważ szybko staną się bezużyteczne. Jednak omawiana zasada „wygasania sesji” brzmi jak problem z autoryzacją. Pewna zmiana stanu oznacza, że użytkownik X nie może już robić czegoś, co kiedyś był w stanie zrobić. Na przykład użytkownik Bob mógł zostać zwolniony - nie ma znaczenia, że jego odznaka mówi, że jest Bobem, ponieważ samo bycie Bobem nie daje mu już żadnej władzy w firmie.
Te dwa przypadki mają różne kody odpowiedzi HTTP:
401 Unauthorized
i403 Forbidden
. Niestety kod o nazwie 401 dotyczy problemów z uwierzytelnianiem, takich jak brakujące, wygasłe lub odwołane poświadczenia. 403 służy do autoryzacji, gdzie serwer dokładnie wie, kim jesteś, ale po prostu nie możesz robić tego, co próbujesz zrobić. W przypadku usunięcia konta użytkownika próba zrobienia czegoś za pomocą JWT w punkcie końcowym spowoduje 403 zabronioną odpowiedź. Jeśli jednak JWT utraci ważność, poprawny wynik to 401 Nieautoryzowany.Częstym wzorem JWT jest posiadanie tokenów „długowiecznych” i „krótkotrwałych”. Tokeny długożyjące są przechowywane na kliencie jak tokeny krótkotrwałe, ale mają ograniczony zakres i są używane tylko z systemem autoryzacji do uzyskiwania tokonów krótkotrwałych. Długowieczne tokeny, jak sama nazwa wskazuje, mają bardzo długie okresy ważności - możesz ich użyć, aby poprosić o nowe tokeny przez kilka dni lub tygodni. Tokeny krótkotrwałe to tokeny, które opisujesz, używane z bardzo krótkim czasem przydatności do użycia w systemie. Tokeny długowieczne są przydatne do wdrożenia funkcji Remember Me, więc nie trzeba podawać hasła co pięć minut, aby uzyskać nowy token krótkotrwały.
Problem „unieważnienia sesji”, który opisujesz, brzmi podobnie do próby unieważnienia długowiecznego JWT, ponieważ te krótkotrwałe rzadko są przechowywane po stronie serwera, a te długofalowe są śledzone na wypadek konieczności ich odwołania. W takim systemie próba uzyskania poświadczeń za pomocą odwołanego długowiecznego tokena skutkowałaby 401 nieautoryzowaniem, ponieważ użytkownik może technicznie być w stanie uzyskać poświadczenia, ale token, którego używają, nie jest odpowiedni do tego zadania. Następnie, gdy użytkownik próbuje uzyskać nowy długowieczny token przy użyciu swojej nazwy użytkownika i hasła, system może odpowiedzieć 403 Forbidden, jeśli zostanie wyrzucony z systemu.
źródło
Sesja interfejsu API jest rzeczą, która w ogóle nie powinna istnieć w świecie RESTful. Operacje RESTful powinny być bezstanowe, sesja zawiera stan i dlatego nie ma miejsca w świecie RESTful.
JWT powinien być Twoim jedynym sposobem ustalenia, czy użytkownik nadal kwalifikuje się do uzyskania dostępu do punktu końcowego, czy nie. Sesja nie powinna odgrywać absolutnie żadnej roli. Jeśli tak, nie masz interfejsu API RESTful.
Po całkowitym wyeliminowaniu sesji, co należy zrobić, jeśli dąży się do interfejsu API RESTful, i należy użyć JWT tylko jako czynnika uwierzytelniającego, użytkownik jest uprawniony do korzystania z punktu końcowego lub nie - w takim przypadku
401 Unauthorized
kod odpowiedzi jest odpowiedni - i powinien wywołaćrenew
punkt końcowy zgrant_type=refresh_token
jakąkolwiek identyfikacją odnowienia, której używasz.Aktualizacja:
Z komentarza wynika, że przepływ sprawdzania poprawności używanego obecnie JWT jest niepoprawny. Walidacja powinna wyglądać następująco:
Serwer
RESTful API
musi sprawdzić poprawność tokena wysyłanego jako autoryzacja. To nie jest odpowiedzialnośćClient
. Wygląda na to, że obecnie tego nie robisz. W ten sposób zaimplementuj weryfikację JWT, a nie potrzebujesz sesji.źródło
Wyznaję więc, że nie ma dla mnie sensu martwić się, które podejście jest najbardziej RESTfulne, gdy już łamiesz konwencje REST podczas sesji, ale rozumiem, że spełniasz wymagania biznesowe.
Z punktu widzenia REST klient albo jest uwierzytelniany, albo nie. Architektura nie dba o to, dlaczego (to wstrzykuje niepotrzebny stan), więc aby odpowiedzieć na twoje główne pytanie, w ogóle nie miałbym odnawiać punktu końcowego. Zalogowany klient po prostu zawsze wyśle swój JWT, a serwer zawsze go potwierdzi i albo zaakceptuje, wysyłając odpowiedni kod sukcesu na podstawie akcji 200, 201 itd.), Albo odrzuci odpowiednio 401 lub 403.
Teraz JWT zostanie powiązany z jakimś kontem. To konto może być zablokowane, zdławione lub cokolwiek innego, więc sam token może być ważny, ale akcja nadal może zostać odrzucona w innym miejscu. Jeśli przypadek jest taki, że konto użytkownika jest zablokowane z powodu reguł biznesowych, to nadal jest to 401 lub 403, w zależności od tego, ile informacji chcesz przekazać klientowi (różne firmy mają różne opinie na ten temat).
Na koniec, jeśli twierdzisz, że konto może zostać odblokowane i ważne, ale JWT musi zostać tylko odwołane, to nadal będę trzymać 401 lub 403 i utrzymywać coś w rodzaju listy unieważnień certyfikatów nieprawidłowych JWT, które możesz umieścić w , o ile czyści się sam po wygaśnięciu JWT (większość baz danych ma na to sposób lub zdarzenia w kodzie aplikacji).
źródło