updated database, sessions managed via signed JWT
token. TODO: sign tokens based user unique token, instead of global salt keypull/4/head
parent
7590e9b644
commit
acf084743d
|
@ -23,6 +23,27 @@ async function readJWT(token) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function signIn(email, password) {
|
||||||
|
|
||||||
|
let account = await models_orm.models.accounts.findOne({where: {email: email}});
|
||||||
|
|
||||||
|
|
||||||
|
if (account.dataValues) {
|
||||||
|
account = account.dataValues;
|
||||||
|
|
||||||
|
const inputPassword = crypto.createHash('sha256').update(password + config.applicationSalt).digest('hex');
|
||||||
|
|
||||||
|
if (account.password === inputPassword) {
|
||||||
|
const token = jwt.sign({accountId: account.id}, config.applicationSalt)
|
||||||
|
return {success: true, jwt: token};
|
||||||
|
} else {
|
||||||
|
return {success: false, msg: 'BAD PASSWORD', invalidPassword: true}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return {success: false, msg: 'BAD ACCOUNT', badAccount: true}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async function changePassword(account, newPassword, oldPassword) {
|
async function changePassword(account, newPassword, oldPassword) {
|
||||||
if (!account || !newPassword || !oldPassword) { return {success: false, error: 'MISSING_DATA'}}
|
if (!account || !newPassword || !oldPassword) { return {success: false, error: 'MISSING_DATA'}}
|
||||||
|
@ -42,29 +63,37 @@ async function changePassword(account, newPassword, oldPassword) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
TODO: update rest of the code to support authentication rejection reasons
|
||||||
|
*/
|
||||||
|
|
||||||
async function getAuthenticatedAccount(req, res) {
|
async function getAuthenticatedAccount(req, res) {
|
||||||
const sessionCookie = (req.signedCookies !== undefined ? req.signedCookies.session : null);
|
const sessionJWT = (req.signedCookies !== undefined ? req.signedCookies.jwt : null)
|
||||||
if (!sessionCookie || sessionCookie.expires <= Date.now()) { return null; }
|
if ((!sessionJWT || sessionJWT.expires <= Date.now())) { return null; }
|
||||||
const email = sessionCookie.account.trim().toLowerCase();
|
const token = jwt.verify(sessionJWT, config.applicationSalt);
|
||||||
|
|
||||||
// TODO stop storing emails in the cookie
|
if (token && token.accountId) {
|
||||||
const account = await models_orm.models.accounts.findOne({where: {email: email}});
|
const account = await models_orm.models.accounts.findOne({where: {id: token.accountId}});
|
||||||
|
|
||||||
if (account.dataValues) {
|
if (account.dataValues) {
|
||||||
const update = models_orm.models.accounts.update({ last_ping: Date.now() },
|
const update = models_orm.models.accounts.update({ last_ping: Date.now() },
|
||||||
{ where: { id: account.id } }
|
{ where: { id: account.id } }
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (!account || account.banned) {
|
||||||
if (!account || account.banned) {
|
return null; // {success: false, isBanned: true}
|
||||||
res ? res.clearCookie('session') : logger.warn(`getAuthenticatedAccount unable to clear banned user (${account.email}) cookie, res not passed`);
|
}
|
||||||
return false
|
return account;
|
||||||
|
} else {
|
||||||
|
return null; // {success: false, isInvalid: true}
|
||||||
}
|
}
|
||||||
return account;
|
|
||||||
} else {
|
} else {
|
||||||
res ? res.clearCookie('session') : logger.warn(`getAuthenticatedAccount unable to clear banned user (${account.email}) cookie, res not passed`);
|
return null; // {success: false, badToken: true}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -75,6 +104,7 @@ module.exports = (_models, _logger) => {
|
||||||
return {
|
return {
|
||||||
validateJWT: validateJWT,
|
validateJWT: validateJWT,
|
||||||
getAuthenticatedAccount: getAuthenticatedAccount,
|
getAuthenticatedAccount: getAuthenticatedAccount,
|
||||||
changePassword: changePassword
|
changePassword: changePassword,
|
||||||
|
signIn: signIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Binary file not shown.
|
@ -24,21 +24,23 @@ let logger;
|
||||||
|
|
||||||
|
|
||||||
router.post('/useradmin/auth', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
router.post('/useradmin/auth', bodyParser.urlencoded({extended: true}), runAsyncWrapper(async (req, res) => {
|
||||||
const account = await models.__db.get('SELECT * FROM accounts WHERE email = ? AND password = ?', req.body.email, crypto.createHash('sha256').update(req.body.password + config.applicationSalt).digest('hex'));
|
const signIn = await controllers.authentication.signIn(req.body.email, req.body.password)
|
||||||
|
|
||||||
if (!account || account.banned) {
|
console.log(signIn)
|
||||||
res.status(200);
|
|
||||||
|
if (signIn.success) {
|
||||||
|
res.cookie('jwt', signIn.jwt, {signed: true});
|
||||||
|
res.redirect('/useradmin/overview');
|
||||||
|
} else {
|
||||||
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid credentials or banned account'));
|
res.redirect('/useradmin?status=' + encodeURIComponent('Invalid credentials or banned account'));
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
res.cookie('session', {account: account.email, expires: Date.now() + 1000 * 3600 * 24 * 365}, {signed: true});
|
|
||||||
res.redirect('/useradmin/overview');
|
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
||||||
router.get('/useradmin/signout', runAsyncWrapper(async (req, res) => {
|
router.get('/useradmin/signout', runAsyncWrapper(async (req, res) => {
|
||||||
res.clearCookie('session');
|
res.clearCookie('session');
|
||||||
res.redirect('/useradmin');
|
res.clearCookie('jwt');
|
||||||
|
res.redirect('/useradmin?status=' + encodeURIComponent('Signed out'));
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
|
||||||
|
@ -124,11 +126,8 @@ router.post('/useradmin/register/token', bodyParser.urlencoded({extended: true})
|
||||||
|
|
||||||
if (result.lastID != undefined) {
|
if (result.lastID != undefined) {
|
||||||
logger.info("USERADMIN REGISTRATION - created new account #" + result.lastID + " with email " + email + "");
|
logger.info("USERADMIN REGISTRATION - created new account #" + result.lastID + " with email " + email + "");
|
||||||
res.cookie('session', {
|
|
||||||
account: email,
|
res.redirect('/useradmin?status=' + encodeURIComponent('Successfully registered'));
|
||||||
expires: Date.now() + 1000 * 3600 * 24 * 365
|
|
||||||
}, {signed: true});
|
|
||||||
res.redirect('/useradmin/overview');
|
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
logger.error("USERADMIN REGISTRATION - account creation failed, resulting account data for email " + email + " is: " + result);
|
logger.error("USERADMIN REGISTRATION - account creation failed, resulting account data for email " + email + " is: " + result);
|
||||||
|
|
Loading…
Reference in New Issue