Architektura do łączenia wielu kont użytkowników razem

176

OK, mam stronę internetową, na której możesz się zarejestrować i zalogować. Możesz również zalogować się za pomocą konta na Facebooku, Twitterze lub koncie linkedin.

Ważne jest, aby użytkownicy mieli zarejestrowane tylko jedno konto. Więc w jakiś sposób chcę połączyć konta użytkowników, jeśli używają różnych metod logowania. Jakie jest najlepsze rozwiązanie tego problemu?

Na przykład użytkownik loguje się na swoje konto na Facebooku. Korzystam z tych danych, aby automatycznie zarejestrować dla niego konto. Czy powinienem wysłać e-mail z nazwą użytkownika i hasłem do naszej strony internetowej? (Jeśli jest to w porządku z polityką Facebooka). Czy powinienem dać im drugi ekran, na którym mogą wpisać nazwę użytkownika i hasło? Ale to nie jest idea logowania się za pomocą konta na Facebooku. Powinno to uprościć procedurę uczestnictwa.

Możliwe jest również, że użytkownik zarejestrował się na naszej stronie i następnym razem zaloguje się na swoje konto na Twitterze. Jak mogę połączyć te 2 konta jako jedno? Jaki jest najlepszy sposób?

Zasadniczo moje pytanie brzmi: Mam 4 różne sposoby, w jakie użytkownik zostaje członkiem naszej witryny. Jak mogę się upewnić, że wszystkie te 4 sposoby tworzą tylko jedno konto, jeśli użytkownik zdecyduje się korzystać z wielu sposobów? Jaki jest najlepszy przepływ, aby upewnić się, że nie stanie się to kłopotliwe dla samego użytkownika?


Edytować:

3 lata po tym, jak zadałem to pytanie, sam udzielam odpowiedzi w serii artykułów: https://www.peternijssen.nl/social-network-authentication-setup/
https://www.peternijssen.nl/social- network-authentication-google /
https://www.peternijssen.nl/social-network-authentication-merging-accounts/
https://www.peternijssen.nl/social-network-authentication-twitter-facebook/

PT
źródło
7
Oczywiście najlepiej jest przede wszystkim uniemożliwić użytkownikowi posiadanie wielu kont, zezwalając na wiele metod logowania, takich jak Stack Overflow, ale nawet SO ma możliwość łączenia kont przez moderatorów. Oferuję nagrodę dla każdego, kto potrafi opisać architekturę, która na to pozwoli. Musi być lepsze rozwiązanie niż „update post set UserID = 2, gdzie UserID = 1”
David Boike,
e-mail i telefon mogą być używane jako klucz scalający, inne?
Wuaner
Witam, link, który podałeś, wydaje się nie działać. Przechodzi tylko do strony głównej serwisu
vigamage
Zaktualizowano linki. Artykuły mają jednak 6 lat.
PT

Odpowiedzi:

120

W tej chwili mam dokładnie to samo zadanie. Projekt, który wypracowałem, jest raczej prosty, ale działa dobrze.

Podstawową ideą jest to, że modele tożsamości lokalnej witryny i tożsamości witryn innych firm są izolowane, ale później są połączone. Dlatego każdy użytkownik logujący się do witryny ma lokalną tożsamość, która jest odwzorowywana na dowolną liczbę tożsamości witryn innych firm.

Lokalny rekord tożsamości zawiera minimum informacji - może to być nawet pojedyncze pole - tylko klucz podstawowy. (W mojej aplikacji nie obchodzi mnie adres e-mail użytkownika, imię i nazwisko ani data urodzenia - chcę tylko wiedzieć, że to osoba, która cały czas logowała się na to konto).

Tożsamości osób trzecich zawierają informacje istotne tylko przy uwierzytelnianiu ze stroną trzecią. W przypadku protokołu OAuth oznacza to zwykle identyfikator użytkownika (taki jak identyfikator, adres e-mail lub nazwa użytkownika) oraz identyfikator usługi (wskazujący, która witryna lub usługa została uwierzytelniona). W innych częściach aplikacji, poza bazą danych, ten identyfikator usługi jest powiązany z metodą pobierania odpowiedniego identyfikatora użytkownika z tej usługi i tak jest wykonywane uwierzytelnianie. W przypadku OpenID stosujemy to samo podejście, z wyjątkiem tego, że metoda uwierzytelniania jest bardziej uogólniona (ponieważ prawie zawsze możemy wykonać dokładnie ten sam protokół - z wyjątkiem tego, że używamy innego adresu URL tożsamości i jest to nasz identyfikator usługi).

