const JWT = require('jsonwebtoken'); const Roles = require('../models/role'); const KEY = 'Th1s is THE s3cr3t kEy. It secures the t0ken!'; const Token = { create: (payload, callback) => { JWT.sign(payload, KEY, { expiresIn: '1h' }, callback); }, verify: (token, callback) => { JWT.verify(token, KEY, callback); } }; function createAnonymousToken (e) { Token.create({ user: null, permission: 0 }, (err, token) => { if (err) { e.emit('token:create', err, null); } if (token) { e.emit('token:create', null, token); } }); } function createHmac (e, options) { } function createAuthenticatedToken (e, user, event = 'token:create') { Token.create({ user: user.userName, permission: user.permission._id, uid: user.uid }, (err, token) => { if (err) { e.emit(event, err, null); } if (token) { e.emit(event, null, token); } }); } function refreshToken (e, token) { Token.verify(e, token, (err, decoded) => { if (err) { e.emit('token:refresh', err, null); } if (decoded) { createAuthenticatedToken( e, { user: decoded.user, permission: decoded.permission }, 'token:refresh' ); } }); } function validateToken (e, token, callback) { if (token) { token = token.replace(/(bearer|basic)\s/i, ''); Token.verify(token, (err, decoded) => { var result = { valid: !!decoded, data: decoded }; if (e) { if (err || !result.valid) { e.emit('token:validate', (err || result), null); } e.emit('token:validate', null, result); } else if (typeof callback === 'function') { if (err) { callback(err, null); } callback(null, result); } }); } else { if (e) { e.emit('token:validate', 'No session token passed.', null); } else if (typeof callback === 'function') { callback('No session token passed.', null); } } } function verifyTokenAndUserThen (token, minimumPermission, callback) { validateToken(null, token, (err, decoded) => { if (err) { callback(err, null); } if (decoded && decoded.valid && decoded.data.permission >= minimumPermission) { callback(null, decoded); } else { callback('User role does not have permission', null); } }); } function verifyTokenAndRoleThen (token, action, callback, log = false) { if (log) console.log('verifyTokenAndRoleThen', { token: token, action: action }); validateToken(null, token, (err, decoded) => { if (log) console.log('verifyTokenAndRoleThen::validateToken', { err: err, decoded: decoded.data }); if (err) { callback('Session could not be validated.', null); } let [initial, canElevateTo = false] = Array.isArray(action) ? action : [ action ]; if (log) { console.log('Roles.canRole[' + initial + ']', Roles.canRole(null, decoded.data.permission, initial)); console.log('Roles.canRole[' + canElevateTo + ']', Roles.canRole(null, decoded.data.permission, canElevateTo)); } if (decoded && decoded.valid) { Roles.canRole(null, decoded.data.permission, action, (err, result) => { if (err) { callback('There was an error verifying the role permissions.', null); } if (result) { decoded.hasPermission = result.hasPermission; decoded.canElevate = result.canElevate; callback(null, decoded); } }); } }); } module.exports = { anonymous: createAnonymousToken, create: createAuthenticatedToken, refresh: refreshToken, validate: validateToken, verifyRoleThen: verifyTokenAndRoleThen, verifyThen: verifyTokenAndRoleThen };