Jak powinienem zaprojektować usługę RESTful do korzystania z usług stron trzecich (tj. Google, Facebook, Twitter) do uwierzytelniania?

25

Do mojej pracy mamy niezłą usługę RESTful, którą zbudowaliśmy i używamy do prowadzenia kilku stron internetowych. Zasadniczo usługa internetowa pozwala tworzyć i obsługiwać zgłoszenia do pomocy technicznej, a strona internetowa jest odpowiedzialna za interfejs. Wszelkie żądania usług sieciowych wykorzystują nagłówek uwierzytelniania, którego używamy do sprawdzania poprawności użytkownika i hasła do każdego połączenia.

W tym roku chcemy rozszerzyć nasze opcje logowania, aby użytkownicy witryny mogli logować się za pośrednictwem Google, Twittera i Facebooka (ewentualnie innych). Mam jednak problemy z ustaleniem, jak to skonstruować, aby usługa mogła korzystać z zewnętrznych dostawców uwierzytelniania, aby upewnić się, że użytkownicy są tacy, za których się podają. Czy istnieją jakieś najlepsze praktyki, jak to zrobić?

Obecnie myślimy o tym, aby witryna obsługiwała uwierzytelnianie samych użytkowników, a następnie użyła nowego wywołania setSessionId, które rejestruje ich bieżącą sesję w zapleczu usługi WWW. Każde dodatkowe żądanie do serwisu internetowego przekaże ten sessionId i zweryfikuje je. Wydaje się to w porządku, ale mam wrażenie, że nie zastanawiam się nad tym, a całe moje forum przeglądania i czytania oauth i openid specyfikacji tylko mnie dezorientują. Wszelkie wskazówki, jak sobie z tym poradzić?

Ralph Callaway
źródło
nie ma nic złego w tym, co sugerujesz. I łatwiej spojrzeć na openid przykład integracja kodu niż rzeczywisty OAuth i OpenID widowisko ...
Spaceman
Jakiego języka / platformy używasz? Nie musisz od nowa wymyślać koła, ponieważ istnieją ramy, które znacznie Ci pomogą. :)
RobM
@Rob Usługa internetowa jest hostowana na Salesforce.com, ale jest dostępna za pośrednictwem serwera proxy, który w tym piśmie jest Node.js. Powiedział, że wydaje się, że ogólne pytanie dotyczyłoby wszystkich platform. I tak, mam nadzieję, że użyję frameworka, zamiast odkrywać koło, po prostu nie jestem pewien, jakiego koła użyć.
Ralph Callaway,
@Ralph Tak, ogólne pytanie jest niezależne od platformy, ale ma to praktyczne implikacje, ponieważ platforma ogólnie zawęzi nieco opcje ramowe. Masz niestandardową aplikację front-end używającą node.js do usługi hostowanej przez Salesforce i repozytorium danych? Czy musisz przechowywać informacje o użytkowniku / tożsamości w wewnętrznej bazie danych, czy po prostu uwierzytelnianie i autoryzacja działań w interfejsie?
RobM,
@RobM tak, będziemy chcieli przechowywać informacje o użytkowniku na zapleczu, tj. E-mail, imię, nazwisko oraz wszystko, co jest potrzebne do potwierdzenia przyszłych połączeń od klientów usług internetowych po ich uwierzytelnieniu.
Ralph Callaway,

Odpowiedzi:

14

Wygląda na to, że są dwa cele:

  1. Użytkownicy końcowi mogą łatwo uwierzytelnić się na istniejących kontach społecznościowych
  2. Łatwy dla programistów korzystających z Twojej usługi internetowej

Upoważnienie osób do korzystania z zasobów w Twojej witrynie sprawia, że ​​OAuth2 jest preferowanym mechanizmem ze względu na popularność i dostępność bibliotek klienckich.

1. Łatwy dla użytkowników końcowych do uwierzytelnienia za pomocą istniejących kont społecznościowych

Użytkownik końcowy odwiedza witrynę korzystającą z interfejsu API i wybiera opcję logowania. Są one wysyłane na twoją stronę logowania OAuth. Strona logowania pokazuje normalną nazwę użytkownika i hasło do kont zarządzanych w Twojej witrynie oraz zestaw przycisków uwierzytelniania społecznościowego, w których można kliknąć, aby zalogować się za pośrednictwem strony takiej jak Facebook. Gdy użytkownik wybierze Facebooka, przekierowujesz go na Facebooka, aby zatwierdzić wybór (rozpoczynając przepływ uwierzytelniania na Facebooku). Gdy użytkownik końcowy zakończy logowanie na Facebooku, zostaje przekierowany z powrotem na twoją stronę.