Wreszcie prowadzę zapisy, które tożsamości osób trzecich są powiązane z tożsamością lokalną. Aby wygenerować te rekordy, przepływ wygląda następująco:

  • Użytkownik loguje się po raz pierwszy przy użyciu tożsamości innej firmy. Tworzony jest lokalny rekord tożsamości, następnie rekord tożsamości innej firmy, a następnie są one parowane.
  • W panelu sterowania użytkownik ma możliwość połączenia konta poprzez zalogowanie się do usług podmiotów trzecich. (Całkiem proste, jak to działa.)
  • W scenariuszu, w którym użytkownik nieświadomie tworzy wiele kont, rozwiązanie jest dość proste. Gdy użytkownik jest zalogowany na jednym z kont, loguje się na inne, z którego wcześniej logował się do serwisu (za pomocą powyższej funkcji panelu sterowania). Usługa internetowa wykrywa tę kolizję (że tożsamość lokalna zalogowanego użytkownika różni się od tożsamości lokalnej połączonej z tożsamością strony trzeciej, która właśnie się zalogowała), a użytkownik jest monitowany o scalenie konta.

Scalanie kont polega na scaleniu poszczególnych pól tożsamości lokalnej (która będzie się różnić w zależności od aplikacji i powinna być łatwa, jeśli masz tylko kilka pól w lokalnych rekordach tożsamości), a następnie zapewnienie połączonych tożsamości stron trzecich są powiązane z powstałą tożsamością lokalną.

policzek
źródło
1
To bardzo dobre rozwiązanie (podoba mi się pomysł automatycznego wykrywania kolizji tożsamości lokalnej)! Zastanawiam się, czy znalazłeś sposób na automatyczne logowanie użytkownika do „dodatkowych” kont, które są połączone po pierwszym zalogowaniu się do aplikacji. Czy użytkownik musiałby logować się osobno na każde konto za każdym razem, gdy odwiedza (jeśli nie ma już aktywnej sesji z tymi dostawcami)?
Alexandra
@Alexandra Co rozumiesz przez „dodatkowe konta”? Czy pytasz, co się dzieje, gdy użytkownik loguje się do aplikacji za pośrednictwem kilku różnych uwierzytelniaczy, tworząc z każdym nową tożsamość lokalną?
cheeken
Wydaje mi się, że gwarantuje to właściwe wyjaśnienie i własne pytanie: stackoverflow.com/questions/11060368/…
Alexandra
3
Pytanie jednak, ale co się stanie, jeśli użytkownik zarejestruje się w witrynie przy użyciu tego samego adresu e-mail? czy podpowiadamy im, że e-mail już istnieje (e-mail pochodzący z modelu strony trzeciej), czy nadal rejestrujemy je w witrynie, a następnie połączyliśmy te konta?
user962206
@ user962206 wiele usług i tak nie poda „prawdziwego” adresu e-mail ze względu na ochronę prywatności. Na przykład Twitter nie poda żadnego adresu e-mail, o ile wiem, Facebook poda „[email protected]”, którego wątpię, by ktoś użył do rejestracji.
kapex
44

Często znajduję wiele witryn łączących się na podstawie wiadomości e-mail jako nakładającego się czynnika łączenia.

Widzę, że jest to realna opcja, ale znowu zależy to od twoich preferencji, jak scalić. Adres e-mail to główny sposób, w jaki ludzie używają do weryfikacji niektórych ważnych zmian w Twojej witrynie, takich jak zmiana hasła, zakończenie usługi, niski stan konta itp. To prawie jak internetowy system numerów ubezpieczenia społecznego, ale z możliwością komunikacji . Kulturowo: myślę, że rozsądne jest założenie, że wiadomość e-mail jest dość unikalną tożsamością w usługach uwierzytelniania OAuth. To prawda, o to proszą formularze logowania do Facebooka i Google.

Mój obecny proces myślowy.

Strona logowania ma 3 opcje

  • Członkostwo w Twojej witrynie
  • Zaloguj się przez facebook
  • Zaloguj się przez Google

1) Logowanie użytkownika po raz pierwszy: uruchom przepływ rejestracji, w którym konto jest tworzone i wypełniane po raz pierwszy.

 if the user logins using Facebook (or whatever 3rd party login)
      1) call the Facebook api asking for their information (email, name, etc...) 
      2) create an account membership entry in your database somewhat like this 

         Table = Users
         [ UserId   |       Email             | Password ]
         [    23     | "[email protected]" |  *null*  ]

      3) create an external auths entry like so
         *ProviderUserId is the unique id of that user on the provider's site

         Table = ExternalAuths
         [ ExternalAuthId  |  User_UserId   | ProviderName |   ProviderUserId  ]
         [    56           |      23        |   Facebook   |  "max.alexander.9"]

 if the user wants to create an account with your own registration it would just be this           

         Table = Users
         [ UserId   |       Email           |   Password  ]
         [    23     | [email protected] |  myCoolPwd  ]

