Zabezpieczenia interfejsu API REST Przechowywany token vs JWT vs OAuth

104

Wciąż próbuję znaleźć najlepsze rozwiązanie bezpieczeństwa do ochrony interfejsu API REST, ponieważ liczba aplikacji mobilnych i interfejsu API rośnie z każdym dniem.

Próbowałem różnych sposobów uwierzytelniania, ale nadal mam pewne nieporozumienia, dlatego potrzebuję porady kogoś bardziej doświadczonego.

Pozwól mi powiedzieć, jak rozumiem te wszystkie rzeczy. Jeśli coś rozumiem źle, daj mi znać.

O ile interfejs API REST jest bezstanowy, a także ogólnie WEB, musimy wysyłać niektóre dane uwierzytelniające w każdym żądaniu (pliki cookie, token ....). Znam trzy szeroko stosowane mechanizmy uwierzytelniania użytkownika

  1. Token z HTTPS. Używałem tego podejścia wiele razy, ponieważ jest wystarczająco dobry z HTTPS. Jeśli użytkownik poda prawidłowe hasło i login, w odpowiedzi otrzyma token i użyje go do dalszych żądań. Token jest generowany przez serwer i przechowywany, na przykład w tabeli osobno lub w tym samym miejscu, w którym przechowywane są informacje o użytkowniku. Tak więc dla każdego żądania serwer sprawdza, czy użytkownik ma token i czy jest taki sam jak w bazie danych. Wszystko jest bardzo proste.

  2. Token JWT. Ten token jest opisowy, zawiera wszystkie niezbędne informacje o samym tokenie, użytkownik nie może zmienić na przykład daty ważności ani żadnego innego roszczenia, ponieważ ten token jest generowany (podpisany) przez serwer za pomocą tajnego słowa kluczowego. To również jasne. Ale jeden duży problem, osobiście dla mnie, jak unieważnić token.

  3. OAuth 2. Nie rozumiem, dlaczego takie podejście powinno być stosowane, gdy komunikacja jest ustanawiana bezpośrednio między serwerem a klientem. O ile rozumiem, serwer OAuth służy do wydawania tokena z ograniczonym zakresem, aby umożliwić innym aplikacjom dostęp do informacji o użytkowniku bez przechowywania hasła i loginu. To świetne rozwiązanie dla sieci społecznościowych, gdy użytkownik chce się zarejestrować na jakiejś stronie, serwer może poprosić o uprawnienia do uzyskania informacji o użytkowniku, na przykład z Twittera lub Facebooka, i wypełnić pola rejestracyjne danymi użytkownika i tak dalej.

Zastanów się nad mobilnym klientem sklepu internetowego.

Pierwsze pytanie, czy wolę JWT niż token pierwszego typu? O ile potrzebuję zalogować / wylogować użytkownika na kliencie mobilnym, muszę zapisać gdzieś token lub w przypadku JWT, token powinien zostać unieważniony przy wylogowaniu. Do unieważnienia tokena stosuje się różne podejścia. Jednym z nich jest utworzenie listy nieprawidłowych tokenów (czarna lista). Hmm Tabela / plik będzie miał znacznie większy rozmiar niż gdyby token był przechowywany w tabeli i powiązany z użytkownikiem, a po prostu usunięty podczas wylogowywania.

Jakie są więc zalety tokena JWT?

Drugie pytanie dotyczące OAuth, czy powinienem z niego korzystać w przypadku bezpośredniej komunikacji z moim serwerem? Jaki jest cel jeszcze jednej warstwy między klientem a serwerem tylko do wydawania tokena, ale komunikacja nie będzie z oauth server, ale z serwerem głównym. Jak rozumiem, serwer OAuth jest odpowiedzialny tylko za udzielanie aplikacjom zewnętrznym uprawnień (tokenów) do uzyskiwania dostępu do prywatnych informacji użytkownika. Ale moja aplikacja klienta mobilnego nie jest firmą zewnętrzną.

CROSP
źródło
Dzięki, zastanawiałem się nad tym ostatnio. Poszedłem z zarządzaniem sesjami (Beaker) i usuwam tokeny sesji po godzinie. Oauth nie wydawał się odpowiedni.
JasTonAChair

Odpowiedzi:

86

Rozważ pierwszy przypadek. Każdy klient otrzymuje losowy identyfikator, który trwa przez czas trwania sesji - co może potrwać kilka dni, jeśli chcesz. Następnie przechowujesz informacje dotyczące tej sesji gdzieś po stronie serwera. Może to być plik lub baza danych. Załóżmy, że przekazujesz identyfikator za pomocą pliku cookie, ale możesz użyć adresu URL lub nagłówka HTTP.

