OAuth2 ROPC czy Basic Auth dla publicznych interfejsów API REST?

21

Konkretnym przypadkiem użycia, który mnie tutaj interesuje, jest uwierzytelnianie klientów REST względem publicznie dostępnych punktów końcowych serwera (takich jak publiczny interfejs API REST).

Najprostszym rozwiązaniem jest tutaj uwierzytelnianie podstawowe . Ale często słyszę OAuth2 reklamowany jako doskonałe rozwiązanie uwierzytelniania w prawie wszystkich okolicznościach.

Chodzi o to, że jedynym typem dotacji OAuth2, który jest możliwy dla klienta REST uwierzytelniającego się na serwerze REST, są poświadczenia hasła właściciela zasobu (ROPC) , ponieważ przydziały kodu i niejawne przydziały wymagają interfejsu użytkownika / strony internetowej (hostowanej przez serwer uwierzytelniania) użytkownik, aby się zalogować i ręcznie autoryzować aplikację kliencką.

Sposób działania ROPC polega na wysłaniu nazwy użytkownika / hasła właściciela zasobu oraz identyfikatora klienta jako parametrów ciągu zapytania ?!? Jest to nawet mniej bezpieczne (IMHO) niż Basic Auth, które przynajmniej base-64 koduje poświadczenia i wysyła je do nagłówka, który może być zaszyfrowany przez TLS!

Pytam więc: czy w kontekście publicznych interfejsów API REST OAuth2 ROPC jest naprawdę lepszy niż Basic Auth? Co jest bardziej bezpieczne niż OAuth2 ROPC?


Aktualizacja

Właśnie przeczytałem ten znakomity artykuł, który wyjaśnia bezpieczeństwo REST Amazon nie oparte na OAuth2 dla AWS. Zasadniczo jest to rozwiązanie oparte na kluczu prywatnym, w którym generowane są skróty dla każdego żądania REST i wysyłane jako wózki boczne obok normalnego (niezaszyfrowanego) żądania. Tylko klient i serwer znają klucz prywatny, więc gdy serwer otrzyma żądanie (ponownie zawierające normalne żądanie + żądanie mieszania), serwer wyszukuje klucz prywatny klienta, stosuje ten sam skrót do normalnego żądania, i następnie porównuje dwa skróty.

Brzmi to o wiele bardziej skomplikowane, złożone i bezpieczne niż ROPC OAuth2! O ile nie brakuje mi tutaj czegoś ważnego , OAuth2 ROPC właśnie wysyła client_id, usernamea passwordjako ciąg znaków zapytania ... całkowicie i całkowicie niezabezpieczony! To rozwiązanie oparte na HMAC / hash wydaje się być znacznie bardziej imponujące i bezpieczne.

Chodzi o to, że nawet autor tego artykułu mówi dalej:

Powinieneś również powoli zdać sobie sprawę i zaakceptować, że w pewnym momencie będziesz musiał wdrożyć OAuth ...

Ba-ba-bwhat?!?! Jeśli OAuth2 jest mniej bezpieczny niż to sprytne rozwiązanie oparte na HMAC / hash, dlaczego autor tego artykułu uważa, że ​​OAuth musi zostać w pewnym momencie zaakceptowany. Jestem zmieszany.