2) W innym czasie użytkownik wraca, ale decyduje się kliknąć Login Google

      1) call the Google api asking for their information (email, name, etc...) 

      2) once you get the email, match it up to the userId entry with the existing email 

      3) create an additional External auth entry as such

         Table = ExternalAuths
         [ ExternalAuthId  |  User_UserId   | ProviderName |   ProviderUserId  ]
         [    56           |      23        |   Facebook   |  "max.alexander.9"]
         [    57           |      23        |    Google    |  "1234854368"     ]

3) Teraz połączyłeś na koncie, któremu ufasz, wiadomości e-mail we wpisach bazy danych są takie same, jak te, którym ufasz z zewnętrznych loginów.

Więc dla kolejnych logowań

A co, jeśli najpierw korzystasz z logowania zewnętrznego, a później chcesz, aby użytkownik mógł zalogować się za pomocą hasła?

Widzę dwa łatwe sposoby, aby to zrobić

  • Przy każdym pierwszym logowaniu, gdy konto jest tworzone przez zewnętrzną autoryzację, poproś ich o hasło, aby dokończyć pierwszy wpis do aplikacji

  • Jeśli wcześniej zarejestrowali się za pomocą Facebooka lub Google, w jakiś sposób chcieli zarejestrować się za pomocą formularza rejestracyjnego Twojej witryny. Sprawdź, czy adres e-mail, który wprowadzili, już istnieje, poproś o hasło i wyślij wiadomość e-mail z potwierdzeniem po zakończeniu rejestracji.

Max Alexander
źródło
1
Korzystając z zewnętrznego schematu uwierzytelniania (Facebook, Google, Twitter itp.), Nigdy nie będziesz mieć dostępu do hasła zewnętrznego dostawcy. Hasło w powyższym przykładzie to hasło do własnej aplikacji internetowej.
Max Alexander,
6
Twitter nie oferuje użytkownikom poczty elektronicznej. Jeśli więc identyfikator użytkownika Twittera nie istnieje, po ich pierwszym uwierzytelnieniu poproś go o podanie adresu e-mail i hasła. Jeśli adres e-mail i hasło istnieją, połącz konta. Jeśli tak się nie stanie, zapisz adres e-mail i hasło w celu bezproblemowego późniejszego uwierzytelnienia. Czy to w ogóle było pomocne?
Max Alexander,
1
Na marginesie, można teraz poprosić o uprawnienia aplikacji Twitter, aby uzyskać adres e-mail użytkownika.
Sunil D.
2
Czy Facebook sprawia, że ​​ludzie weryfikują swój adres e-mail? Wiem, że na przykład Github nie. Złośliwy użytkownik może zarejestrować się w Github, używając cudzej nazwy e-mail, a następnie uzyskać dostęp do swojego konta w Twojej witrynie dzięki tej strategii. (Interfejs API Github informuje, czy ich adres e-mail jest zweryfikowany, czy nie - możesz odrzucić każdego, kto uwierzytelnia się za pomocą Github na niezweryfikowany adres e-mail)
Matthew Moisen
6
Jest to naruszenie bezpieczeństwa, jeśli użytkownik zarejestruje się za pośrednictwem mediów społecznościowych, edytuje swój adres e-mail w mediach społecznościowych, ktoś inny przyjmie ten sam adres e-mail, zarejestruje się w mediach społecznościowych, a następnie zaloguje się, zostanie połączony z kontem innej osoby. Jest to mało prawdopodobne, ale mimo wszystko naruszenie. Albo coś mi brakuje.
Shane,
35

Przeszedłem przez to ze sled.com. Istnieje wiele problemów związanych z tworzeniem kont i obsługą logowania wielu kont innych firm. Niektórzy z nich są:

  • Czy potrzebujesz obsługiwać zarówno hasło lokalne, jak i loginy osób trzecich?