Gdy użytkownik zostanie przekierowany z powrotem na twoją stronę z Facebooka, zapisujesz informacje tego użytkownika w rekordzie użytkownika w bazie danych, a następnie generujesz nową sesję dla tego użytkownika. Natychmiast przekierowujesz użytkownika końcowego do jego oryginalnej strony podrzędnej za pomocą tokena oauth access_token, uzupełniając oryginalny przepływ oauth.

2. Łatwe dla programistów korzystających z Twojej usługi internetowej

Jeśli jesteś dostawcą autoryzacji, powinieneś stworzyć prosty interfejs dla programistów, od którego nie będzie się zmieniać za każdym razem, gdy dodajesz nowego dostawcę autoryzacji, który nie wdraża doskonale. Dlatego uważam, że powinieneś wdrożyć witrynę dostawcy OAuth2, która powinna być konsumentem serwisów społecznościowych.

Deweloperowi korzystającemu z przyjemnego interfejsu API odpoczynku, nie będzie on świadomy interakcji na Facebooku, chyba że zdecydujesz się dać mu podpowiedź poprzez post przechwytywania sesji (na przykład).

TL; DR

Spraw, aby konsumenci Twoich interfejsów API byli tacy jak Ty, wdrażając OAuth2 i ukrywając złożoność uwierzytelniania społecznościowego. Możesz, podczas swojego oauth przepływu dla twoich dalszych stron, wywołać dodatkowy oauth flow za pomocą Facebooka.

Obraz, ponieważ obraz == słowa * 1000:

wprowadź opis zdjęcia tutaj

Czy możemy nazwać to oauth2-piggy-back?

Przepływ krok po kroku

  1. Użytkownik końcowy odwiedza witrynę korzystającą z interfejsu API
  2. Użytkownik końcowy jest wysyłany do Twojej witryny w celu autoryzacji lub rejestracji (oauth2)
  3. Użytkownik końcowy wybiera uwierzytelnianie społecznościowe, klika przycisk logowania na Facebooku
  4. Twoja strona ustawia plik cookie lub ustawia statena Facebooku, aby wiedzieć, skąd pochodzi użytkownik
  5. Użytkownik końcowy został przekierowany na Facebook i akceptuje połączenie na stronie Facebook
  6. Użytkownik końcowy został przekierowany do Twojej witryny, aby dokończyć proces autoryzacji na Facebooku
  7. Wyszukaj lub utwórz użytkownika w bazie danych
  8. Tworzysz nową sesję na swoim serwerze
  9. Za pomocą tokena sesji przekierowujesz użytkownika z powrotem do oryginalnej witryny
James Sullivan
źródło
5

Jak sprawić, by był rozszerzalny

Najpierw powinieneś zauważyć, że wszystkie te api używają tego samego mechanizmu do logowania. Wszystkie używają OAuth do uwierzytelnienia. Musisz to wykorzystać, zaczynając od ogólnej biblioteki OAuth. Nie używaj własnych bibliotek do uwierzytelniania, będą one bezużyteczne dla innych dostawców. Jeśli wiesz, jak działa OAuth2, dość łatwo jest dodać więcej dostawców.

Potrzebujesz niestety dwóch z nich, ponieważ Twitter wciąż nie przeskoczył modemu OAuth2.

OAuth wymaga utworzenia interfejsu dla strony uwierzytelniającej. Tokeny zostaną wymienione między serwerami. Utwórz jeden punkt wejścia, który może obsłużyć całą komunikację.

Token powinien być przechowywany w oddzielnej tabeli od konta, ponieważ może to być wiele tokenów i wiele połączonych profili. Niektóre usługi dają dwa tokeny, jeden z nich to token odświeżania.

Teraz projektujesz interfejs, który zawiera inne potrzebne funkcje. Osobiście skonfigurowałbym do tego osobną usługę REST. W ten sposób możesz łatwo rozszerzyć uwierzytelnianie na inne miejsca.
Niektóre usługi używają JSON do komunikacji, inne używają XML itp. Dla użytkownika głównego musisz je wszystkie zunifikować. Jest to dość bolesny proces, ale można tu wyciągnąć pewne wspólne podstawy.

