Architettura per unire più account utente insieme


176

Ok, ho un sito web dove puoi registrarti e accedere. Puoi anche accedere con il tuo account Facebook, Twitter o linkedin.

È importante che gli utenti abbiano un solo account registrato. Quindi, in qualche modo, voglio unire gli account degli utenti se usano metodi diversi per accedere. Qual è la soluzione migliore per risolvere questo?

Ad esempio, l'utente accede con il suo account Facebook. Uso i dati per registrare automaticamente un account per lui. Devo inviare un'e-mail con un nome utente e una password del nostro sito Web? (Se questo va bene con la politica di Facebook). Devo dare loro una seconda schermata in cui possono inserire un nome utente e una password? Ma questa non è l'idea alla base dell'accesso con il tuo account Facebook. Dovrebbe semplificare la procedura di partecipazione.

È anche possibile che l'utente si sia registrato sul nostro sito Web e la prossima volta che accede con il suo account Twitter. Come posso unire questi 2 account come uno? Qual è il modo migliore?

Quindi sostanzialmente la mia domanda è: ho 4 modi diversi in cui un utente diventa membro del nostro sito web. Come posso assicurarmi che tutti questi 4 modi creino un solo account se un utente decide di utilizzare più modi? Qual è il flusso migliore per assicurarsi che non diventi una seccatura per l'utente stesso?


Modificare:

3 anni dopo che ho posto questa domanda, sto dando io stesso la risposta in una serie di articoli: 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/


7
Ovviamente è meglio cercare di impedire a un utente di avere più account in primo luogo consentendo più metodi di accesso come Stack Overflow, ma anche SO ha la possibilità per i moderatori di unire gli account. Offro generosità a chiunque sappia descrivere un'architettura per permetterlo. Deve esserci una soluzione migliore di "update post set UserID = 2 dove UserID = 1"
David Boike

e-mail e telefono possono essere usati come chiave di fusione, altri?
Wuaner,

Ciao, il link che hai fornito non sembra funzionare. Va solo sulla homepage del sito
vigamage

Aggiornato i collegamenti. Gli articoli hanno 6 anni però.
PT

Risposte:


120

Mi trovo ad affrontare esattamente lo stesso compito al momento. Il design che ho elaborato è piuttosto semplice, ma funziona bene.

L'idea principale è che i modelli per l'identità di un sito locale e le identità del sito di terze parti siano mantenuti isolati, ma in seguito siano collegati. Quindi ogni utente che accede al sito ha un'identità locale che si associa a un numero qualsiasi di identità del sito di terze parti.

