openhim-core
Version:
The OpenHIM core application that provides logging and routing of http requests
105 lines (90 loc) • 3.6 kB
JavaScript
var User, atna, auditing, auditingExemptPaths, config, crypto, himSourceID, isUndefOrEmpty, logger, os;
User = require('../model/users').User;
crypto = require('crypto');
logger = require('winston');
config = require("../config/config");
config.api = config.get('api');
config.auditing = config.get('auditing');
atna = require('atna-audit');
auditing = require('../auditing');
os = require('os');
himSourceID = config.auditing.auditEvents.auditSourceID;
auditingExemptPaths = [/\/tasks/, /\/events.*/, /\/metrics.*/, /\/mediators\/.*\/heartbeat/, /\/audits/, /\/logs/];
isUndefOrEmpty = function(string) {
return (string == null) || string === '';
};
exports.authenticate = function*(next) {
var audit, auditAuthFailure, authSalt, authTS, authToken, authWindowSeconds, email, from, hash, header, i, len, pathTest, ref, requestDate, to, user;
header = this.request.header;
email = header['auth-username'];
authTS = header['auth-ts'];
authSalt = header['auth-salt'];
authToken = header['auth-token'];
auditAuthFailure = function() {
var audit;
audit = atna.userLoginAudit(atna.OUTCOME_SERIOUS_FAILURE, himSourceID, os.hostname(), email);
audit = atna.wrapInSyslog(audit);
return auditing.sendAuditEvent(audit, function() {
return logger.debug('Processed internal audit');
});
};
if (isUndefOrEmpty(email) || isUndefOrEmpty(authTS) || isUndefOrEmpty(authSalt) || isUndefOrEmpty(authToken)) {
logger.info("API request made by " + email + " from " + this.request.host + " is missing required API authentication headers, denying access");
this.status = 401;
auditAuthFailure();
return;
}
requestDate = new Date(Date.parse(authTS));
authWindowSeconds = (ref = config.api.authWindowSeconds) != null ? ref : 10;
to = new Date();
to.setSeconds(to.getSeconds() + authWindowSeconds);
from = new Date();
from.setSeconds(from.getSeconds() - authWindowSeconds);
if (requestDate < from || requestDate > to) {
logger.info("API request made by " + email + " from " + this.request.host + " has expired, denying access");
this.status = 401;
auditAuthFailure();
return;
}
user = (yield User.findOne({
email: email
}).exec());
this.authenticated = user;
if (!user) {
logger.info("No user exists for " + email + ", denying access to API, request originated from " + this.request.host);
this.status = 401;
auditAuthFailure();
return;
}
hash = crypto.createHash('sha512');
hash.update(user.passwordHash);
hash.update(authSalt);
hash.update(authTS);
if (authToken === hash.digest('hex')) {
if (this.path === '/transactions') {
if (!this.query.filterRepresentation || this.query.filterRepresentation !== 'full') {
(yield next);
return;
}
} else {
for (i = 0, len = auditingExemptPaths.length; i < len; i++) {
pathTest = auditingExemptPaths[i];
if (pathTest.test(this.path)) {
(yield next);
return;
}
}
}
audit = atna.userLoginAudit(atna.OUTCOME_SUCCESS, himSourceID, os.hostname(), email, user.groups.join(','), user.groups.join(','));
audit = atna.wrapInSyslog(audit);
auditing.sendAuditEvent(audit, function() {
return logger.debug('Processed internal audit');
});
return (yield next);
} else {
logger.info("API token did not match expected value, denying access to API, the request was made by " + email + " from " + this.request.host);
this.status = 401;
return auditAuthFailure();
}
};
//# sourceMappingURL=authentication.js.map