trailsjs / sails-auth

Passport-based User Authentication system for sails.js applications. Designed to work well with the sails-permissions module.
https://www.npmjs.org/package/sails-auth
MIT License
265 stars 141 forks source link

Duplicate user error when an unauthenticated user tries to login with an external provider when already having a local identity. #98

Open justinwatkins opened 8 years ago

justinwatkins commented 8 years ago

from api/passport.js. connect method // Scenario: A new user is attempting to sign up using a third-party // authentication provider. // Action: Create a new user and assign them a passport. if (!passport) { return sails.models.user.create(user) .then(function (_user) { user = user; return sails.models.passport.create(.extend({ user: user.id }, query)) }) .then(function (passport) { next(null, user); }) .catch(next); }

The use case of a user creates a local account. The user comes back in another time and clicks a passport-[external] without an active session and auth (because users do that kind of thing). In this scenario there will be no req.user and no passport and user.create will eventually throw a duplicate key error on username or email if the user used either.

The simple fix is just change that .create to a .findOrCreate and match on emails since the assumption is it's the same person.

A more complicated fix is to mimic other identity providers that account for mixing internal / external auth with a partial login status and an explicit external authentication call back that allows the app to decide how to bind external and local accounts.

sample flow:

user clicks on external auth provider external auth provider responds with a success (access or identity token) auth system calls external login callback [(sample external login callback) check if external identity is mapped to local account: yes - set status return full login no - { check if user identity exists by identifier: yes - ask user to provider existing username & password, map accounts return full login no - ask user to register a local account, map external account return full login } ]

joshbuckley182 commented 8 years ago

+1

I had the same issue (using facebook-token, user logs in again from another browser/device, and app attempts to create duplicate user), and the user.create to user.findOrCreate solution solved it.