UNPKG

ya-express-ntlm

Version:
108 lines 5.85 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.authNTLM = void 0; const af_color_1 = require("af-color"); const buffer_1 = require("buffer"); const handle_authenticate_1 = require("./handle-authenticate"); const handle_negotiate_1 = require("./handle-negotiate"); const debug_1 = require("./debug"); const ntlm_parser_1 = require("../ntlm-parser"); const prepare_options_1 = require("../prepare-options"); const constants_1 = require("./lib/constants"); const utils_1 = require("./lib/utils"); /** * Returns data from the Authorization header: NTLM <data> * If they can be parsed, then req.ntlm is filled */ const getNtlmAuthorizationData = (req) => { const [title, data] = req.headers?.authorization?.split(' ') || []; if (title === 'NTLM' && data) { return data; } }; /** * Fills req.ntlm with data from the Authorization header: NTLM <data> * If they can be parsed. */ const fillReqNtlm = (req, data) => { const parsedData = (0, ntlm_parser_1.ntlmParse)(data, { compact: true }); (0, debug_1.debugNtlmAuthFlow)(`Decoded Authorization header: ${debug_1.hvInColor}${JSON.stringify(parsedData, undefined, 2)}`); ['domain', 'username', 'workstation'].forEach((p) => { if (parsedData[p]) { req.ntlm[p] = parsedData[p]; } }); return parsedData; }; const authNTLM = (authNtlmOptions) => { const options = (0, prepare_options_1.prepareOptions)(authNtlmOptions); return async (req, res, next) => { const rsn = { req, res, next, options }; let userData = options.getCachedUserData(rsn); const uri = `${req.protocol}://${req.get('host')}${req.originalUrl}`; const requestedURI = `${constants_1.arrowR} ${req.method}: ${req.protocol}://${req.get('host')}${req.originalUrl}`; const authorizationHeader = req.headers.authorization; const uriA = `${requestedURI} : ${authorizationHeader ? `${debug_1.hnColor}Authorization: ${debug_1.hvInColor}${authorizationHeader || ''}` : `${debug_1.hnColor}No Authorization header`}`; req.ntlm = req.ntlm || { uri }; const mTitle = `============ Start NTLM Authorization. Strategy: '${options.getStrategy(rsn)}' ==================`; // req.ntlm.isAuthenticated must be filled in earlier when determining the presence of a session cookie if (userData.isAuthenticated) { if (!authorizationHeader || (authorizationHeader && req.method !== 'POST')) { const { username, domain } = (0, utils_1.transferExistingProps)({ ...userData, uri }, req.ntlm); (0, debug_1.debugNtlmAuthFlow)(`${requestedURI}\nConnection already authenticated / user: ${username} / domain: ${domain}`); return next(); } (0, debug_1.debugNtlmAuthFlow)(`The connection is authenticated, but the "Authorization" header sent using the POST method was detected`); } (0, debug_1.debugNtlmAuthFlow)(uriA); if (!authorizationHeader) { (0, debug_1.debugNtlmAuthFlow)(mTitle); (0, debug_1.debugNtlmAuthFlow)(`${constants_1.Larrow} Return ${af_color_1.blue}401${af_color_1.reset}: ${debug_1.hnColor}WWW-Authenticate${af_color_1.blue}: ${debug_1.hvOutColor}NTLM`); return res .setHeader('Content-Type', 'text/plain; charset=utf-8') .setHeader('WWW-Authenticate', 'NTLM') .setHeader('Date', (new Date()).toUTCString()) .status(401) .send('401 UNAUTHORIZED'); } // Returns data from the Authorization header: NTLM <data> const ntlmAuthData = getNtlmAuthorizationData(req); if (!ntlmAuthData) { return options.handleHttpError400(res, `Authorization header does not contain NTLM data. URI ${uri}`); } // Fills req.ntlm with data from the Authorization header: NTLM <data>. const { domain, messageType } = fillReqNtlm(req, ntlmAuthData); // Domain names from NTLM messages - we believe if (domain) { (0, debug_1.debugNtlmLdapProxyId)(`↓ ${domain}`); req.ntlm.domain = domain; } const dataBuf = buffer_1.Buffer.from(ntlmAuthData, 'base64'); if (messageType === ntlm_parser_1.NTLMMessageType.UNKNOWN) { return options.handleHttpError400(res, `Incorrect NTLM message Type ${dataBuf.readUInt8(8)}`); } if (messageType === ntlm_parser_1.NTLMMessageType.NEGOTIATE_MESSAGE) { return (0, handle_negotiate_1.handleNegotiate)(rsn, dataBuf).then(() => 0); } if (messageType === ntlm_parser_1.NTLMMessageType.AUTHENTICATE_MESSAGE) { const isNoErrors = await (0, handle_authenticate_1.handleAuthenticate)(rsn, dataBuf); if (!isNoErrors) { return; // In this case the error has already been sent over HTTP } userData = options.getCachedUserData(rsn); if (!userData.isAuthenticated) { return options.handleHttpError403(rsn); } if (debug_1.debugNtlmAuthFlow.enabled) { // eslint-disable-next-line no-console console.log(`\n${af_color_1.bg.lGreen + af_color_1.black}req.ntlm:${af_color_1.bg.def + af_color_1.rs}`, userData, `\n`); } options.handleSuccessAuthentication(rsn); (0, debug_1.debugNtlmAuthFlow)(`${constants_1.Larrow} handle success authorisation (Default ${af_color_1.bold + af_color_1.reset}next${af_color_1.blue}()${af_color_1.boldOff}${af_color_1.reset})`); return; } return options.handleHttpError400(res, 'NTLM: Unexpected Type 2 message (CHALLENGE) in client request'); }; }; exports.authNTLM = authNTLM; //# sourceMappingURL=auth-ntlm.js.map