W przypadku sled.com zdecydowałem się porzucić hasło lokalne ze względu na niewielką wartość, jaką dodaje, i dodatkowy koszt zabezpieczenia formularza wprowadzania hasła. Istnieje wiele znanych ataków na łamanie haseł i jeśli zamierzasz wprowadzić hasła, upewnij się, że nie są one łatwe do złamania. Musisz również przechowywać je w jednokierunkowym skrócie lub czymś podobnym, aby zapobiec ich wyciekowi.

  • Jak dużą elastyczność chcesz pozwolić na obsługę wielu kont innych firm?

Wygląda na to, że wybrałeś już trzech dostawców logowania: Facebook, Twitter i LinkedIn. To świetnie, ponieważ oznacza, że ​​używasz protokołu OAuth i współpracujesz z dobrze zdefiniowanym zbiorem zaufanych dostawców. Nie jestem fanem OpenID. Pozostaje pytanie, czy musisz obsługiwać wiele kont innych firm od tego samego dostawcy (np. Jedno konto lokalne z dwoma połączonymi kontami na Twitterze). Zakładam, że nie, ale jeśli to zrobisz, będziesz musiał uwzględnić to w swoim modelu danych.

W przypadku Sled obsługujemy logowanie za pomocą Facebooka, Twittera i Yahoo! a na każdym koncie użytkownika przechowuj klucz dla każdego z nich: {"_id": "djdjd99dj", "yahoo": "dj39djdj", twitter: "3723828732", "facebook": "12837287"}. Skonfigurowaliśmy kilka ograniczeń, aby zapewnić, że każde konto innej firmy może być połączone tylko z jednym kontem lokalnym.

Jeśli zamierzasz zezwolić na wiele kont od tego samego zewnętrznego dostawcy, będziesz musiał użyć list lub innych struktur do obsługi tego, a wraz z tym wszystkich innych ograniczeń, aby zapewnić unikalność.

  • Jak połączyć wiele kont?

Gdy użytkownik po raz pierwszy rejestruje się w Twojej usłudze, najpierw udaje się do dostawcy zewnętrznego i wraca ze zweryfikowanym identyfikatorem innej firmy. Następnie tworzysz dla nich konto lokalne i zbierasz wszelkie inne informacje, które chcesz. Zbieramy ich adresy e-mail, a także prosimy ich o wybranie lokalnej nazwy użytkownika (staramy się wstępnie wypełnić formularz ich istniejącą nazwą użytkownika od innego dostawcy). Posiadanie jakiejś formy lokalnego identyfikatora (e-mail, nazwa użytkownika) jest bardzo ważne dla późniejszego odzyskania konta.

Serwer wie, że jest to pierwsze logowanie, jeśli przeglądarka nie ma pliku cookie sesji (ważnego lub wygasłego) dla istniejącego konta, a używane konto strony trzeciej nie zostało znalezione. Staramy się poinformować użytkownika, że ​​nie tylko się loguje, ale tworzy nowe konto, więc jeśli ma już konto, miejmy nadzieję, że zamiast tego zatrzyma się i zaloguje się na swoje istniejące konto.

Używamy dokładnie tego samego przepływu do łączenia dodatkowych kont, ale gdy użytkownik wraca od strony trzeciej, obecność ważnego pliku cookie sesji jest używana do odróżnienia próby połączenia nowego konta z akcją logowania. Zezwalamy tylko na jedno konto innej firmy każdego typu, a jeśli jest już jedno połączone, blokuj akcję. Nie powinno to stanowić problemu, ponieważ interfejs do łączenia nowego konta jest wyłączony, jeśli już je masz (na dostawcę), ale na wszelki wypadek.

  • Jak połączyć konta?

Jeśli użytkownik próbował połączyć nowe konto innej firmy, które jest już połączone z kontem lokalnym, po prostu monitujesz go o potwierdzenie, że chce połączyć oba konta (zakładając, że możesz obsłużyć takie połączenie ze swoim zestawem danych - często łatwiej powiedzieć niż gotowe). Możesz również udostępnić im specjalny przycisk, aby poprosić o połączenie, ale w praktyce wszystko, co robią, to łączenie innego konta.

To jest dość prosta maszyna stanowa. Użytkownik wraca od firmy zewnętrznej z identyfikatorem konta innej firmy. Twoja baza danych może znajdować się w jednym z trzech stanów:

  1. Konto jest połączone z kontem lokalnym i nie ma plików cookie sesji -> Zaloguj się
  2. Konto jest połączone z kontem lokalnym i obecny jest plik cookie sesji -> Scal
  3. Konto nie jest połączone z kontem lokalnym i nie ma plików cookie sesji -> Rejestracja
  4. Konto nie jest połączone z kontem lokalnym i obecny jest plik cookie sesji -> Łączenie konta dodatkowego

    • Jak odzyskać konto u dostawców zewnętrznych?