smeeb
źródło
O jakim kliencie mówisz? Zakładam, że większość klientów będzie miała interfejs użytkownika. W takim przypadku możesz załadować stronę logowania OAuth w widoku internetowym (komputer, urządzenie mobilne) lub przekierować na nią bezpośrednio (internet). Nie rozumiem, dlaczego musisz unikać interfejsu użytkownika.
decyklon
@decyclone proszę przeczytać pierwsze zdanie pytania! Mówię o klientach REST (bezgłowy HTTP) uwierzytelniających się przeciwko usługom REST.
smeeb
Pytanie, które zadaję, brzmi: czy ten klient ma w ogóle jakiś interfejs użytkownika? Nawet jeśli nie, widziałem, że aplikacje bez interfejsu użytkownika wyświetlają okno dialogowe przynajmniej do uwierzytelnienia.
decyklon
@decyclone żaden czysty klient REST nie ma żadnego interfejsu użytkownika, chociaż interfejsy użytkownika zwykle używają czystego klienta REST do łączenia się z usługą REST. Jednym z przypadków użycia jest narzędzie wiersza polecenia, które używa klienta REST do wysyłania poleceń użytkownika (wprowadzonych do powłoki) do usługi REST. Wyskakiwanie interfejsu użytkownika z powłoki po prostu nie jest tutaj akceptowalnym rozwiązaniem.
smeeb
1
Należy jednak zauważyć, że istnieje wiele innych przypadków użycia poza wierszem poleceń / powłoką. Innym przykładem użycia jest klient Java / Ruby / Python czysty REST / HTTP, który nie ma interfejsu użytkownika i może działać na serwerze zaplecza, który nie ma interfejsu użytkownika. Serwer zaplecza musi komunikować się z innym serwerem zaplecza za pośrednictwem usługi REST. W tym przypadku nie tylko niewygodne i pospieszne byłoby włożenie interfejsu użytkownika, gdy serwer zaplecza nr 1 musi komunikować się z serwerem zaplecza nr 2, prawdziwy problem polega na tym, że nie ma przeglądarki / klienta interfejsu użytkownika wyświetlającego stronę logowania i nie ma człowieka będąc tam, aby się zalogować !!!
smeeb

Odpowiedzi:

24

Odpowiedź na twoje pytanie może być na poziomie kodu, protokołu lub architektury. Spróbuję podsumować tutaj większość problemów na poziomie protokołu, ponieważ jest to zwykle krytyczne w analizie zalet i wad. Należy pamiętać, że OAuth2 to znacznie więcej niż poświadczenia hasła właściciela zasobu, które zgodnie ze specyfikacją istnieją z „starszych lub migracyjnych powodów”, są uważane za „wyższe ryzyko niż inne typy dotacji”, a specyfikacja wyraźnie stwierdza, że ​​klienci i serwery autoryzacji „POWINIEN zminimalizować użycie tego rodzaju grantu i w miarę możliwości wykorzystywać inne typy grantu”.

Nadal istnieje wiele zalet korzystania z ROPC w porównaniu z podstawowym uwierzytelnianiem, ale zanim do tego przejdziemy, zrozumiemy podstawową różnicę protokołu między OAuth2 i podstawowym uwierzytelnianiem. Proszę o wyrozumiałość, gdy je wyjaśnię i przybędę do ROPC później.

Przepływy uwierzytelnienia użytkownika

Istnieją cztery role zdefiniowane w specyfikacji OAuth2. Przykładami są:

  1. Właściciel zasobu: użytkownik, który ma dostęp do niektórych zasobów, np. W twoim przypadku różni użytkownicy mogą mieć inny poziom dostępu do interfejsu API REST;
  2. Klient: zwykle aplikacja, z której korzysta użytkownik, i potrzebuje dostępu do zasobu, aby świadczyć usługi na rzecz użytkownika;
  3. Serwer zasobów: interfejs API REST w twoim przypadku; i
  4. Serwer autoryzacji: serwer, na którym prezentowane są poświadczenia użytkownika i który będzie uwierzytelniał użytkownika.

Po uruchomieniu aplikacji klienckiej przyznaje się dostęp do zasobów na podstawie użytkownika. Jeśli użytkownik ma uprawnienia administratora, zasoby i operacje dostępne dla użytkownika w interfejsie API REST mogą być czymś znacznie większym niż użytkownik bez uprawnień administratora.

OAuth2 umożliwia także korzystanie z jednego serwera autoryzacji z wieloma klientami i wieloma zasobami. Na przykład serwer zasobów może akceptować uwierzytelnianie użytkownika za pomocą Facebooka (który w takim przypadku może działać jako serwer autoryzacji). Kiedy więc użytkownik uruchomi aplikację (tj. Klienta), wysyła użytkownika do Facebooka. Użytkownik wpisuje swoje dane uwierzytelniające na Facebooku, a klient otrzymuje „token”, który może przedstawić serwerowi zasobów. Serwer zasobów patrzy na token i akceptuje go po sprawdzeniu, że Facebook faktycznie go wystawił i umożliwia użytkownikowi dostęp do zasobu. W takim przypadku klient nigdy nie widzi poświadczeń użytkownika (tj. Poświadczeń na Facebooku).

