JWT refresh token - własna implementacja

0

Chciałbym zabezpieczyć swoją aplikację tokenami JWT. Robię to pierwszy raz, a że security to poważny aspekt, przedstawiam tutaj swoją ogólną koncepcję:

  1. User po zalogowaniu dostaje access_token (JWT) ważny 15 minut oraz refresh_token (randomowy String) ważny 2 tygodnie
  2. refresh_token zapisywany jest w local storage, access_token local storage + cookie (ze względu na SSR)
  3. refresh_token zapisuję również na serwerze, wraz z nazwą użytkownika i datą jego wygaśnięcia
  4. request z nieważnym access_token:
    • zwraca np. 401 Unauthorized
    • wykonuje kolejny request z access_token i refresh_token
    • pobiera nazwę użytkownika z JWT i sprawdza czy refresh_token jest do niego przypisany i ważny
    • jeśli tak, to zwraca nowy access_token i refresh_token, aktualizuje odpowiednio po stronie serwera i użytkownika
    • jeśli nie to użytkownik zostaje przekierowany na stronę logowania
  5. refresh_tokeny są okresowo czyszczone po stronie serwera

Jeśli użytkownik się wyloguje lub usunie konto, to czyszczę mu tokeny po stronie klienta.

Problem, który widzę, to w momencie kiedy strona wykona dwa równoczesne requesty z przeterminowanym access_token. Pierwszy wyśle mu nowy token, drugi go wyloguje, bo refresh_token będzie już nieprawidłowy. Na chwilę obecną nie wiem za bardzo jak to rozwiązać po stronie frontu.

Czy są tu jeszcze jakieś babole? Czy takie rozwiązanie jest w miarę OK? Czy implementując to znowu wynajduję koło na nowo? :)

3

Tak, olej JWT i zamiast tego użyj ciastek. Będzie zdecydowanie bezpieczniej niż JWK i refresh token. Ogólnie JWT jest spoko dla stateless services, przykładowo serwer plików, gdzie masz ogólnie krótki czas życia tokenu i nie potrzebujesz go refreshować, jak zaczyna być potrzeba refreshu oraz masz statefull service (co wygląda z Twojego opisu - "usunie konto") to tracisz wszystkie zalety JWT nad ciastkiem z sesją.

Całkiem dobry (trochę ironiczny) flowchart porównujący ciastka i JWT (polecam również artykuł).

0

Ten flowchart dość celnie trafia w moje wątpliwości ;)

Rzeczywiście w swojej aplikacji nie widzę zbytnio korzyści z JWT nad sesją. Recz w tym, że do backendu używam Spring WebFlux, a tam chyba nie mam wbudowanego mechanizmu zarządzania sesją i "remember me" (nie chcę automatycznie wylogowywać usera w ciągu 2 tygodni). Także zostaje JWT. Pewnie tylko w ciastku, bez local storage.

0

@hauleth Co jeśli chciałbym mieć klienta jako przeglądarkę i aplikację mobilną. Na przeglądarce używać cookie i sesje, a na aplikacji mobilnej JWT i refresh token?

1

@discoStar: a po co? Nie lepiej używać ciastek i sesji w obu miejscach?

0

Rob Winch poleca JWT do aplikacji mobilnych, ale spróbuję z ciasteczkami. Jestem ciekaw jak to wyjdzie.

3

Z jakiegoś powodu ludzie uważają, że:

add_header(connection, "authorization", "Bearer " <> jwt_token)

Jest prostsze niż:

set_cookie(connection, "session_id", session_id)

Nie rozumiem z czym jest tutaj problem, zwłaszcza, że ostatnimi czasy coraz popularniejsze są stateful clients do HTTP, więc to już zupełnie przestaje być jakimkolwiek problemem.

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0