updated database, sessions managed via signed JWT

token.

TODO: sign tokens based user unique token, instead of
global salt key
pull/4/head
AdamSBlack 2021-10-03 17:44:43 +01:00
parent 7590e9b644
commit acf084743d
3 changed files with 58 additions and 29 deletions

View File

@ -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.

View File

@ -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);