Załóżmy jednak, że zarządzasz tożsamościami użytkownika (i masz serwer autoryzacji) zamiast Facebooka, który już udziela tokenów klientowi. Załóżmy teraz, że masz partnera i chcesz zezwolić jego aplikacji (tj. Klientowi) na dostęp do interfejsu API REST. W przypadku podstawowego uwierzytelnienia (lub nawet ROPC) użytkownik poda poświadczenia temu klientowi, który wyśle ​​je do serwera autoryzacji. Serwer autoryzacji dostarczy token, którego klient może użyć do uzyskania dostępu do zasobów. Niestety oznacza to, że poświadczenia użytkownika są teraz widoczne również dla tego klienta. Jednak nie chcesz, aby aplikacja partnera (która mogła być spoza organizacji) nawet znała hasło użytkownika. To teraz problem bezpieczeństwa. Aby osiągnąć ten cel,

Zatem w przypadku OAuth2 idealnie byłoby nie używać ROPC w takich przypadkach, a raczej użyć innego, takiego jak przepływ kodu autoryzacji. Chroni to każdą aplikację przed znajomością poświadczeń użytkownika, które są prezentowane tylko serwerowi autoryzacji. W ten sposób poświadczenia użytkownika nie są wyciekane. Te same problemy dotyczą podstawowego uwierzytelnienia, ale w następnej sekcji wyjaśnię, w jaki sposób ROPC jest jeszcze lepszy, ponieważ poświadczenia użytkownika nadal nie muszą być przechowywane przez klienta w ROPC, aby klienci mieli stały dostęp.

Pamiętaj, że gdy użytkownik przejdzie do serwera autoryzacji, serwer autoryzacji może również poprosić użytkownika o potwierdzenie, że chce zezwolić klientowi na dostęp do zasobów w jego imieniu, czy też nie. Dlatego nazywa się to serwerem autoryzacji, ponieważ proces autoryzacji klienta do dostępu do zasobów jest związany z tym procesem. Jeśli użytkownik nie autoryzuje klienta, nie uzyska dostępu do zasobów. Podobnie, jeśli sam użytkownik nie ma dostępu do zasobów, serwer autoryzacji może nadal odmówić dostępu i nie wydać tokena.

W podstawowym uwierzytelnianiu nawet serwer autoryzacji i serwer zasobów są połączone w jedną całość. W związku z tym serwer zasobów chce autoryzować użytkownika, więc prosi o poświadczenia od klienta. Klient dostarcza poświadczenia, które są używane przez serwer zasobów do uwierzytelnienia użytkownika. Oznacza to, że wiele serwerów zasobów będzie zasadniczo wymagało poświadczeń od użytkownika.

Wydanie tokena

Klienci pobierają tokeny z serwera autoryzacji, przechowują je i używają do uzyskiwania dostępu do zasobów (więcej szczegółów na temat samych tokenów poniżej). Klienci nigdy nie znają hasła użytkownika (w przepływach innych niż ROPC) i nie muszą go przechowywać. W ROPC, chociaż klienci znają hasło użytkownika, nadal nie muszą go przechowywać, ponieważ używają tych tokenów do uzyskiwania dostępu do zasobów. Natomiast w przypadku podstawowego uwierzytelniania, jeśli klient nie chce, aby użytkownik podawał poświadczenia w każdej sesji, wówczas musi przechowywać hasło użytkownika, aby móc je podać następnym razem. Jest to poważna wada korzystania z podstawowego uwierzytelniania, chyba że klient jest tylko aplikacją internetową, w którym to przypadku pliki cookie mogą rozwiązać niektóre z tych problemów. W przypadku aplikacji natywnych zazwyczaj nie jest to możliwe.

Istnieje inny aspekt OAuth2, związany z tym, jak tokeny są wydawane i działają. Gdy użytkownik dostarczy dane uwierzytelniające do serwera autoryzacji (nawet w ROPC), serwer autoryzacji może nadać jeden lub więcej z dwóch typów tokenów: 1) token dostępu i 2) token odświeżania.

