Sha256: 89f57327b7fad8407028bbe180baa0edbee4e52fe03d6c1097038155ddfd8738

Contents?: true

Size: 1.99 KB

Versions: 4

Compression:

Stored size: 1.99 KB

Contents

# frozen_string_literal: true
module Slack
  module Events
    class Request
      class MissingSigningSecret < StandardError; end
      class TimestampExpired < StandardError; end
      class InvalidSignature < StandardError; end

      attr_reader :http_request,
                  :signing_secret,
                  :signature_expires_in

      def initialize(http_request, options = {})
        @http_request = http_request
        @signing_secret = options[:signing_secret] || Slack::Events.config.signing_secret
        @signature_expires_in =
          options[:signature_expires_in] || Slack::Events.config.signature_expires_in
      end

      # Request timestamp.
      def timestamp
        @timestamp ||= http_request.headers['X-Slack-Request-Timestamp']
      end

      # The signature is created by combining the signing secret with the body of the request
      # Slack is sending using a standard HMAC-SHA256 keyed hash.
      def signature
        @signature ||= http_request.headers['X-Slack-Signature']
      end

      # Signature version.
      def version
        'v0'
      end

      # Request body.
      def body
        @body ||= http_request.body.read
      end

      # Returns true if the signature coming from Slack has expired.
      def expired?
        timestamp.nil? || (Time.now.to_i - timestamp.to_i).abs > signature_expires_in
      end

      # Returns true if the signature coming from Slack is valid.
      def valid?
        raise MissingSigningSecret unless signing_secret

        digest = OpenSSL::Digest::SHA256.new
        signature_basestring = [version, timestamp, body].join(':')
        hex_hash = OpenSSL::HMAC.hexdigest(digest, signing_secret, signature_basestring)
        computed_signature = [version, hex_hash].join('=')
        computed_signature == signature
      end

      # Validates the request signature and its expiration.
      def verify!
        raise TimestampExpired if expired?
        raise InvalidSignature unless valid?

        true
      end
    end
  end
end

Version data entries

4 entries across 4 versions & 1 rubygems

Version Path
slack-ruby-client-0.15.1 lib/slack/events/request.rb
slack-ruby-client-0.15.0 lib/slack/events/request.rb
slack-ruby-client-0.14.6 lib/slack/events/request.rb
slack-ruby-client-0.14.5 lib/slack/events/request.rb