Un record di identità locale contiene un minimo di informazioni - potrebbe anche essere un singolo campo - solo una chiave primaria. (Per la mia applicazione, non mi interessa l'e-mail, il nome o la data di nascita dell'utente - Voglio solo sapere che sono la persona che ha effettuato l'accesso a questo account da sempre.)

Le identità di terze parti contengono informazioni rilevanti solo per l'autenticazione con una terza parte. Per OAuth, ciò significa in genere un identificatore utente (come un ID, e-mail o nome utente) e un identificatore del servizio (che indica con quale sito o servizio è stato autenticato). In altre parti dell'applicazione, al di fuori del database, quell'identificatore di servizio è associato a un metodo per recuperare l'identificatore utente rilevante da quel servizio, ed è così che viene eseguita l'autenticazione. Per OpenID, utilizziamo lo stesso approccio, tranne per il fatto che il metodo di autenticazione è più generalizzato (perché possiamo quasi sempre eseguire lo stesso protocollo esatto - tranne per il fatto che utilizziamo un URL di identità diverso e che è il nostro identificatore del servizio).

Infine, tengo un registro di quali identità di terze parti sono associate all'identità locale. Per generare questi record, il flusso è simile al seguente:

  • Un utente accede per la prima volta utilizzando un'identità di terze parti. Viene creato un record di identità locale, quindi un record di identità di terze parti e quindi vengono accoppiati.
  • In un pannello di controllo, all'utente viene offerta la possibilità di collegare un account accedendo a servizi di terze parti. (Abbastanza semplice come funziona.)
  • Nello scenario in cui l'utente crea involontariamente più account, la soluzione è piuttosto semplice. Mentre l'utente ha effettuato l'accesso a uno degli account, accede a un altro che in precedenza aveva utilizzato per accedere al sito (tramite la funzionalità del pannello di controllo sopra). Il servizio Web rileva questa collisione (che l'identità locale dell'utente che ha effettuato l'accesso differisce dall'identità locale collegata all'identità di terze parti che ha appena effettuato l'accesso) e all'utente viene richiesto di unire l'account.

L'unione degli account è una questione di fusione di ogni singolo campo dell'identità locale (che varierà da un'applicazione all'altra e dovrebbe essere facile se hai solo un paio di campi nei tuoi record di identità locali) e quindi garantire le identità di terze parti collegate sono collegati all'identità locale risultante.


1
Questa è un'ottima soluzione (adoro l'idea di rilevare automaticamente la collisione dell'identità locale)! Mi chiedo se hai trovato un modo per accedere automaticamente all'utente agli account "extra" che sono collegati dopo il primo accesso all'applicazione. L'utente dovrebbe accedere separatamente a ciascun account ogni volta che visita (se non esiste già una sessione attiva con questo provider)?
Alexandra,

@Alexandra Cosa intendi con "account extra"? Stai chiedendo cosa succede quando l'utente accede all'applicazione tramite diversi autenticatori diversi, creando una nuova identità locale con ciascuno?
Cheeken,

Immagino che ciò meriti un chiarimento adeguato e una sua domanda: stackoverflow.com/questions/11060368/…
Alexandra,

3
Domanda però, ma cosa succede se l'utente si registra al sito utilizzando lo stesso indirizzo e-mail? chiediamo loro che l'e-mail esiste già (l'e-mail proveniente dal modello di terze parti) o li registriamo ancora sul sito e quindi abbiamo unito questi account?
user962206,

@utente962206 molti servizi non ti forniranno comunque l'indirizzo di posta elettronica "reale" per motivi di privacy. Ad esempio, Twitter non ti fornirà alcun indirizzo e-mail, per quanto ne so Facebook fornirà "user.name@facebook.com" che dubito che qualcuno userebbe per la registrazione.
Kapex,

44

Tendo a trovare molti siti che si fondono in base alla posta elettronica come fattore di sovrapposizione.

Vedo che questa è un'opzione praticabile, ma di nuovo dipende dalle tue preferenze su come unire. L'indirizzo e-mail è il modo principale utilizzato dalle persone per verificare alcune importanti modifiche alle informazioni sul tuo sito come, cambiare la password, terminare il servizio, il saldo dell'account è basso ecc ... È quasi come il sistema di numeri di sicurezza sociale del web ma con la capacità di comunicazione . Culturalmente: penso che sia ragionevole presumere che un'e-mail sia un'identità piuttosto unica nei servizi di autenticazione OAuth. Certo, è ciò che chiedono i moduli di accesso per Facebook e Google.

Il mio attuale processo di pensiero.

La pagina di accesso ha 3 opzioni

  • Iscrizione al tuo sito
  • Fai il login con facebook
  • Accedi con google

1) Accessi utente per la prima volta: attiva un flusso di registrazione in cui un account viene creato e popolato per la prima volta.

 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     | "newuser@coolmail.com" |  *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     | newuser@coolmail.com |  myCoolPwd  ]

2) In un altro momento, l'utente torna ma decide di fare clic su Google Login

      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) Ora hai unito l'account con cui ti fidi che l'e-mail sulle voci del tuo database siano le stesse di quelle di cui ti fidi dagli accessi esterni.

Quindi per i successivi accessi

Quindi cosa succede se si dispone prima di accessi esterni e quindi si desidera che un utente possa accedere con una password in un secondo momento?

Vedo due semplici modi per farlo

  • Ad ogni primo accesso quando viene creato un account da un'autorità esterna, chiedi loro una password per completare la loro prima entrata nella tua applicazione

  • Se si sono già registrati utilizzando prima Facebook o Google, in qualche modo vogliono registrarsi utilizzando il modulo di registrazione del proprio sito. Rileva se l'indirizzo e-mail che hanno inserito esiste già, chiedi loro una password e invia loro una e-mail di conferma al termine della registrazione.


1
Quando usi uno schema di autenticazione esterno (Facebook, Google, Twitter ecc ...) non avrai mai accesso alla password del provider esterno. La password nell'esempio sopra è la password per la tua app Web PROPRIA.
Max Alexander

6
Twitter non offre agli utenti la posta elettronica. Quindi, dopo la loro prima autenticazione, se l'ID utente di Twitter non esiste, richiedi e-mail e password. Se l'e-mail e la password esistono, collegare gli account. In caso contrario, conservare l'e-mail e la password per autenticazioni successive senza interruzioni. Ti è stato di aiuto?
Max Alexander

1
Come nota a margine, ora è possibile richiedere le autorizzazioni per l'app di Twitter per ottenere l'indirizzo e-mail dell'utente.
Sunil D.24