Tokeny dostępu są wysyłane do serwera zasobów, który zapewni dostęp do zasobów po ich sprawdzeniu, i zazwyczaj mają krótki okres użytkowania, np. 1 godz. Tokeny odświeżające są wysyłane do serwera autoryzacji przez klienta, aby uzyskać kolejny token dostępu, gdy wygasa, i zwykle mają długi okres użytkowania (np. Kilka dni do miesięcy lub nawet lat).

Gdy klient udostępnia token dostępu do serwera zasobów, patrzy na token, a po sprawdzeniu poprawności przegląda token, aby ustalić, czy zezwolić na dostęp, czy nie. Tak długo, jak token dostępu jest ważny, klient może go używać. Załóżmy, że użytkownik zamyka aplikację i uruchamia ją następnego dnia, a token dostępu wygasł. Teraz klient wykona połączenie z serwerem autoryzacji i przedstawi token odświeżania, zakładając, że nie wygasł. Serwer autoryzacji, ponieważ już wydał token, weryfikuje go i może stwierdzić, że użytkownik nie musi ponownie podawać poświadczeń, a tym samym daje klientowi kolejny token dostępu. Klient ma teraz ponownie dostęp do serwera zasobów. W ten sposób zwykle aplikacje klienckie na Facebooku i Twitterze pytają o dane uwierzytelniające raz, a następnie nie wymagają od użytkownika ponownego podawania danych uwierzytelniających. Aplikacje te nigdy nie muszą znać poświadczeń użytkowników, a jednak mogą uzyskiwać dostęp do zasobów za każdym razem, gdy użytkownik uruchomi aplikację.

Teraz użytkownik może wejść na serwer autoryzacji (np. W swoim profilu użytkownika na Facebooku), zmienić hasło bez wpływu na aplikacje klienckie. Wszystkie będą nadal działać poprawnie. Jeśli użytkownik straci urządzenie, na którym miał już aplikację z tokenami odświeżania, może nakazać serwerowi autoryzacji (np. Facebookowi) „wylogowanie” z tych aplikacji, które serwer autoryzacji (tj. Facebook) wykona, nie honorując żadnego z istniejących odświeżyć tokeny i zmusić użytkownika do ponownego podania poświadczeń podczas próby uzyskania dostępu do zasobów za pośrednictwem tych aplikacji.

JWT to po prostu format tokena, który jest zwykle używany z OAuth2 i OpenID Connect. Metody podpisywania tokena i sprawdzania jego poprawności są również znormalizowane z bibliotekami dostępnymi dla nich zamiast z każdym serwerem zasobów wdrażającym jeszcze inne rozwiązanie. Zaletą jest zatem możliwość ponownego użycia sprawdzonego kodu, który jest nadal obsługiwany.

Wpływ na bezpieczeństwo

Uwierzytelnianie podstawowe będzie słabsze, gdy którykolwiek z powyższych scenariuszy będzie widoczny na zdjęciu. Istnieje również rozbudowany model zagrożeń dla OAuth2 dostępny dla programistów, którzy mogą wykorzystać zawarte w nim sugestie, aby uniknąć typowych luk w swoich implementacjach. Jeśli przejdziesz przez model zagrożenia, zobaczysz, że obejmuje on również wiele luk związanych z implementacją (takich jak otwarty readresator i CSRF). W tej odpowiedzi nie przeprowadziłem porównania tych z podstawowym uwierzytelnianiem.

Ostatnią ważną zaletą protokołu OAuth2 jest to, że protokół jest ustandaryzowany i honoruje go wiele serwerów autoryzacji, klientów i serwerów zasobów. Liczne biblioteki są dostępne dla programistów, które są utrzymywane, więc ponieważ w implementacjach wykryte zostaną problemy bezpieczeństwa, biblioteki są aktualizowane przy jednoczesnym zapewnieniu interoperacyjności.

Wniosek

Jeśli piszesz nową aplikację, IMO, idealnym rozwiązaniem byłoby uniknięcie zarówno podstawowego uwierzytelnienia, jak i ROPC ze względu na związane z nimi problemy. Jednak każda aplikacja ma inne potrzeby, harmonogramy, biegłość programistyczną itp., Więc decyzja jest podejmowana indywidualnie. Ale nawet jeśli nie potrzebujesz więcej niż podstawowego uwierzytelnienia, wybierając go, możesz zablokować się w architekturze, która może nie być łatwa do rozszerzenia (np. Jeśli będziesz mieć wiele serwerów w przyszłości, niekoniecznie będziesz chciał mieć użytkownik podaje poświadczenia każdemu z nich, a tylko raz przekazuje serwer autoryzacji, który może rozdawać tokeny itp.)

