148 lines
3.7 KiB
JavaScript
148 lines
3.7 KiB
JavaScript
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
|
|
};
|