"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.verify = exports.isValidSlackRequest = exports.verifySlackRequest = void 0; // Deprecated: this function will be removed in the near future. Use HTTPModuleFunctions instead. const crypto_1 = require("crypto"); const logger_1 = require("@slack/logger"); const tsscmp_1 = __importDefault(require("tsscmp")); const HTTPModuleFunctions_1 = require("./HTTPModuleFunctions"); // ------------------------------ // HTTP module independent methods // ------------------------------ const verifyErrorPrefix = 'Failed to verify authenticity'; /** * Verifies the signature of an incoming request from Slack. * If the request is invalid, this method throws an exception with the error details. */ function verifySlackRequest(options) { var _a; const requestTimestampSec = options.headers['x-slack-request-timestamp']; const signature = options.headers['x-slack-signature']; if (Number.isNaN(requestTimestampSec)) { throw new Error(`${verifyErrorPrefix}: header x-slack-request-timestamp did not have the expected type (${requestTimestampSec})`); } // Calculate time-dependent values const nowMs = (_a = options.nowMilliseconds) !== null && _a !== void 0 ? _a : Date.now(); const requestTimestampMaxDeltaMin = 5; const fiveMinutesAgoSec = Math.floor(nowMs / 1000) - 60 * requestTimestampMaxDeltaMin; // Enforce verification rules // Rule 1: Check staleness if (requestTimestampSec < fiveMinutesAgoSec) { throw new Error(`${verifyErrorPrefix}: x-slack-request-timestamp must differ from system time by no more than ${requestTimestampMaxDeltaMin} minutes or request is stale`); } // Rule 2: Check signature // Separate parts of signature const [signatureVersion, signatureHash] = signature.split('='); // Only handle known versions if (signatureVersion !== 'v0') { throw new Error(`${verifyErrorPrefix}: unknown signature version`); } // Compute our own signature hash const hmac = (0, crypto_1.createHmac)('sha256', options.signingSecret); hmac.update(`${signatureVersion}:${requestTimestampSec}:${options.body}`); const ourSignatureHash = hmac.digest('hex'); if (!signatureHash || !(0, tsscmp_1.default)(signatureHash, ourSignatureHash)) { throw new Error(`${verifyErrorPrefix}: signature mismatch`); } } exports.verifySlackRequest = verifySlackRequest; /** * Verifies the signature of an incoming request from Slack. * If the request is invalid, this method returns false. */ function isValidSlackRequest(options) { try { verifySlackRequest(options); return true; } catch (e) { if (options.logger) { options.logger.debug(`Signature verification error: ${e}`); } } return false; } exports.isValidSlackRequest = isValidSlackRequest; // ------------------------------ // legacy methods (deprecated) // ------------------------------ const consoleLogger = new logger_1.ConsoleLogger(); // Deprecated: this function will be removed in the near future. Use HTTPModuleFunctions instead. async function verify(options, req, res) { consoleLogger.warn('This method is deprecated. Use HTTPModuleFunctions.parseAndVerifyHTTPRequest(options, req, res) instead.'); return HTTPModuleFunctions_1.HTTPModuleFunctions.parseAndVerifyHTTPRequest(options, req, res); } exports.verify = verify; //# sourceMappingURL=verify-request.js.map