Skip to content

Commit bb8c4a2

Browse files
committed
Link OAuth accounts with different email from account email
1 parent 050b3ed commit bb8c4a2

File tree

1 file changed

+88
-62
lines changed

1 file changed

+88
-62
lines changed

server/config/passport.js

Lines changed: 88 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -96,39 +96,52 @@ passport.use(new GitHubStrategy({
9696
}, (req, accessToken, refreshToken, profile, done) => {
9797
User.findOne({ github: profile.id }, (findByGithubErr, existingUser) => {
9898
if (existingUser) {
99+
if (req.user && req.user.email !== existingUser.email) {
100+
done(new Error('GitHub account is already linked to another account.'));
101+
return;
102+
}
99103
done(null, existingUser);
100104
return;
101105
}
102106

103107
const emails = getVerifiedEmails(profile.emails);
104108
const primaryEmail = getPrimaryEmail(profile.emails);
105109

106-
User.findByEmail(emails, (findByEmailErr, existingEmailUser) => {
107-
if (existingEmailUser) {
108-
existingEmailUser.email = existingEmailUser.email || primaryEmail;
109-
existingEmailUser.github = profile.id;
110-
existingEmailUser.username = existingEmailUser.username || profile.username;
111-
existingEmailUser.tokens.push({ kind: 'github', accessToken });
112-
existingEmailUser.name = existingEmailUser.name || profile.displayName;
113-
existingEmailUser.verified = User.EmailConfirmation.Verified;
114-
existingEmailUser.save(saveErr => done(null, existingEmailUser));
115-
} else {
116-
let { username } = profile;
117-
User.findByUsername(username, { caseInsensitive: true }, (findByUsernameErr, existingUsernameUser) => {
118-
if (existingUsernameUser) {
119-
username = generateUniqueUsername(username);
120-
}
121-
const user = new User();
122-
user.email = primaryEmail;
123-
user.github = profile.id;
124-
user.username = profile.username;
125-
user.tokens.push({ kind: 'github', accessToken });
126-
user.name = profile.displayName;
127-
user.verified = User.EmailConfirmation.Verified;
128-
user.save(saveErr => done(null, user));
129-
});
110+
if (req.user) {
111+
if (!req.user.github) {
112+
req.user.github = profile.id;
113+
req.user.tokens.push({ kind: 'github', accessToken });
114+
req.user.verified = User.EmailConfirmation.Verified;
130115
}
131-
});
116+
req.user.save(saveErr => done(null, req.user));
117+
} else {
118+
User.findByEmail(emails, (findByEmailErr, existingEmailUser) => {
119+
if (existingEmailUser) {
120+
existingEmailUser.email = existingEmailUser.email || primaryEmail;
121+
existingEmailUser.github = profile.id;
122+
existingEmailUser.username = existingEmailUser.username || profile.username;
123+
existingEmailUser.tokens.push({ kind: 'github', accessToken });
124+
existingEmailUser.name = existingEmailUser.name || profile.displayName;
125+
existingEmailUser.verified = User.EmailConfirmation.Verified;
126+
existingEmailUser.save(saveErr => done(null, existingEmailUser));
127+
} else {
128+
let { username } = profile;
129+
User.findByUsername(username, { caseInsensitive: true }, (findByUsernameErr, existingUsernameUser) => {
130+
if (existingUsernameUser) {
131+
username = generateUniqueUsername(username);
132+
}
133+
const user = new User();
134+
user.email = primaryEmail;
135+
user.github = profile.id;
136+
user.username = profile.username;
137+
user.tokens.push({ kind: 'github', accessToken });
138+
user.name = profile.displayName;
139+
user.verified = User.EmailConfirmation.Verified;
140+
user.save(saveErr => done(null, user));
141+
});
142+
}
143+
});
144+
}
132145
});
133146
}));
134147

@@ -144,49 +157,62 @@ passport.use(new GoogleStrategy({
144157
}, (req, accessToken, refreshToken, profile, done) => {
145158
User.findOne({ google: profile._json.emails[0].value }, (findByGoogleErr, existingUser) => {
146159
if (existingUser) {
160+
if (req.user && req.user.email !== existingUser.email) {
161+
done(new Error('Google account is already linked to another account.'));
162+
return;
163+
}
147164
done(null, existingUser);
148165
return;
149166
}
150167

151168
const primaryEmail = profile._json.emails[0].value;
152169

153-
User.findByEmail(primaryEmail, (findByEmailErr, existingEmailUser) => {
154-
let username = profile._json.emails[0].value.split('@')[0];
155-
User.findByUsername(username, { caseInsensitive: true }, (findByUsernameErr, existingUsernameUser) => {
156-
if (existingUsernameUser) {
157-
username = generateUniqueUsername(username);
158-
}
159-
// what if a username is already taken from the display name too?
160-
// then, append a random friendly word?
161-
if (existingEmailUser) {
162-
existingEmailUser.email = existingEmailUser.email || primaryEmail;
163-
existingEmailUser.google = profile._json.emails[0].value;
164-
existingEmailUser.username = existingEmailUser.username || username;
165-
existingEmailUser.tokens.push({ kind: 'google', accessToken });
166-
existingEmailUser.name = existingEmailUser.name || profile._json.displayName;
167-
existingEmailUser.verified = User.EmailConfirmation.Verified;
168-
existingEmailUser.save((saveErr) => {
169-
if (saveErr) {
170-
console.log(saveErr);
171-
}
172-
done(null, existingEmailUser);
173-
});
174-
} else {
175-
const user = new User();
176-
user.email = primaryEmail;
177-
user.google = profile._json.emails[0].value;
178-
user.username = username;
179-
user.tokens.push({ kind: 'google', accessToken });
180-
user.name = profile._json.displayName;
181-
user.verified = User.EmailConfirmation.Verified;
182-
user.save((saveErr) => {
183-
if (saveErr) {
184-
console.log(saveErr);
185-
}
186-
done(null, user);
187-
});
188-
}
170+
if (req.user) {
171+
if (!req.user.google) {
172+
req.user.google = profile._json.emails[0].value;
173+
req.user.tokens.push({ kind: 'google', accessToken });
174+
req.user.verified = User.EmailConfirmation.Verified;
175+
}
176+
req.user.save(saveErr => done(null, req.user));
177+
} else {
178+
User.findByEmail(primaryEmail, (findByEmailErr, existingEmailUser) => {
179+
let username = profile._json.emails[0].value.split('@')[0];
180+
User.findByUsername(username, { caseInsensitive: true }, (findByUsernameErr, existingUsernameUser) => {
181+
if (existingUsernameUser) {
182+
username = generateUniqueUsername(username);
183+
}
184+
// what if a username is already taken from the display name too?
185+
// then, append a random friendly word?
186+
if (existingEmailUser) {
187+
existingEmailUser.email = existingEmailUser.email || primaryEmail;
188+
existingEmailUser.google = profile._json.emails[0].value;
189+
existingEmailUser.username = existingEmailUser.username || username;
190+
existingEmailUser.tokens.push({ kind: 'google', accessToken });
191+
existingEmailUser.name = existingEmailUser.name || profile._json.displayName;
192+
existingEmailUser.verified = User.EmailConfirmation.Verified;
193+
existingEmailUser.save((saveErr) => {
194+
if (saveErr) {
195+
console.log(saveErr);
196+
}
197+
done(null, existingEmailUser);
198+
});
199+
} else {
200+
const user = new User();
201+
user.email = primaryEmail;
202+
user.google = profile._json.emails[0].value;
203+
user.username = username;
204+
user.tokens.push({ kind: 'google', accessToken });
205+
user.name = profile._json.displayName;
206+
user.verified = User.EmailConfirmation.Verified;
207+
user.save((saveErr) => {
208+
if (saveErr) {
209+
console.log(saveErr);
210+
}
211+
done(null, user);
212+
});
213+
}
214+
});
189215
});
190-
});
216+
}
191217
});
192218
}));

0 commit comments

Comments
 (0)