2
Facebook fa sì che le persone verifichino la loro e-mail? So che Github, per esempio, non lo fa. Un utente malintenzionato potrebbe iscriversi a Github con il nome e-mail di qualcun altro e quindi ottenere l'accesso al proprio account sul proprio sito con questa strategia. (L'API di Github ti dice se la loro e-mail è verificata o meno - potresti rifiutare chiunque si autentichi con Github su un indirizzo e-mail non verificato)
Matthew Moisen

6
Questa è una violazione della sicurezza se un utente si registra tramite i social media, modifica il proprio indirizzo e-mail nei social media, qualcun altro prende lo stesso indirizzo e-mail, si registra sui social media e quindi effettua l'accesso, verrà unito a un altro account. Questo è molto improbabile, ma comunque una violazione. Oppure mi sfugge qualcosa.
Shane,

35

Ci sono passato con sled.com. Ci sono più problemi qui per quanto riguarda la creazione di account e il supporto di più account di terze parti per l'accesso. Alcuni di loro sono:

  • Devi supportare sia una password locale che accessi di terze parti?

Per sled.com, ho deciso di eliminare la password locale a causa del piccolo valore aggiunto e del costo aggiuntivo per la protezione di un modulo di immissione della password. Esistono molti attacchi noti per la violazione delle password e, se si intende introdurre password, è necessario assicurarsi che non siano facili da violare. È inoltre necessario memorizzarli in un hash unidirezionale o qualcosa di simile per evitare che trapelino.

  • Quanta flessibilità vuoi consentire nel supportare più account di terze parti?

Sembra che tu abbia già scelto i tre provider di accesso: Facebook, Twitter e LinkedIn. È fantastico perché significa che stai utilizzando OAuth e stai lavorando con un set ben definito di provider affidabili. Non sono un fan di OpenID. La domanda rimanente è se è necessario supportare più account di terze parti dallo stesso provider (ad esempio un account locale con due account Twitter collegati). Suppongo di no, ma se lo fai, dovrai adattarlo nel tuo modello di dati.

Per Sled, supportiamo l'accesso con Facebook, Twitter e Yahoo! e all'interno di ciascun account utente memorizzare una chiave per ognuno: {"_id": "djdjd99dj", "yahoo": "dj39djdj", twitter: "3723828732", "facebook": "12837287"}. Abbiamo impostato una serie di vincoli per garantire che ogni account di terze parti possa essere collegato solo a un singolo account locale.

Se hai intenzione di consentire più account dallo stesso fornitore di terze parti, dovrai utilizzare elenchi o altre strutture per supportare tale e, con ciò, tutte le altre restrizioni per garantire l'univocità.

  • Come collegare più account?

La prima volta che l'utente si iscrive al servizio, si rivolge innanzitutto al provider di terze parti e restituisce un ID di terze parti verificato. Quindi crei un account locale per loro e raccogli qualsiasi altra informazione desideri. Raccogliamo il loro indirizzo e-mail e chiediamo anche loro di scegliere un nome utente locale (proviamo a precompilare il modulo con il loro nome utente esistente dall'altro fornitore). Avere una qualche forma di identificatore locale (e-mail, nome utente) è molto importante per il recupero dell'account in un secondo momento.

Il server sa che si tratta del primo accesso se il browser non ha un cookie di sessione (valido o scaduto) per un account esistente e che l'account di terze parti utilizzato non viene trovato. Cerchiamo di informare l'utente che non stanno solo effettuando l'accesso, ma stanno creando un nuovo account in modo che, se hanno già un account, si speri che si interrompano e accedano con il loro account esistente.

Usiamo lo stesso flusso esatto per collegare account aggiuntivi, ma quando l'utente ritorna da una terza parte, viene utilizzata la presenza di un cookie di sessione valido per distinguere tra un tentativo di collegare un nuovo account a un'azione di accesso. Consentiamo solo un account di terze parti per ciascun tipo e se ne esiste già uno collegato, blocca l'azione. Non dovrebbe essere un problema perché l'interfaccia per collegare un nuovo account è disabilitata se ne hai già uno (per provider), ma per ogni evenienza.

  • Come unire gli account?

Se un utente ha tentato di collegare un nuovo account di terze parti che è già collegato a un account locale, è sufficiente richiedere loro di confermare che desiderano unire i due account (supponendo che sia possibile gestire tale unione con il proprio set di dati - spesso più facile a dirlo di fatto). Puoi anche fornire loro un pulsante speciale per richiedere un'unione, ma in pratica tutto ciò che stanno facendo è collegare un altro account.