To wciąż jest terytorium eksperymentalne. Nie widziałem do tego idealnego UX, ponieważ większość usług zapewnia zarówno lokalne hasło obok kont osób trzecich, a zatem koncentruje się na przypadku użycia „zapomniałem hasła”, a nie na wszystkim innym, co może pójść nie tak.

W przypadku Sled zdecydowaliśmy się na użycie opcji „Potrzebujesz pomocy przy logowaniu?” a kiedy klikniesz, poproś użytkownika o jego adres e-mail lub nazwę użytkownika. Sprawdzamy to i jeśli znajdziemy pasujące konto, wyślij do tego użytkownika e-mail z linkiem, który może automatycznie zalogować go do usługi (dobre tylko raz). Po wejściu przenosimy ich bezpośrednio do strony łączenia kont, informujemy, że powinni zajrzeć i potencjalnie połączyć dodatkowe konta, a także pokazać im konta innych firm, które już połączyli.

Eran Hammer
źródło
To rozwiązanie jest dla mnie znacznie lepsze, dzięki!
Roy Shoa
2
Plik cookie sesji nie jest wystarczająco dobry, aby zidentyfikować użytkownika. A jeśli inny użytkownik korzysta z tego samego urządzenia?
DeepBlue,
23

Oba podejścia do automatycznego łączenia kont pozostawiają dość dużą lukę, która pozwoliłaby komuś przejąć konto. Obaj wydają się zakładać, że użytkownik jest tym, za kogo się podaje, oferując opcję scalania rejestrującemu się użytkownikowi.

Moim zaleceniem, aby złagodzić tę lukę, jest poproszenie użytkownika o uwierzytelnienie u jednego ze znanych dostawców tożsamości przed wykonaniem scalenia w celu zweryfikowania tożsamości użytkownika.

Przykład: Użytkownik A rejestruje się z tożsamością Facebooka. Jakiś czas później wracają do Twojej witryny i próbują uzyskać dostęp za pomocą identyfikatora Windows Live i rozpocząć proces rejestracji. Twoja witryna wyświetli monit użytkownika A z… Wygląda na to, że zarejestrowałeś się wcześniej na Facebooku. Zaloguj się za pomocą Facebooka (podaj link), a będziemy mogli połączyć Twój identyfikator Windows Live z istniejącym profilem.

Inną alternatywą jest przechowywanie wspólnego hasła (hasła / pytania osobistego) podczas początkowej rejestracji, którą użytkownik musi podać podczas łączenia tożsamości, jednak w ten sposób z powrotem zaczniesz zajmować się przechowywaniem wspólnych sekretów. Oznacza to również, że musisz poradzić sobie ze scenariuszem, w którym użytkownik nie pamięta wspólnego hasła i przepływu pracy, który mu towarzyszy.

Brad J.
źródło
co zrobisz, jeśli nie otrzymasz adresu e-mail od dostawcy?
fred.kassi
1

Większość postów jest dość stara i wydaje mi się, że bezpłatnej usługi Google Firebase Authentication jeszcze nie było. Po weryfikacji za pomocą OAuth przekazujesz do niego token OAuth i uzyskujesz unikalny identyfikator użytkownika, który możesz przechowywać w celach informacyjnych. Obsługiwani dostawcy to Google, Facebook, Twitter, GitHub i istnieje możliwość rejestracji niestandardowych i anonimowych dostawców.

galki
źródło
Są przypadki użycia, w których Firebase nie ma sensu. Na przykład systemy intranetowe, które wymagają więcej niż jednego logowania…
Bostwick
-4

Powinieneś zezwolić na logowanie z jednego konta, a następnie po zalogowaniu dać opcję dodania innego konta, aby się z nim połączyć.

Naftali alias Neal
źródło
4
A co się stanie, jeśli użytkownik tego nie zrobi i znajdzie się z 4 różnymi kontami? Jak stworzyć architekturę, która w tym przypadku pozwala na scalenie?
David Boike,
W zależności od Twoich potrzeb może to być rzeczywiście ważna sugestia. Chcę tylko ostrzec tych, którzy uważają, że łączenie lub łączenie kont można wykonać później jako następstwo: Jeśli uważasz, że jest to coś, czego możesz chcieć później, na początku przygotuj się na to, projektując bazę danych: opcją jest posiadanie UserGroup i UserMapping. Możesz zmapować identyfikator użytkownika OAuth lub identyfikator użytkownika adresu e-mail i hasło do grupy użytkowników.
BumbleB2na