passport login error handling

This commit is contained in:
HF 2020-01-11 15:47:29 +01:00
parent c758fee082
commit 81e1d50aae
2 changed files with 102 additions and 59 deletions

View File

@ -12,9 +12,9 @@ import { Strategy as FacebookStrategy } from 'passport-facebook';
import { Strategy as VkontakteStrategy } from 'passport-vkontakte'; import { Strategy as VkontakteStrategy } from 'passport-vkontakte';
import { OAuth2Strategy as GoogleStrategy } from 'passport-google-oauth'; import { OAuth2Strategy as GoogleStrategy } from 'passport-google-oauth';
import logger from './logger';
import { sanitizeName } from '../utils/validation'; import { sanitizeName } from '../utils/validation';
import logger from './logger';
import { User, RegUser } from '../data/models'; import { User, RegUser } from '../data/models';
import { auth } from './config'; import { auth } from './config';
import { compareToHash } from '../utils/hash'; import { compareToHash } from '../utils/hash';
@ -50,37 +50,44 @@ passport.use(new JsonStrategy({
usernameProp: 'nameoremail', usernameProp: 'nameoremail',
passwordProp: 'password', passwordProp: 'password',
}, (nameoremail, password, done) => { }, (nameoremail, password, done) => {
// Decide if email or name by the occurance of @ try {
// this is why we don't allow @ in usernames // Decide if email or name by the occurance of @
// NOTE: could allow @ in the future by making an OR query, // this is why we don't allow @ in usernames
// but i guess nobody really cares. // NOTE: could allow @ in the future by making an OR query,
// https://sequelize.org/master/manual/querying.html // but i guess nobody really cares.
const query = (nameoremail.indexOf('@') !== -1) ? { email: nameoremail } : { name: nameoremail }; // https://sequelize.org/master/manual/querying.html
RegUser.findOne({ where: query }).then((reguser) => { const query = (nameoremail.indexOf('@') !== -1)
if (!reguser) { ? { email: nameoremail }
return done(null, false, { message: 'Name or Email does not exist!' }); : { name: nameoremail };
} RegUser.findOne({ where: query }).then((reguser) => {
if (!compareToHash(password, reguser.password)) { if (!reguser) {
return done(null, false, { message: 'Incorrect password!' }); return done(null, false, { message: 'Name or Email does not exist!' });
} }
const user = new User(reguser.id); if (!compareToHash(password, reguser.password)) {
user.regUser = reguser; return done(null, false, { message: 'Incorrect password!' });
user.updateLogInTimestamp(); }
return done(null, user); const user = new User(reguser.id);
}); user.regUser = reguser;
user.updateLogInTimestamp();
return done(null, user);
});
} catch (err) {
done(err);
}
})); }));
/* /*
* OAuth SignIns, mail based * OAuth SignIns, mail based
* *
*/ */
async function oauth_login(email, name, discordid = null) { async function oauthLogin(email, name, discordid = null) {
name = sanitizeName(name); name = sanitizeName(name);
let reguser = await RegUser.findOne({ where: { email } }); let reguser = await RegUser.findOne({ where: { email } });
if (!reguser) { if (!reguser) {
reguser = await RegUser.findOne({ where: { name } }); reguser = await RegUser.findOne({ where: { name } });
while (reguser) { while (reguser) {
// name is taken by someone else // name is taken by someone else
// eslint-disable-next-line max-len
name = `${name.substring(0, 15)}-${Math.random().toString(36).substring(2, 10)}`; name = `${name.substring(0, 15)}-${Math.random().toString(36).substring(2, 10)}`;
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
reguser = await RegUser.findOne({ where: { name } }); reguser = await RegUser.findOne({ where: { name } });
@ -109,10 +116,14 @@ passport.use(new FacebookStrategy({
proxy: true, proxy: true,
profileFields: ['displayName', 'email'], profileFields: ['displayName', 'email'],
}, async (req, accessToken, refreshToken, profile, done) => { }, async (req, accessToken, refreshToken, profile, done) => {
const { displayName: name, emails } = profile; try {
const email = emails[0].value; const { displayName: name, emails } = profile;
const user = await oauth_login(email, name); const email = emails[0].value;
done(null, user); const user = await oauthLogin(email, name);
done(null, user);
} catch (err) {
done(err);
}
})); }));
/** /**
@ -123,11 +134,20 @@ passport.use(new DiscordStrategy({
callbackURL: '/api/auth/discord/return', callbackURL: '/api/auth/discord/return',
proxy: true, proxy: true,
}, async (accessToken, refreshToken, profile, done) => { }, async (accessToken, refreshToken, profile, done) => {
// TODO get discord id try {
console.log({ profile, refreshToken, accessToken }); logger.info({ profile, refreshToken, accessToken });
const { id, email, username: name } = profile; const { id, email, username: name } = profile;
const user = await oauth_login(email, name, id); if (!email) {
done(null, user); done(null, false, {
// eslint-disable-next-line max-len
message: 'Sorry, you can not use discord login with an discord account that does not have email set.',
});
}
const user = await oauthLogin(email, name, id);
done(null, user);
} catch (err) {
done(err);
}
})); }));
/** /**
@ -138,10 +158,14 @@ passport.use(new GoogleStrategy({
callbackURL: '/api/auth/google/return', callbackURL: '/api/auth/google/return',
proxy: true, proxy: true,
}, async (accessToken, refreshToken, profile, done) => { }, async (accessToken, refreshToken, profile, done) => {
const { displayName: name, emails } = profile; try {
const email = emails[0].value; const { displayName: name, emails } = profile;
const user = await oauth_login(email, name); const email = emails[0].value;
done(null, user); const user = await oauthLogin(email, name);
done(null, user);
} catch (err) {
done(err);
}
})); }));
/* /*
@ -152,28 +176,34 @@ passport.use(new RedditStrategy({
callbackURL: '/api/auth/reddit/return', callbackURL: '/api/auth/reddit/return',
proxy: true, proxy: true,
}, async (accessToken, refreshToken, profile, done) => { }, async (accessToken, refreshToken, profile, done) => {
console.log({ profile, refreshToken, accessToken }); try {
const redditid = profile.id; logger.info({ profile, refreshToken, accessToken });
let name = sanitizeName(profile.name); const redditid = profile.id;
// reddit needs an own login strategy based on its id, let name = sanitizeName(profile.name);
// because we can not access it's mail // reddit needs an own login strategy based on its id,
let reguser = await RegUser.findOne({ where: { redditid } }); // because we can not access it's mail
if (!reguser) { let reguser = await RegUser.findOne({ where: { redditid } });
reguser = await RegUser.findOne({ where: { name } }); if (!reguser) {
while (reguser) {
// name is taken by someone else
name = `${name.substring(0, 15)}-${Math.random().toString(36).substring(2, 10)}`;
reguser = await RegUser.findOne({ where: { name } }); reguser = await RegUser.findOne({ where: { name } });
while (reguser) {
// name is taken by someone else
// eslint-disable-next-line max-len
name = `${name.substring(0, 15)}-${Math.random().toString(36).substring(2, 10)}`;
// eslint-disable-next-line no-await-in-loop
reguser = await RegUser.findOne({ where: { name } });
}
reguser = await RegUser.create({
name,
verified: 1,
redditid,
});
} }
reguser = await RegUser.create({ const user = new User(reguser.id);
name, user.regUser = reguser;
verified: 1, done(null, user);
redditid, } catch (err) {
}); done(err);
} }
const user = new User(reguser.id);
user.regUser = reguser;
done(null, user);
})); }));
/** /**
@ -186,11 +216,15 @@ passport.use(new VkontakteStrategy({
scope: ['email'], scope: ['email'],
profileFields: ['displayName', 'email'], profileFields: ['displayName', 'email'],
}, async (accessToken, refreshToken, params, profile, done) => { }, async (accessToken, refreshToken, params, profile, done) => {
console.log(profile); try {
const { displayName: name } = profile; logger.info(profile);
const { email } = params; const { displayName: name } = profile;
const user = await oauth_login(email, name); const { email } = params;
done(null, user); const user = await oauthLogin(email, name);
done(null, user);
} catch (err) {
done(err);
}
})); }));

View File

@ -69,7 +69,10 @@ export default (passport) => {
'Content-Type': 'text/html', 'Content-Type': 'text/html',
}); });
const host = getHostFromRequest(req); const host = getHostFromRequest(req);
const index = getHtml('OAuth Authentification', 'LogIn failed :(, please try again later or register a new account with Mail.', host); // eslint-disable-next-line max-len
const text = 'LogIn failed :(, please try again later or register a new account with mail.';
const message = (req.session) ? req.session.flash : text;
const index = getHtml('OAuth Authentification', message, host);
res.status(200).send(index); res.status(200).send(index);
}); });
@ -105,7 +108,13 @@ export default (passport) => {
logger.info(`User ${user.id} logged in with mail/password.`); logger.info(`User ${user.id} logged in with mail/password.`);
req.logIn(user, async (e) => { req.logIn(user, async (e) => {
if (e) { res.json({ success: false, errors: ['Failed to establish session. Please try again later :('] }); return; } if (e) {
res.json({
success: false,
errors: ['Failed to establish session. Please try again later :('],
});
return;
}
user.ip = req.user.ip; user.ip = req.user.ip;
const me = await getMe(user); const me = await getMe(user);