UNPKG

galleon

Version:

A badass SMTP mail server built on Node to make your life simpler.

144 lines (123 loc) 5.82 kB
const moment = require('moment'); const bcrypt = require('bcryptjs'); const jwt = require('jsonwebtoken'); const herb = require('herb'); exports = module.exports = function (urls) { return function authenticator(req, res, next) { // Use a REGEX like code here if ((req.path !== urls.login) || req.path !== urls.logout) { // Basic cookie/token based authentication let token = req.signedCookies.authentication; if ((!token) || (token == '') || (!token.sessionID)) { try { token = jwt.verify(req.headers.token || "", req.envSecret); } catch (error) { token = null; req.getCredentials = function (callback) { callback("NOT AUTHENTICATED") }; } } // :O No cookie! if (!token) { req.getCredentials = function (callback) { callback("NOT AUTHENTICATED") } } else { req.getCredentials = function (callback) { if (!token.sessionID) return res.redirect(urls.login); // /// Do a ton of cool security stuff here // req.database.models.sessions.findOne({ sessionID: token.sessionID }).exec(function (error, session) { if ((!session) || (!session.email)) return callback("Session Not Found"); if (moment(session.stamp.expires).isBefore(moment())) { req.database.models.sessions.destroy({ sessionID: token.sessionID }, function (error) { // Should do better logging here // An invalid sessionID would either // mean a broken secret key or // possibly an error in the token // system. if (error) console.log(error); res.clearCookie('authentication'); callback("Session expired"); }); } else { req.database.models.users.findOne({ email: session.email }).exec(function (error, user) { if ((!user) || (!user.email)) return callback("Email Not Found");; callback(error, { email: user.email, name: user.name }); }); } }); } } /// } req.signIn = function (req, res, callback) { var opened = moment(); var expires = opened.add(7, 'days'); herb.config({ verbose: (req.environment.verbose) ? 4 : 1 }); if (req.environment.verbose) herb.log('Login requested for', req.param('email')); req.database.models.users.findOne({ email: req.param('email') }).exec(function (error, user) { if (error) herb.error(error); if (error) return callback(error); if (!user) return callback('User not found.'); if (!user.id) return callback('Email does not match a record'); bcrypt.compare(req.param('password'), user.password, function (error, result) { if (error) herb.error(error); if (error) return callback(error); if (result) { herb.marker({ color: 'green' }).log('accessGranted to', user.email); req.database.models.sessions.destroy({ email: req.param('email') }, function (error) { // Log any errors here if (error) callback("DATABASE ERROR"); // Create a new session token req.database.models.sessions.create({ email: user.email, access: 'approved', ipAddress: req.ip, stamp: { opened: opened.toISOString(), expires: expires.toISOString() } }, function (error, session) { if (error) return callback(error); const payload = { sessionID: session.sessionID, opened: opened }; const token = jwt.sign(payload, req.envSecret); res.cookie('authentication', payload, { signed: true, httpOnly: true, secure: (req.protocol === 'https') }); return callback(error, token); }); }) } else { herb.marker({ color: 'red' }).log('accessDenied to', user.email); return callback("INCORRECT PASSWORD"); } }); }) } req.signOut = function (req, res, callback) { // If cookie/token does not exist then call it a success const token = req.signedCookies.authentication || jwt.verify(req.headers.token || "", req.envSecret); if (!token) callback(null); req.database.models.sessions.destroy({ sessionID: token.sessionID }, function (error) { // Should do better logging here // An invalid sessionID would either // mean a broken secret key or // possibly an error in the token // system. if (error) console.log(error); res.clearCookie('authentication'); return callback(error); }); } req.changePassword = function (req, res, callback) { req.getCredentials(function (error, credentials) { if (error) res.status(403).json({ error: "Not Authenticated" }); if (req.environment.verbose) herb.log('Password Change requested for', credentials.name + ' <' + credentials.email + '>'); req.database.models.users.findOne({ email: credentials.email }).exec(function (error, user) { if (error) herb.error(error); if (error) return callback(error); if (!user) return callback('User not found.'); if (!user.id) return callback('Email does not match a record'); req.galleon.changePassword(user, req.param('password'), req.param('cpassword'), function (error) { if (!error) if (req.environment.verbose) herb.log('Password Changed for', credentials.name + ' <' + credentials.email + '>'); callback(error); }); }) }); } next(); } }