Identyfikatory sesji / pliki cookie

Plusy:

  • Łatwo kodować zarówno klienta, jak i serwer.
  • Łatwo zniszczyć sesję, gdy ktoś się wyloguje.

Cons:

  • Po stronie serwera należy okresowo usuwać wygasłe sesje, w których klient się nie wylogował.
  • Każde żądanie HTTP wymaga sprawdzenia magazynu danych.
  • Wymagania dotyczące pamięci rosną wraz ze wzrostem liczby aktywnych sesji użytkowników.
  • Jeśli istnieje wiele serwerów HTTP typu front-end, przechowywane dane sesji muszą być dostępne dla wszystkich. Może to być nieco więcej pracy niż przechowywanie go na jednym serwerze. Większe problemy to to, że magazyn danych staje się pojedynczym punktem awarii i może stać się wąskim gardłem.

Tokeny internetowe JSON (JWT)

W drugim przypadku dane są przechowywane w JWT, który jest przekazywany zamiast na serwerze.

Plusy:

  • Problemy z pamięcią masową po stronie serwera zniknęły.
  • Kod po stronie klienta jest łatwy.

Cons:

  • Rozmiar JWT może być większy niż identyfikator sesji. Może to wpłynąć na wydajność sieci, ponieważ jest dołączana do każdego żądania HTTP.
  • Dane przechowywane w JWT są czytelne dla klienta. To może być problem.
  • Po stronie serwera potrzebny jest kod do generowania, sprawdzania poprawności i odczytu JWT. To nie jest trudne, ale jest trochę krzywej uczenia się i od tego zależy bezpieczeństwo.

    Każdy, kto otrzyma kopię klucza podpisu, może utworzyć JWT. Możesz nie wiedzieć, kiedy to się stanie.

    W niektórych bibliotekach był (jest?) Błąd, który akceptował dowolny JWT podpisany algorytmem „none”, aby każdy mógł tworzyć JWT, którym serwer ufałby.

  • Aby odwołać JWT przed jego upływem, musisz użyć listy odwołania. W ten sposób powrócisz do problemów z pamięcią po stronie serwera, których starałeś się uniknąć.

OAuth

Często OAuth służy do uwierzytelniania (tj. Tożsamości), ale może być wykorzystywany do udostępniania innych danych, takich jak lista treści zakupionych przez użytkownika i do pobrania. Można go również użyć do udzielenia dostępu do zapisu danych przechowywanych przez stronę trzecią. Możesz użyć OAuth do uwierzytelnienia użytkowników, a następnie użyć pamięci po stronie serwera lub JWT dla danych sesji.

Plusy:

  • Brak kodu umożliwiającego zarejestrowanie się lub zresetowanie hasła.
  • Brak kodu do wysłania wiadomości e-mail z linkiem weryfikacyjnym, a następnie zweryfikowania adresu.
  • Użytkownicy nie muszą uczyć się / zapisywać innej nazwy użytkownika i hasła.

Cons:

  • Użytkownik może polegać na usługach zewnętrznych. Jeśli ich usługa spadnie lub przestaną, musisz wymyślić coś innego. Np .: w jaki sposób migrujesz dane konta użytkownika, jeśli jego tożsamość zmieni się z „[email protected]” na „[email protected]”?
  • Zwykle musisz napisać kod dla każdego dostawcy. np. Google, Facebook, Twitter.
  • Ty lub Twoi użytkownicy mogą mieć obawy dotyczące prywatności. Dostawcy wiedzą, którzy z ich użytkowników korzystają z Twojej usługi.
  • Ufasz dostawcy. Możliwe jest, że dostawca wyda tokeny ważne dla jednego użytkownika komuś innemu. Może to być zgodne z prawem lub nie.

Różne

  • Zarówno identyfikatory sesji, jak i JWT mogą być kopiowane i używane przez wielu użytkowników. Możesz zapisać adres IP klienta w JWT i zweryfikować go, ale to uniemożliwia klientom roaming z powiedz Wi-Fi do sieci komórkowej.
