163 lines
5.1 KiB
JavaScript
163 lines
5.1 KiB
JavaScript
const jwt = require('jsonwebtoken');
|
|
const crypto = require('crypto');
|
|
|
|
const config = require('../config.js');
|
|
const UserModel = require('../users/users.model');
|
|
|
|
//-----Validations------
|
|
|
|
var AuthTool = {};
|
|
|
|
|
|
AuthTool.isValidJWT = (req, res, next) => {
|
|
|
|
if (!req.headers['authorization'])
|
|
return res.status(401).send();
|
|
|
|
try {
|
|
//Validate access token
|
|
let authorization = req.headers['authorization'];
|
|
req.jwt = jwt.verify(authorization, config.jwt_secret);
|
|
|
|
//Validate expiry time
|
|
const nowSeconds = Math.round(Number(new Date()) / 1000);
|
|
const expiration = req.jwt.iat + config.jwt_expiration;
|
|
if(nowSeconds > expiration)
|
|
return res.status(403).send({error: "Expired"});
|
|
|
|
} catch (err) {
|
|
return res.status(403).send({error: "Invalid Token"});
|
|
}
|
|
|
|
return next();
|
|
};
|
|
|
|
AuthTool.isLoginValid = async(req, res, next) => {
|
|
|
|
if (!req.body || !req.body.password)
|
|
return res.status(400).send({error: 'Invalid params'});
|
|
|
|
//Requires EITHER username or email, dont need both
|
|
if (!req.body.email && !req.body.username)
|
|
return res.status(400).send({error: 'Invalid params'});
|
|
|
|
var user = null;
|
|
|
|
if(req.body.email)
|
|
user = await UserModel.getByEmail(req.body.email);
|
|
else if(req.body.username)
|
|
user = await UserModel.getByUsername(req.body.username);
|
|
if(!user)
|
|
return res.status(404).send({error: "Invalid username or password"});
|
|
|
|
let validPass = AuthTool.validatePassword(user, req.body.password);
|
|
if(!validPass)
|
|
return res.status(400).send({error: 'Invalid username or password'});
|
|
|
|
if(user.permission_level <= 0)
|
|
return res.status(403).send({error: "Your account has been disabled, please contact support!"});
|
|
|
|
req.login = {
|
|
userId: user.id,
|
|
username: user.username,
|
|
email: user.email,
|
|
permission_level: user.permission_level,
|
|
validation_level: user.validation_level,
|
|
provider: req.body.email ? 'email' : 'username',
|
|
};
|
|
|
|
return next();
|
|
};
|
|
|
|
AuthTool.isRefreshValid = async(req, res, next) => {
|
|
|
|
if (!req.body || !req.body.refresh_token)
|
|
return res.status(400).send();
|
|
|
|
if (!req.headers['authorization'])
|
|
return res.status(401).send();
|
|
|
|
if (typeof req.body.refresh_token !== "string")
|
|
return res.status(400).send();
|
|
|
|
try {
|
|
//Validate access token
|
|
let authorization = req.headers['authorization'];
|
|
req.jwt = jwt.verify(authorization, config.jwt_secret);
|
|
|
|
//Validate expiry time
|
|
const nowUnixSeconds = Math.round(Number(new Date()) / 1000);
|
|
const expiration = req.jwt.iat + config.jwt_refresh_expiration;
|
|
if(nowUnixSeconds > expiration)
|
|
return res.status(403).send({error: "Token Expired"});
|
|
|
|
//Validate refresh token
|
|
let refresh_token = req.body.refresh_token;
|
|
let hash = crypto.createHmac('sha512', req.jwt.refresh_key).update(req.jwt.userId + config.jwt_secret).digest("base64");
|
|
if (hash !== refresh_token)
|
|
return res.status(403).send({error: 'Invalid refresh token'});
|
|
|
|
//Validate refresh key in DB
|
|
var user = await UserModel.getById(req.jwt.userId);
|
|
if(!user)
|
|
return res.status(404).send({error: "Invalid user"});
|
|
|
|
if(user.refresh_key !== req.jwt.refresh_key)
|
|
return res.status(403).send({error: 'Invalid refresh key'});
|
|
|
|
} catch (err) {
|
|
return res.status(403).send({error: "Invalid Token"});
|
|
}
|
|
|
|
req.login = req.jwt;
|
|
delete req.login.iat; //Delete previous iat to generate a new one
|
|
return next();
|
|
};
|
|
|
|
AuthTool.hashPassword = (password) => {
|
|
let saltNew = crypto.randomBytes(16).toString('base64');
|
|
let hashNew = crypto.createHmac('sha512', saltNew).update(password).digest("base64");
|
|
let newPass = saltNew + "$" + hashNew;
|
|
return newPass;
|
|
}
|
|
|
|
AuthTool.validatePassword = (user, password) =>
|
|
{
|
|
let passwordFields = user.password.split('$');
|
|
let salt = passwordFields[0];
|
|
let hash = crypto.createHmac('sha512', salt).update(password).digest("base64");
|
|
return hash === passwordFields[1];
|
|
}
|
|
|
|
//--- Permisions -----
|
|
|
|
AuthTool.isPermissionLevel = (required_permission) => {
|
|
return (req, res, next) => {
|
|
let user_permission_level = parseInt(req.jwt.permission_level);
|
|
if (user_permission_level >= required_permission) {
|
|
return next();
|
|
} else {
|
|
return res.status(403).send({error: "Permission Denied"});
|
|
}
|
|
};
|
|
};
|
|
|
|
AuthTool.isSameUserOr = (required_permission) => {
|
|
return (req, res, next) => {
|
|
let user_permission_level = parseInt(req.jwt.permission_level);
|
|
let userId = req.params.userId || "";
|
|
let same_user = (req.jwt.userId === userId || req.jwt.username.toLowerCase() === userId.toLowerCase());
|
|
if (userId && same_user) {
|
|
return next();
|
|
} else {
|
|
if (user_permission_level >= required_permission) {
|
|
return next();
|
|
} else {
|
|
return res.status(403).send({error: "Permission Denied"});
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
module.exports = AuthTool;
|