Questa è una macchina a stati piuttosto semplice. L'utente torna dalla terza parte con un ID account di terze parti. Il database può trovarsi in uno dei tre stati:

  1. L'account è collegato a un account locale e non è presente alcun cookie di sessione -> Accesso
  2. L'account è collegato a un account locale ed è presente un cookie di sessione -> Unisci
  3. L'account non è collegato a un account locale e non è presente alcun cookie di sessione -> Iscriviti
  4. L'account non è collegato a un account locale ed è presente un cookie di sessione -> Collegamento di un account aggiuntivo

    • Come eseguire il recupero dell'account con fornitori di terze parti?

Questo è ancora territorio sperimentale. Non ho visto un UX perfetto per questo in quanto la maggior parte dei servizi fornisce sia una password locale accanto agli account di terze parti e quindi si concentra sul caso d'uso "password dimenticata", non su tutto ciò che può andare storto.

Con Sled, abbiamo scelto di utilizzare "Hai bisogno di aiuto per accedere?" e quando fai clic, chiedi all'utente la sua e-mail o nome utente. Lo cerchiamo e se troviamo un account corrispondente, inviamo a quell'utente un link che può accedere automaticamente al servizio (valido per una volta). Una volta entrati, li portiamo direttamente alla pagina di collegamento dell'account, diciamo loro che dovrebbero dare un'occhiata e potenzialmente collegare altri account e mostriamo loro gli account di terze parti che hanno già collegato.


Questa soluzione è molto meglio per me, grazie!
Roy Shoa,

2
Il cookie di sessione non è abbastanza buono per identificare l'utente. Cosa succede se un altro utente utilizza lo stesso dispositivo?
DeepBlue,

23

Entrambi gli approcci per la fusione automatica degli account lasciano una grande vulnerabilità che consentirebbe a qualcuno di acquisire un account. Entrambi sembrano ipotizzare che l'utente sia quello che dicono di essere quando offrono l'opzione di unione a un utente registrato.

La mia raccomandazione per mitigare la vulnerabilità è di richiedere all'utente di autenticarsi con uno dei provider di identità noti prima di eseguire l'unione per verificare l'identità dell'utente.

Esempio: l'utente A registra con l'identità di Facebook. Qualche tempo dopo tornano sul tuo sito e tentano di accedere con Windows Live ID e avviano il processo di registrazione. Il tuo sito richiederà all'utente A con ... Sembra che tu ti sia registrato con Facebook in precedenza. Effettua il login con Facebook (fornisci il link) e possiamo unire il tuo Windows Live ID con il tuo profilo esistente.

Un'altra alternativa è quella di archiviare un segreto condiviso (password / domanda personale) sulla registrazione iniziale che l'utente deve fornire quando si uniscono le identità, tuttavia questo ti riporta al business della memorizzazione dei segreti condivisi. Significa anche che devi gestire lo scenario in cui l'utente non ricorda il segreto condiviso e il flusso di lavoro che lo accompagna.


cosa fai se non ricevi un indirizzo email dal provider?
fred.kassi,

1

La maggior parte dei post sono piuttosto vecchi e immagino che il servizio gratuito di autenticazione Firebase di Google non fosse ancora in circolazione. Dopo aver verificato con OAuth, si passa il token OAuth e si ottiene un ID utente univoco che è possibile memorizzare come riferimento. I provider supportati sono Google, Facebook, Twitter, GitHub e c'è un'opzione per registrare provider personalizzati e anonimi.


Ci sono casi d'uso pensati in cui firebase non ha senso. Ad esempio, i sistemi intranet che hanno più di un accesso.
Bostwick,


-4

Dovresti consentire l'accesso da un account, quindi quando accedi dai l'opzione di aggiungere un altro account per unirti a esso.


4
E cosa succede se l'utente non lo fa e si trova con 4 account distinti? Come si crea un'architettura che consente un'unione in questo caso?
David Boike,

A seconda delle esigenze, questo può effettivamente essere un suggerimento valido. Voglio solo avvertire coloro che pensano che la fusione o il collegamento di account potrebbe essere fatto in seguito come un post-pensiero: se ritieni che questo sia qualcosa che potresti desiderare in seguito, ti consigliamo di prepararti per quello all'inizio con la progettazione del tuo database: Uno l'opzione è di avere un gruppo utenti e un UserMapping. È possibile mappare l'ID utente OAuth o l'ID utente e-mail e password a un gruppo utenti.
BumbleB2na,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.