Zauważ, że nie odniosłem się do twojego komentarza na temat tego, w jaki sposób poświadczenia są przesyłane przewodowo, ponieważ można je zabezpieczyć za pomocą TLS lub podobnego protokołu lub dowodu posiadania itp. Jak ktoś już sugerował, kodowanie bazowe 64 to 0 zabezpieczeń, proszę nie dać się zwieść temu. Różnice wspomniane powyżej są zwykle na poziomie architektonicznym, dlatego skupiłem się na nich, ponieważ architektura jest najtrudniejsza do zmiany po wdrożeniu.

Azure Active Directory B2C Basic , usługa, nad którą pracuję, a która została niedawno wydana do publicznej wersji zapoznawczej, umożliwia aplikacjom zewnętrznym używanie AAD jako serwera autoryzacji z interoperacyjnością z serwisami społecznościowymi IDP (takimi jak Facebook, Google itp.). Umożliwia także użytkownikom tworzenie własnych kont zamiast korzystania z IDP społecznościowych, które można później wykorzystać do celów uwierzytelnienia. Istnieje również kilka innych podobnych usług (np. Inna, o której wiem, to auth0), z którego programiści mogą korzystać w celu całkowitego outsourcingu uwierzytelniania i zarządzania użytkownikami dla swoich aplikacji i zasobów. Te same cechy protokołów, o których wspomniałem powyżej, są używane przez programistów do rozdzielania serwera autoryzacji (AAD), zasobu (np. Ich interfejsów API REST), klienta (np. Ich aplikacji mobilnych) i użytkowników. Mam nadzieję, że to wyjaśnienie nieco pomoże.

Omer Iqbal
źródło
Dzięki za szeroki kąt, ale nie sądzę, że te zalety (a) letting the user agent hold just the token instead of the password, (b) allowing a password change without disrupting existing client apps, (c) allowing users log out other sessionssą specyficzne dla przepływów uwierzytelniania tokenów. W podstawowych specyfikacjach ani uwierzytelnienia podstawowe, ani tokeny nie wspominają o funkcjach (b) i (c). Implementacja (b) i (c) wydaje się możliwa dla dowolnego rodzaju uwierzytelnienia. Wymagałoby to śledzenia haseł (najlepiej ich skrótów). Zaleta (a) wydaje się zależeć od szerszego zakresu hasła.
węgorz ghEEz
Jak możemy użyć OAuth, jeśli użytkownik (właściciel zasobów) nie ma poświadczeń z zewnętrznym serwerem autoryzacji, ale ma poświadczenia w aplikacji klienta? Oznacza to, że mamy właściciela zasobów (użytkownika), klienta (reprezentującego użytkownika i zawierającego poświadczenia dla użytkownika) oraz serwer zasobów. W jaki sposób serwer zasobów może uwierzytelnić i autoryzować użytkownika?
Arun Avanathan
3

Uważam, że jesteś źle poinformowany o szyfrowaniu wokół zmiennych GET w adresie URL

Jedynymi osobami, które mogą wyświetlać zmienne GET w żądaniu, jest oryginalny komputer i serwer odbierający ( łącze ).

Tylko wyszukiwanie DNS na podstawie domeny, do której wysyłane jest żądanie HTTPS, nie jest szyfrowane. Cała reszta, porty, zmienne GET, identyfikator zasobu, są szyfrowane.

Jedynym zastrzeżeniem jest to, że serwer odbierający może wylogować pełną ścieżkę żądania, ale Ty masz kontrolę nad tym, abyś mógł chronić te dane w dowolny sposób.

Patrick
źródło
3

Uwierzytelnianie podstawowe nie jest dobrym sposobem na zabezpieczenie interfejsu API REST. W tej odpowiedzi wyjaśniłem powody .

