node-expose-sspi-strict
Version:
Expose the Microsoft Windows SSPI interface in order to do NTLM and Kerberos authentication.
128 lines (127 loc) • 5.22 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
exports.__esModule = true;
exports.ServerContextHandleManager = void 0;
var cookies_1 = require("./cookies");
var debug_1 = __importDefault(require("debug"));
var debug = debug_1["default"]('node-expose-sspi:schManager');
var COOKIE_KEY = 'NEGOTIATE_ID';
var COOKIE_PREFIX_VALUE = 'NEGOTIATE_';
var ServerContextHandleManager = /** @class */ (function () {
function ServerContextHandleManager(delayMax) {
if (delayMax === void 0) { delayMax = 20000; }
this.delayMax = delayMax;
this.queue = [];
this.sessionMap = new Map();
}
ServerContextHandleManager.prototype.initCookie = function (req, res) {
debug('initCookie');
var cookieToken = cookies_1.parseCookies(req)[COOKIE_KEY];
if (!cookieToken) {
cookieToken = COOKIE_PREFIX_VALUE + Math.floor(1e10 * Math.random());
// create a session cookie (without expiration specified)
res.setHeader('Set-Cookie', COOKIE_KEY + '=' + cookieToken);
}
if (!this.sessionMap.has(cookieToken)) {
this.sessionMap.set(cookieToken, {
method: undefined,
serverContextHandle: undefined
});
}
return cookieToken;
};
ServerContextHandleManager.prototype.waitForReleased = function (cookieToken) {
var _this = this;
if (cookieToken) {
return Promise.resolve();
}
debug('waitForReleased: start');
return new Promise(function (resolve, reject) {
debug('waitForReleased: start promise');
// if nobody else is currently authenticating then go now.
var authItem = { resolve: resolve, reject: reject };
var timeout = setTimeout(function () {
_this.tooLate(authItem);
}, _this.delayMax);
if (_this.authItem === undefined) {
debug('waitForReleased: no other authentication ongoing: we can start now.');
_this.authItem = { resolve: resolve, reject: reject, timeout: timeout };
return _this.authItem.resolve();
}
debug('someone is currently authenticating, go in the queue and wait for your turn.');
_this.queue.push({ resolve: resolve, reject: reject, timeout: timeout });
debug('queue length', _this.queue.length);
});
};
ServerContextHandleManager.prototype.set = function (serverContextHandle, cookieToken) {
if (cookieToken) {
var contextInfo = this.sessionMap.get(cookieToken);
contextInfo.serverContextHandle = serverContextHandle;
return;
}
this.serverContextHandle = serverContextHandle;
};
ServerContextHandleManager.prototype.getServerContextHandle = function (cookieToken) {
if (cookieToken) {
var contextInfo = this.sessionMap.get(cookieToken);
return contextInfo.serverContextHandle;
}
return this.serverContextHandle;
};
ServerContextHandleManager.prototype.release = function (cookieToken) {
if (cookieToken) {
this.sessionMap["delete"](cookieToken);
return;
}
if (this.authItem) {
clearTimeout(this.authItem.timeout);
}
this.serverContextHandle = undefined;
this.authItem = undefined;
if (this.queue.length > 0) {
// it means another client B was waiting for authenticating.
// so we start authenticating this client B.
this.authItem = this.queue.shift();
debug('releasing. queue length', this.queue.length);
this.authItem.resolve();
}
};
/**
* Used only when a negotiate connection
* does not go to its final state before timeout.
*
* Note: Do not interfer with cookies.
*
* @param {AuthItem} authItem
* @returns
* @memberof ServerContextHandleManager
*/
ServerContextHandleManager.prototype.tooLate = function (authItem) {
while (this.queue.length > 0) {
var ai = this.queue.shift();
clearTimeout(ai.timeout);
this.authItem.reject();
}
this.authItem = authItem;
this.authItem.resolve();
};
ServerContextHandleManager.prototype.setMethod = function (method, cookieToken) {
if (cookieToken) {
var contextInfo = this.sessionMap.get(cookieToken);
contextInfo.method = method;
return;
}
this.method = method;
};
ServerContextHandleManager.prototype.getMethod = function (cookieToken) {
if (cookieToken) {
var contextInfo = this.sessionMap.get(cookieToken);
return contextInfo.method;
}
return this.method;
};
return ServerContextHandleManager;
}());
exports.ServerContextHandleManager = ServerContextHandleManager;