Files
dougal-software/lib/www/server/api/middleware/auth/authentify.js
2020-10-23 14:50:35 +02:00

93 lines
2.2 KiB
JavaScript

const dns = require('dns');
const { Netmask } = require('netmask');
const cfg = require('../../../lib/config');
const jwt = require('../../../lib/jwt');
async function authorisedIP (req, res) {
const validIPs = cfg._("global.users.login.ip") || {};
for (const key in validIPs) {
const block = new Netmask(key);
if (block.contains(req.ip)) {
const payload = Object.assign({
ip: req.ip,
autologin: true
}, validIPs[key]);
jwt.issue(payload, req, res);
return true;
}
}
return false;
}
async function authorisedHost (req, res) {
const validHosts = cfg._("global.users.login.host") || {};
for (const key in validHosts) {
try {
const ip = await dns.promises.resolve(key);
if (ip == req.ip) {
const payload = Object.assign({
ip: req.ip,
host: key,
autologin: true
}, validHosts[key]);
jwt.issue(payload, req, res);
return true;
}
} catch (err) {
if (err.code != "ENODATA") {
console.error(err);
}
}
}
return false;
}
async function auth (req, res, next) {
if (res.headersSent) {
// Nothing to do, this request must have been
// handled already by another middleware.
return;
}
// Check for a valid JWT (already decoded by a previous
// middleware).
if (req.user) {
if (!req.user.autologin) {
// If this is not an automatic login, check if the token is in the
// second half of its lifetime. If so, reissue a new one, valid for
// another cfg.jwt.options.expiresIn seconds.
if (req.user.exp) {
const ttl = req.user.exp - Date.now()/1000;
if (ttl < cfg.jwt.options.expiresIn/2) {
const credentials = cfg._("global.users.login.user").find(i => i.name == req.user.name && i.role == req.user.role);
if (credentials) {
// Refresh token
payload = Object.assign({}, credentials);
delete payload.hash;
jwt.issue(Object.assign({}, credentials), req, res);
}
}
}
}
next();
return;
}
// Check if the IP is known to us
if (await authorisedIP(req, res)) {
next();
return;
}
// Check if the hostname is known to us
if (await authorisedHost(req, res)) {
next();
return;
}
next({status: 401, message: "Not authorised"});
}
module.exports = auth;