diff options
Diffstat (limited to 'lib/api/integrations/slack/request.rb')
-rw-r--r-- | lib/api/integrations/slack/request.rb | 51 |
1 files changed, 51 insertions, 0 deletions
diff --git a/lib/api/integrations/slack/request.rb b/lib/api/integrations/slack/request.rb new file mode 100644 index 00000000000..df0109b07aa --- /dev/null +++ b/lib/api/integrations/slack/request.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +module API + class Integrations + module Slack + module Request + VERIFICATION_VERSION = 'v0' + VERIFICATION_TIMESTAMP_HEADER = 'X-Slack-Request-Timestamp' + VERIFICATION_SIGNATURE_HEADER = 'X-Slack-Signature' + VERIFICATION_DELIMITER = ':' + VERIFICATION_HMAC_ALGORITHM = 'sha256' + VERIFICATION_TIMESTAMP_EXPIRY = 1.minute.to_i + + # Verify the request by comparing the given request signature in the header + # with a signature value that we compute according to the steps in: + # https://api.slack.com/authentication/verifying-requests-from-slack. + def self.verify!(request) + return false unless Gitlab::CurrentSettings.slack_app_signing_secret + + timestamp, signature = request.headers.values_at( + VERIFICATION_TIMESTAMP_HEADER, + VERIFICATION_SIGNATURE_HEADER + ) + + return false if timestamp.nil? || signature.nil? + return false if Time.current.to_i - timestamp.to_i >= VERIFICATION_TIMESTAMP_EXPIRY + + request.body.rewind + + basestring = [ + VERIFICATION_VERSION, + timestamp, + request.body.read + ].join(VERIFICATION_DELIMITER) + + hmac_digest = OpenSSL::HMAC.hexdigest( + VERIFICATION_HMAC_ALGORITHM, + Gitlab::CurrentSettings.slack_app_signing_secret, + basestring + ) + + # Signature will look like: 'v0=a2114d57b48eac39b9ad189dd8316235a7b4a8d21a10bd27519666489c69b503' + ActiveSupport::SecurityUtils.secure_compare( + signature, + "#{VERIFICATION_VERSION}=#{hmac_digest}" + ) + end + end + end + end +end |