Chad Clark
źródło
Aby dodać do swojej odpowiedzi, oAuth może nie być przydatny, gdy użytkownik chce się zarejestrować przy użyciu swoich kont firmowych, które zwykle nie są powiązane ani powiązane z żadnymi witrynami sieci społecznościowych ani google.
Aftab Naveed,
5
Nie wiem, dlaczego jest to zaakceptowana odpowiedź? to nie jest odpowiedź na prawdziwe pytanie, tylko reformowania pytanie w inny sposób
amd
1
Mówisz: „Dane przechowywane w JWT są czytelne dla klienta. To może być problem. Dlaczego nie użyć JWE, jeśli to jest problem?
Srebrny
Ta odpowiedź myli jabłka i pomarańcze. Nie należy ich porównywać z OAuth 2.0 (specyfikacja „autoryzacja”). To, o czym OP musi wiedzieć, to: „Przepływ hasła właściciela zasobów” - czyli uwierzytelnianie jako dotacja.
Onur Yıldırım
5

Zadaj sobie pytanie, dlaczego musisz unieważnić oryginalny token.

Użytkownik loguje się, generowany jest token i wyłącza się aplikacja.

Użytkownik naciska wylogowanie, generowany jest nowy token i zastępuje oryginalny token. Po raz kolejny wszystko jest w porządku.

Wygląda na to, że martwisz się sytuacją, w której oba tokeny wiszą w pobliżu. Co się stanie, jeśli użytkownik wyloguje się, a następnie w jakiś sposób złoży żądanie za pomocą zalogowanego tokena. Jak realistyczny jest ten scenariusz? Czy to tylko problem podczas wylogowania, czy jest wiele możliwych scenariuszy, w których wiele tokenów może stanowić problem?

Sam nie sądzę, że warto się martwić. Jeśli ktoś przechwytuje i dekoduje zaszyfrowane dane https, masz o wiele większe problemy.

Możesz zapewnić sobie dodatkową ochronę, umieszczając czas ważności na oryginalnym tokenie. Jeśli więc zostanie skradziony lub coś takiego, byłoby dobrze tylko przez krótki okres czasu.

W przeciwnym razie myślę, że musisz mieć informacje o stanie na serwerze. Nie umieszczaj na czarnej liście tokenów, ale zamiast tego umieść na białej liście podpis bieżącego tokena.

Cerad
źródło
2
Jeśli założysz, że niektórzy z twoich klientów są złośliwi, łatwo zauważyć, że sesja zostanie skopiowana i ponownie wykorzystana, i musisz temu zaradzić na serwerze.
Michael Shaw,
1
Zły pomysł, może być później wykorzystany przez hakera lub po prostu brutalny zmuszony ...
CROSP
2
Wyobraź sobie, że użytkownik chce się wylogować ze wszystkich innych urządzeń, korzystanie z JWT nie jest możliwe.
amd
@amd niemożliwe? Co jeśli dodam nonce = (losowo) i jeśli użytkownik się wyloguje, zastąp nonce. Wydaje się prosty i skuteczny.
Simon B.
3

Możesz poradzić sobie z problemami JWT, o których wspomniałeś, przechowując wartość soli razem z użytkownikiem i używając soli jako części tokena dla użytkownika. Następnie, gdy musisz unieważnić token, po prostu zmień sól.

Wiem, że minęło kilka lat, ale teraz zrobiłbym to inaczej. Myślę, że zapewniłbym, że tokeny dostępu miały stosunkowo krótki okres użytkowania, powiedzmy godzinę. Będę również musiał używać tokenów odświeżania, które były stanowe na serwerze, a następnie, gdy chciałem zakończyć czyjąś sesję, odwołałem token odświeżania, usuwając go z serwera. Następnie po godzinie użytkownik zostanie wylogowany i będzie musiał zalogować się ponownie, aby odzyskać dostęp.

RibaldEddie
źródło
4
Ale znowu w tym przypadku staje się pełna, więc jaki jest powód, aby utworzyć sól lub zastosować inne podejście, możesz po prostu zapisać token w tabeli i usunąć, kiedy powinien zostać unieważniony
CROSP
2
Możesz także unieważnić na podstawie czasu.
RibaldEddie,
Jaka jest różnica między czasem wygaśnięcia w tym przypadku? Jak mogę unieważnić token na podstawie czasu, kiedy użytkownik chce się wylogować z klienta mobilnego? Wydaje się, że w tym przypadku API nie może być bezstanowe. Jakie jest najbardziej odpowiednie i bezpieczne rozwiązanie niż?
CROSP
2
Najbardziej odpowiednie do wylogowania z jednego urządzenia jest upewnienie się, że oprócz soli używasz clientId. Sugeruję, aby spojrzeć na specyfikację tokena okaziciela Oauth-jwt w celu uzyskania wglądu.
RibaldEddie,
Dzięki za odpowiedź, ale w ogóle nie rozumiem, dlaczego w takim przypadku powinienem używać OAuth.
CROSP