This is probably a question a bit in between SO and UX.se.
I'm implementing a signup/login sytem which allows for multiple ways of authentication: social signups using Facebook, Twitter, Github and a local (username + password) signup.
In the backend I'm having a User model and a Passport model. A User may have multiple Passports, meaning a User may authenticate through different means (e.g.: through local signin,. or through facebook for example)
For good measure: the Passports of a particular User will always be from a different provider (facebook, twitter, local). I.e.: a Facebook-passport, a Local-passport, etc.
This seems like a good way and would allow me to have a User account connected to multiple ways of authentication.
I'm familiar with the security issues this might raise, so for passports to be combined/merged a User has to be logged in to both.
Ok on to the problem. Consider the following flow:
Currently, I've defined email to be unique on the User-model. This would mean the above signup would fail, because there's already a User-account that, by means of the local Passport, has the mentioned email-address.
What would be considered a best practice in a situation like this? I trust there must be many implementations floating around that must have seen this problem pop-up.
Options:
<user,email>, but on <passport, email>. This would allow a new User and associated Passport to be created and all goes well. Now the same actual person probably has 2 User Accounts: 1 for each authentication provider. As a next stage allow the User-accounts to be merged, by signing in to both and acknowledging the merge. I'm leaning towards 3, but 1 is simpler. I'm not sure, what do you think? Have you encountered this before?
Yes, #3. I have implemented this myself. The concept you're looking at is: Associate multiple SSO accounts. My user structure is as follows:
name : {
first: { type: String},
last: { type: String }
},
emails: [{ type: String, unique: true, 'index': true }], //all known emails as provided by SSO services. we use this to cross ref when the user uses a different SSO to login after initial setup. this avoids account dupes
sso: [{
provider: { type: String, required: true}, //matches the name of passport strategy name employed
userid: { type: String, required: true } //the specific SSO provider userID that's unique in the provider's realm
}]
So, in your auth sequence, you look it up by email OR provider+userid combo, if you don't find the SSO provider, you attach it. The reason for or, someone may update their email but the specific SSO provider ID never changes.
Another common practice (if it makes sense in your app) is to allow the user to "link" SSO accounts. That allows you to handle different email addresses. Example: user FB email is a personal one but in LinkedIn he lists as primary the business one. LinkedIn sadly gives you only the primary via their OAuth2 call.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With