Podczas tworzenia interfejsu API REST implementujesz serwer zasobów na zasadach OAuth2. Wszystko, co musisz zrobić, to sprawdzić, czy token przekazany wraz z żądaniem w nagłówku HTTP autoryzacji jest prawidłowy i pochodzi od zaufanego wystawcy. Zobacz ten link, aby dowiedzieć się, jak zaimplementować sprawdzanie poprawności, jeśli nie jest dostępna biblioteka.

To, w jaki sposób klient pozyskuje token z serwera autoryzacji, zależy od tego, jakiego rodzaju klientem . Pamiętaj, że musisz określić typ klienta, którego będziesz używać podczas rejestracji klienta na serwerze autoryzacji.

W przypadku aplikacji internetowej komunikującej się z twoim serwerem może ona użyć przyznania kodu autoryzacyjnego . Jeśli jest to niezaufany klient, taki jak aplikacja mobilna lub aplikacja JavaScript, powinien użyć domyślnej dotacji .

W przypadku usług zaplecza, które nie mogą wchodzić w interakcje z właścicielem zasobu, można użyć przyznania poświadczeń klienta . W przypadku narzędzi wiersza poleceń można użyć poświadczeń klienta lub hasła właściciela zasobu .

Wszystko zależy od tego, jakiego klienta używasz.

Na koniec sprawdzanie poprawności tokena JWT odbywa się na serwerze zasobów bez potrzeby rozmowy z serwerem autoryzacji. Prowadzi to do lepszej skalowalnej architektury niż rozwiązania, które muszą wyszukiwać prywatne dane dla każdego klienta.

MvdD
źródło
1

Jest albo bezpieczny, albo niezabezpieczony. Nie więcej nie mniej. Posiadanie base64 nie sprawia, że ​​uwierzytelnianie podstawowe (lub cokolwiek innego) jest bezpieczniejsze.

Nie ma nic złego w wysyłaniu czegokolwiek niezaszyfrowanego, jeśli używa szyfrowanej potoku, takiego jak Https.

OAuth ma więcej funkcji, użyj go, jeśli go potrzebujesz. W przypadku wszystkiego innego, np. Bankowości, korzystanie z podstawowych odpowiedzi na wyzwania jest w porządku i bezpieczne.

imel96
źródło
0

Myślę, że najpierw musisz zrozumieć terminologię. Porównujesz - Autoryzacja i podpis cyfrowy

OAuth jest otwartym standardem dla autoryzacji , w którym to, co robi Amazon (zgodnie z artykułem i szczegółami podanymi w pytaniu), tworzy prawidłowy podpis cyfrowy, który daje odbiorcy (tutaj Amazonowi) powód do przekonania, że ​​wiadomość została stworzona przez znanego nadawca, że ​​nadawca nie może odmówić wysłania wiadomości ( uwierzytelnienie i niezaprzeczenie)

To, który mechanizm autoryzacji ma zostać użyty, zależy mniej więcej od przypadku użycia.

Poniżej znajduje się to, co można znaleźć na StackOverflow tutaj :

Podstawowe uwierzytelnianie, które wymaga bardzo prostego mieszania w celu obliczenia pojedynczego wymaganego nagłówka - OAuth jest bez wątpienia droższym uwierzytelnieniem. Ważne jest, aby zdać sobie sprawę, że dwa mechanizmy uwierzytelniania służą całkowicie innym celom. Podstawowe uwierzytelnianie służy do uwierzytelniania klienta w podstawowej aplikacji. OAuth służy do autoryzacji strony trzeciej w celu uzyskania dostępu do danych klienta z aplikacji podstawowej. Oba mają swoje miejsce, a wybranie jednego z drugiego powinno zależeć od konkretnego przypadku zastosowania wdrożenia.

A oto kolejny interesujący artykuł porównujący oba.

Podstawowe uwierzytelnianie za pośrednictwem protokołu SSL jest w rzeczywistości dość odpowiedzialne z uproszczonego punktu widzenia. Kiedy walczymy z nazwami użytkowników i hasłami, podstawowe uwierzytelnianie jest powszechnym rozwiązaniem, ponieważ jest tak łatwe do wdrożenia. Przesyłanie danych uwierzytelniających jest szyfrowane za pomocą protokołu SSL, a użycie nagłówka „Autoryzacja” jest wszechobecne w klientach i systemach HTTP.

Guanxi
źródło