Innym problemem jest to, że nie wszystkie usługi zapewniają tę samą funkcjonalność. Może to oznaczać, że Twoje usługi nie mogą zapewnić pełnego interfejsu API, jak określono. Musisz mieć tutaj strategię, która pozwoli z wdziękiem obniżyć aplikację.

Wszystko to zapewni łatwe dodawanie nowych zewnętrznych dostawców usług.

Problemy z tokenami

Tokeny są ograniczone w czasie, dlatego potrzebujesz kilku zadań cron, które mogą sprawdzić, czy token jest nadal użyteczny, w przeciwnym razie musisz go usunąć. Możesz także odświeżyć token za pomocą tego mechanizmu.

Czasami zdarza się, że użytkownik cofa token. Przygotuj się na to.

Przechowywanie danych

Jeśli masz ten projekt, musisz pomyśleć o potrzebnych danych. Wynika to częściowo z właśnie utworzonego interfejsu. Zaprojektuj w tym celu kilka tabel i sprawdź, czy dane można w rzeczywistości odzyskać. Niektóre usługi nie pozwalają na pobranie dużej ilości danych. Należy również wziąć pod uwagę, że im więcej danych potrzebujesz, tym trudniejsze stają się komunikaty o prywatności. Bądź więc skromny w swoich potrzebach, w przeciwnym razie użytkownicy nie będą go używać.

W celu dodatkowej weryfikacji możesz przechowywać profile w osobnej, ale połączonej tabeli dla użytkowników. Zapewni to znacznie więcej informacji o kimś.

Sprawdź także lokalne przepisy, w przypadku niektórych danych potrzebujesz dodatkowych środków ostrożności.

Ostatnia rzecz Nie popełniaj błędu, gdy nie tworzysz konta we własnych usługach. Jeśli użytkownik zostanie zablokowany na Facebooku, nie będzie mógł zalogować się do Twojej usługi. Jest to sytuacja, której nie chcesz tworzyć. Jest to często pomijane.

Edgar Klerks
źródło
1

Zdecydowanie wybrałbym rozwiązanie, które wygląda na to, że już się zorientowałeś: wdrożenie uwierzytelnienia strony trzeciej w witrynie skierowanej do klienta, a następnie powiązanie tych tokenów uwierzytelnienia strony trzeciej z kontami użytkowników witryny, a następnie w końcu wywołanie połączenia setSessionID Zaloguj Się.

W zależności od architektury witryny może okazać się bardzo pomocne korzystanie z biblioteki takiej jak EveryAuth lub Passport .

Rex
źródło
1

Moje dwa centy: nigdy wcześniej nie robiłem czegoś takiego, ani nie wiem, jak działają mechanizmy logowania do FB, Twittera lub Google, ale kilka problemów pojawiło się w mojej głowie, gdy tylko przeczytałem twoje pytanie:

  • Wiele logowań: Co się stanie, jeśli pewnego dnia zaloguję się na swoje konto Facebook, a następnego na konto Google? Czy jednocześnie? Czy traktujesz te dwa konta jako unikalne, osobne konta, czy powinieneś mieć jakąś metodę powiązania tych dwóch kont i umożliwienia mi dostępu do moich biletów w obu przypadkach?
  • Poleganie na zewnętrznych identyfikatorach: co się stanie, gdy Facebook lub Twitter zdecydują się zmienić wygląd identyfikatorów swoich kont? Aby to zilustrować, jeśli BazLogin reprezentuje unikalne konto przy użyciu kodu {4382-af56}, ale zdecyduje, że odtąd konta będą miały 12 cyfr, ponieważ 8 to za mało, jak to powiedzieć {1234-4382-af56} z {0000-4382 -af56}?

Możemy rozwiązać te dwa problemy, wybierając powiązanie kont zewnętrznych z kontem wewnętrznym, a nie tylko identyfikatorem sesji. W takim przypadku zewnętrzny login może być tylko bramą do utworzenia konta wewnętrznego. Jeśli uwierzytelnię się przy użyciu więcej niż jednej metody logowania, możesz mi powiedzieć, że jestem już zalogowany. Jeśli zewnętrzny dostawca autoryzacji zmieni coś, na czym polegamy, możemy poprosić użytkownika o podanie nazwy i hasła konta wewnętrznego i utworzenie nowe skojarzenie dla przyszłych logowań.

Nie jestem pewien, czy rozwiązałem problemy, które miałeś na myśli, ale tak naprawdę nie wspomniałeś o żadnych konkretnych obawach. Mam nadzieję, że moja odpowiedź była pomocna.

idoby
źródło