diff --git a/package-lock.json b/package-lock.json index 6ed2085560..9f1f06e5bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11958,13 +11958,12 @@ "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=" }, "passport": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/passport/-/passport-0.6.0.tgz", - "integrity": "sha512-0fe+p3ZnrWRW74fe8+SvCyf4a3Pb2/h7gFkQ8yTJpAO50gDzlfjZUZTO1k5Eg9kUct22OxHLqDZoKUWRHOh9ug==", + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/passport/-/passport-0.5.0.tgz", + "integrity": "sha512-ln+ue5YaNDS+fes6O5PCzXKSseY5u8MYhX9H5Co4s+HfYI5oqvnHKoOORLYDUPh+8tHvrxugF2GFcUA1Q1Gqfg==", "requires": { "passport-strategy": "1.x.x", - "pause": "0.0.1", - "utils-merge": "^1.0.1" + "pause": "0.0.1" } }, "passport-facebook": { diff --git a/package.json b/package.json index 196f12df1d..d226279891 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "nconf": "^0.12.0", "node-gcm": "^1.0.5", "on-headers": "^1.0.2", - "passport": "^0.6.0", + "passport": "^0.5.0", "passport-facebook": "^3.0.0", "passport-google-oauth2": "^0.2.0", "passport-google-oauth20": "2.0.0", diff --git a/website/server/controllers/api-v3/auth.js b/website/server/controllers/api-v3/auth.js index a0fc435731..7092066446 100644 --- a/website/server/controllers/api-v3/auth.js +++ b/website/server/controllers/api-v3/auth.js @@ -19,6 +19,7 @@ import { hasBackupAuth, loginSocial, registerLocal, + socialEmailToLocal, } from '../../libs/auth'; import { verifyUsername } from '../../libs/user/validation'; @@ -478,6 +479,7 @@ api.resetPasswordSetNewOne = { // set new password and make sure it's using bcrypt for hashing await passwordUtils.convertToBcrypt(user, String(newPassword)); user.auth.local.passwordResetCode = undefined; // Reset saved password reset code + if (!user.auth.local.email) user.auth.local.email = await socialEmailToLocal(user); await user.save(); return res.respond(200, {}, res.t('passwordChangeSuccess')); diff --git a/website/server/libs/auth/index.js b/website/server/libs/auth/index.js index 887902389e..30a5e70b15 100644 --- a/website/server/libs/auth/index.js +++ b/website/server/libs/auth/index.js @@ -12,7 +12,10 @@ import common from '../../../common'; import logger from '../logger'; import { decrypt } from '../encryption'; import { model as Group } from '../../models/group'; -import { loginSocial } from './social'; +import { + loginSocial, + socialEmailToLocal, +} from './social'; import { loginRes } from './utils'; import { verifyUsername } from '../user/validation'; @@ -227,4 +230,5 @@ export { hasLocalAuth, loginSocial, registerLocal, + socialEmailToLocal, }; diff --git a/website/server/libs/auth/social.js b/website/server/libs/auth/social.js index 61883a2f87..982f25310f 100644 --- a/website/server/libs/auth/social.js +++ b/website/server/libs/auth/social.js @@ -23,6 +23,21 @@ function _passportProfile (network, accessToken) { }); } +export async function socialEmailToLocal (user) { + const socialEmail = (user.auth.google && user.auth.google.emails + && user.auth.google.emails[0].value) + || (user.auth.facebook && user.auth.facebook.emails && user.auth.facebook.emails[0].value) + || (user.auth.apple && user.auth.apple.emails && user.auth.apple.emails[0].value); + if (socialEmail) { + const conflictingUser = await User.findOne( + { 'auth.local.email': socialEmail }, + { _id: 1 }, + ).exec(); + if (!conflictingUser) return socialEmail; + } + return null; +} + export async function loginSocial (req, res) { // eslint-disable-line import/prefer-default-export let existingUser = res.locals.user; const { network } = req.body; @@ -45,19 +60,25 @@ export async function loginSocial (req, res) { // eslint-disable-line import/pre [`auth.${network}.id`]: profile.id, }, { _id: 1, apiToken: 1, auth: 1 }).exec(); + let email; + if (profile.emails && profile.emails[0] && profile.emails[0].value) { + email = profile.emails[0].value.toLowerCase(); + } + // User already signed up if (user) { if (existingUser) { throw new NotAuthorized(res.t('socialAlreadyExists')); } + if (!user.auth.local.email) { + user.auth.local.email = await socialEmailToLocal(user); + if (user.auth.local.email) { + await user.save(); + } + } return loginRes(user, req, res); } - let email; - if (profile.emails && profile.emails[0] && profile.emails[0].value) { - email = profile.emails[0].value.toLowerCase(); - } - if (!existingUser && email) { existingUser = await User.findOne({ 'auth.local.email': email }).exec(); }