Zadawanych jest tutaj wiele pytań i wydaje się, że chociaż pytania są zadawane w kontekście Node i passport.js, prawdziwe pytania dotyczą bardziej przepływu pracy niż tego, jak to zrobić za pomocą określonej technologii.
Użyjmy przykładowej konfiguracji @Keith, nieco zmodyfikowanej w celu zwiększenia bezpieczeństwa:
- Serwer sieci Web pod adresem
https://example.com
obsługuje pojedynczą stronę aplikacji klienckiej Javascript
- Usługa internetowa RESTful pod adresem
https://example.com/api
zapewnia obsługę serwera dla bogatej aplikacji klienckiej
- Serwer zaimplementowany w Node i passport.js.
- Serwer posiada bazę danych (dowolnego rodzaju) z tabelą "użytkowników".
- Nazwa użytkownika / hasło i Facebook Connect są oferowane jako opcje uwierzytelniania
- Bogaty klient wysyła żądania REST do
https://example.com/api
- Mogą istnieć inni klienci (na przykład aplikacje na telefon), którzy korzystają z usługi internetowej pod adresem,
https://example.com/api
ale nie wiedzą o serwerze WWW pod adresem https://example.com
.
Pamiętaj, że używam bezpiecznego protokołu HTTP. Moim zdaniem jest to obowiązkowe dla każdej usługi, która jest dostępna na wolnym powietrzu, ponieważ poufne informacje, takie jak hasła i tokeny autoryzacyjne, są przesyłane między klientem a serwerem.
Uwierzytelnianie nazwy użytkownika / hasła
Przyjrzyjmy się najpierw, jak działa zwykłe stare uwierzytelnianie.
- Użytkownik łączy się z
https://example.com
- Serwer obsługuje bogatą aplikację JavaScript, która renderuje stronę początkową. Gdzieś na stronie znajduje się formularz logowania.
- Wiele sekcji tej pojedynczej strony aplikacji nie zostało wypełnionych danymi, ponieważ użytkownik nie jest zalogowany. Wszystkie te sekcje mają detektor zdarzeń na zdarzeniu „logowania”. To wszystko po stronie klienta, serwer nie wie o tych zdarzeniach.
- Użytkownik wprowadza swój login i hasło i naciska przycisk przesyłania, co powoduje, że moduł obsługi Javascript rejestruje nazwę użytkownika i hasło w zmiennych po stronie klienta. Następnie ten program obsługi wyzwala zdarzenie „login”. Ponownie, jest to akcja po stronie klienta, poświadczenia nie zostały jeszcze wysłane na serwer .
- Wywoływane są detektory zdarzenia „login”. Każdy z nich musi teraz wysłać jedno lub więcej żądań do RESTful API pod adresem,
https://example.com/api
aby uzyskać dane użytkownika do wyświetlenia na stronie. Każde żądanie wysłane do usługi sieciowej będzie zawierało nazwę użytkownika i hasło, prawdopodobnie w formie podstawowego uwierzytelniania HTTP , ponieważ usługa RESTful nie może utrzymywać stanu klienta od jednego żądania do następnego. Ponieważ usługa sieciowa korzysta z bezpiecznego protokołu HTTP, hasło jest bezpiecznie szyfrowane podczas przesyłania.
- Usługa internetowa pod adresem
https://example.com/api
odbiera zestaw indywidualnych żądań, z których każde zawiera informacje uwierzytelniające. Nazwa użytkownika i hasło w każdym żądaniu są sprawdzane w bazie danych użytkowników i jeśli okaże się, że są prawidłowe, wykonywana jest żądana funkcja, a dane są zwracane do klienta w formacie JSON. Jeśli nazwa użytkownika i hasło nie są zgodne, do klienta wysyłany jest błąd w postaci kodu błędu 401 HTTP.
- Zamiast zmuszać klientów do wysyłania nazwy użytkownika i hasła przy każdym żądaniu, możesz mieć funkcję „get_access_token” w swojej usłudze RESTful, która pobiera nazwę użytkownika i hasło i odpowiada tokenem, który jest rodzajem kryptograficznego skrótu, który jest unikalny i ma pewną datę ważności data z tym związana. Te tokeny są przechowywane w bazie danych z każdym użytkownikiem. Następnie klient wysyła token dostępu w kolejnych żądaniach. Token dostępu zostanie następnie zweryfikowany w bazie danych zamiast nazwy użytkownika i hasła.
- Aplikacje klienckie inne niż przeglądarki, takie jak aplikacje na telefon, robią to samo, co powyżej, proszą użytkownika o wprowadzenie swoich poświadczeń, a następnie wysyłają je (lub wygenerowany z nich token dostępu) przy każdym żądaniu do usługi internetowej.
Ważnym punktem wyjścia z tego przykładu jest to, że usługi sieciowe obsługujące REST wymagają uwierzytelniania przy każdym żądaniu .
Dodatkowa warstwa zabezpieczeń w tym scenariuszu dodałaby autoryzację aplikacji klienckiej oprócz uwierzytelniania użytkownika. Na przykład, jeśli masz klienta internetowego, aplikacje iOS i Android korzystające z usługi internetowej, możesz chcieć, aby serwer wiedział, który z trzech klientów danego żądania jest, niezależnie od tego, kto jest uwierzytelnionym użytkownikiem. Może to umożliwić usłudze internetowej ograniczenie niektórych funkcji do określonych klientów. W tym celu możesz użyć kluczy i kluczy API, zobacz tę odpowiedź, aby uzyskać kilka pomysłów na ten temat.
Uwierzytelnianie na Facebooku
Powyższy przepływ pracy nie działa w przypadku połączenia z Facebookiem, ponieważ logowanie za pośrednictwem Facebooka ma stronę trzecią, sam Facebook. Procedura logowania wymaga przekierowania użytkownika do witryny Facebooka, gdzie dane uwierzytelniające są wprowadzane poza naszą kontrolą.
Zobaczmy więc, jak to się zmienia:
- Użytkownik łączy się z
https://example.com
- Serwer obsługuje bogatą aplikację JavaScript, która renderuje stronę początkową. W niektórych miejscach na stronie znajduje się formularz logowania, który zawiera przycisk „Zaloguj się przez Facebook”.
- Użytkownik klika przycisk „Zaloguj się przez Facebooka”, który jest po prostu linkiem przekierowującym (na przykład)
https://example.com/auth/facebook
.
https://example.com/auth/facebook
Trasy obsługiwane przez passport.js (patrz dokumentacja )
- Jedyne, co użytkownik widzi, to zmiana strony i teraz znajduje się na stronie hostowanej na Facebooku, gdzie musi się zalogować i autoryzować naszą aplikację internetową. To jest całkowicie poza naszą kontrolą.
- Użytkownik loguje się na Facebooku i udziela pozwolenia naszej aplikacji, więc Facebook przekierowuje teraz z powrotem do adresu URL wywołania zwrotnego, który skonfigurowaliśmy w konfiguracji passport.js, co zgodnie z przykładem w dokumentacji to
https://example.com/auth/facebook/callback
- Program obsługi passport.js dla
https://example.com/auth/facebook/callback
trasy wywoła funkcję zwrotną, która odbiera token dostępu Facebooka i niektóre informacje o użytkowniku z Facebooka, w tym adres e-mail użytkownika.
- Za pomocą e-maila możemy zlokalizować użytkownika w naszej bazie danych i przechowywać wraz z nim token dostępu do Facebooka.
- Ostatnią rzeczą, jaką robisz w wywołaniu zwrotnym Facebooka, jest przekierowanie z powrotem do bogatej aplikacji klienta, ale tym razem musimy przekazać klientowi nazwę użytkownika i token dostępu, aby mógł z nich korzystać. Można to zrobić na wiele sposobów. Na przykład zmienne JavaScript można dodać do strony za pośrednictwem mechanizmu szablonów po stronie serwera, albo też można zwrócić plik cookie z tymi informacjami. (podziękowania dla @RyanKimber za wskazanie problemów bezpieczeństwa podczas przekazywania tych danych w adresie URL, jak początkowo sugerowałem).
- Więc teraz ponownie uruchamiamy aplikację z jedną stroną, ale klient ma nazwę użytkownika i token dostępu.
- Aplikacja kliencka może natychmiast wywołać zdarzenie „logowanie” i pozwolić różnym częściom aplikacji zażądać informacji, których potrzebują, z usługi sieciowej.
- Wszystkie żądania wysyłane do
https://example.com/api
będą zawierały token dostępu Facebook do uwierzytelniania lub token dostępu do aplikacji wygenerowany z tokena Facebooka za pośrednictwem funkcji „get_access_token” w REST API.
- W przypadku aplikacji innych niż przeglądarki jest to nieco trudniejsze, ponieważ OAuth wymaga przeglądarki internetowej do logowania. Aby zalogować się z aplikacji na telefon lub komputer, musisz uruchomić przeglądarkę, aby wykonać przekierowanie do Facebooka, a co gorsza, Potrzebujesz sposobu, aby przeglądarka mogła przekazać token dostępu Facebooka z powrotem do aplikacji za pośrednictwem jakiegoś mechanizmu.
Mam nadzieję, że to odpowiada na większość pytań. Oczywiście możesz zastąpić Facebooka serwisem Twitter, Google lub inną usługą uwierzytelniania opartą na OAuth.
Chciałbym wiedzieć, czy ktoś ma prostszy sposób radzenia sobie z tym.
passport-facebook
. Gdy już to zrobisz, następnym krokiem jest zrozumienie, jak działa usługa Passport i jak przechowuje poświadczenia. Podłączenie go do Restify ( zobacz tutaj zaktualizowaną wersję tej, o której wspomniałeś) byłoby jednym z ostatnich kroków (lub możesz zaimplementować interfejs REST w Express).