const JWT = require('jsonwebtoken'); const KEY = 'Th1s is THE s3cr3t kEy. It secures the t0ken!'; const Token = { create: (payload, expires = '1h', callback) => { JWT.sign(payload, KEY, { expiresIn: expires }, callback); }, verify: (token, callback) => { JWT.verify(token, KEY, callback); } }; function createAnonymousToken (e) { Token.create({ username: null, can: ['view'] }, (err, token) => { if (err) { e.emit('token:create', err, null); } if (token) { e.emit('token:create', null, token); } }); } function createAuthenticatedToken (e, user, expires = '1h', event = 'token:create') { Token.create({ username: user.name, can: user.can }, expires, (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, { username: decoded.username, can: decoded.can }, '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 verifyTokenThen (token, action, callback) { if (action === 'view') { callback(null, { hasPermission: true }); } else { validateToken(null, token, (err, decoded) => { if (err) { callback('Session could not be validated.', null); } if (decoded) { callback(null, { hasPermission: (decoded.valid && (decoded.can.indexOf(action) > -1)) }); } }); } } module.exports = { anonymous: createAnonymousToken, create: createAuthenticatedToken, refresh: refreshToken, validate: validateToken, verifyThen: verifyTokenThen };