const db = require('@config/database') const jwt = require('jsonwebtoken') const cs = require('@helpers/CryptoString') let Auth = {} const tokenSecretKey = process.env.JSON_KEY Auth.createToken = (userId, masterKey, request = null) => { return new Promise((resolve, reject) => { const created = Math.floor(+new Date/1000) const userHash = cs.hash(String(userId)).toString('base64') //Encrypt Master Password and save it to the server const salt = cs.createSmallSalt() const tempPass = cs.createSmallSalt() const encryptedMasterPass = cs.encrypt(tempPass, salt, masterKey) db.promise().query( 'INSERT INTO user_active_session (salt, encrypted_master_password, created, uses, user_hash) VALUES (?,?,?,?,?)', [salt, encryptedMasterPass, created, 1, userHash]) .then((r,f) => { //Required Data for JWT payload const tokenPayload = {userId, tempPass, salt} //Return token const token = jwt.sign(tokenPayload, tokenSecretKey) return resolve(token) }) }) } Auth.decodeToken = (token, request = null) => { return new Promise((resolve, reject) => { let decodedToken = null //Decode Json web token jwt.verify(token, tokenSecretKey, function(err, decoded){ if(err || decoded.tempPass == undefined || decoded.tempPass.length < 5 || decoded.salt == undefined || decoded.salt.length < 5){ return reject('Bad Token') } decodedToken = decoded //Lookup session data in database return db.promise().query('SELECT * FROM user_active_session WHERE salt = ? LIMIT 1', [decodedToken.salt]) }) .then((r,f) => { const row = r[0][0] if(row == undefined || row.length == 0){ return reject(false) } //Decrypt master key from database const masterKey = cs.decrypt(decodedToken.tempPass, decodedToken.salt, row.encrypted_master_password) if(masterKey == null){ return reject (false) } const userData = { userId: decodedToken.userId, masterKey, tokenId: row.id } //Async update DB counts db.promise().query('UPDATE user_active_session SET uses = uses + 1 WHERE salt = ? LIMIT 1', [decodedToken.salt]) return resolve(userData) }) }) } Auth.reissueToken = () => { //If token has more than 200 uses, renew it } Auth.deletAllLoginKeys = (userId) => { const userHash = cs.hash(String(userId)).toString('base64') return db.promise().query('DELETE FROM user_active_session WHERE user_hash = ?', [userHash]) } Auth.test = () => { // return Auth.deletAllLoginKeys(testUserId) const testUserId = 22 const testPass = cs.createSmallSalt() Auth.createToken(testUserId, testPass) .then(token => { console.log('Test: Create JWT -> Pass') return Auth.decodeToken(token) }) .then(userData => { console.log('Test: Decrypted key Match -> ' + (testPass == userData.masterKey)) return Auth.deletAllLoginKeys(testUserId) }) .then(results => { console.log('Test: Remove user Json Web Tokens - Pass') }) //create token with userId and master key // Auth.createToken() //Thirt days ago // const thirtyDays = (Math.floor((+new Date)/1000)) - (86400 * 30) // const created = Math.floor(decoded.date/1000) // if(created < thirtyDays){ // return reject('Token Expired') // } } module.exports = Auth