Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Does slack-ruby-client include a method I can use for verifying Slack event requests? #238

Closed
ndbroadbent opened this issue Nov 18, 2018 · 5 comments

Comments

@ndbroadbent
Copy link

ndbroadbent commented Nov 18, 2018

I've got the Events API working, and Slack is posting events to my server. I'm looking at the Verifying Requests From Slack documentation, and it doesn't mention Ruby under the "SDK support" section. Is that an oversight, or is there still no official way to verify Slack requests if you're using Ruby? I'm happy to follow the step-by-step instructions, but would prefer to use a library. Is there another Ruby gem that implements the same HMAC verification?

Thanks!

@dblock
Copy link
Collaborator

dblock commented Nov 18, 2018

The library doesn't have much for slack events support, but this was discussed in #131. Currently there's no code here that verifies events are coming from slack. Any such code is welcome, please PR!

@alexagranov
Copy link
Contributor

alexagranov commented Nov 18, 2018

As @dblock pointed out, it's probably more appropriate to add a request validation helper in the repo that actually receives requests - slack-ruby-bot or slack-ruby-bot-server - but since you're asking here...

If your registered endpoint is something like /events and you're running a Sinatra server, you could do something like:

# Events API endpoint
post '/events' do
  body = ActiveSupport::JSON.decode(request.body.read)&.deep_symbolize_keys!
  halt 404 unless valid_token?(body[:token])
  ...
end

def valid_token?(token)
  token == Rails.configuration.x.slack.verification_token
end

You may notice that I'm referencing Rails.configuration which is possible by init'ing the Rails app via,

require ::File.expand_path('../config/environment', __FILE__)

from your rackup .ru file. You could also just use basic Sinatra configuration for your verification token - I happen to run slack-bot servers in tandem with a Rails app and wanted to share the same config.

Note that the token will be in params for slash command and action callback endpoints, the events API endpoint is yet another endpoint.

@jmanian
Copy link
Collaborator

jmanian commented Nov 29, 2018

It could actually be useful to have a simple method as part of slack-ruby-client that implements Slack's signature verification procedure. (Slack rolled out request signing a while back; the old token verification system is deprecated.)

Even just a method to take care of the hashing perhaps, so that you could do something like this:

Slack::Events.valid_signature?(signature, timestamp, body, secret)

For reference, my implementation as a controller filter in Rails looks like this

  def verify_signature
    signing_secret = ENV['SLACK_SIGNING_SECRET']
    version_number = 'v0' # always v0 for now
    timestamp = request.headers['X-Slack-Request-Timestamp']
    raw_body = request.body.read # raw body JSON string

    if Time.at(timestamp.to_i) < 5.minutes.ago
      # could be a replay attack
      render nothing: true, status: :bad_request
      return
    end

    sig_basestring = [version_number, timestamp, raw_body].join(':')
    digest = OpenSSL::Digest::SHA256.new
    hex_hash = OpenSSL::HMAC.hexdigest(digest, signing_secret, sig_basestring)
    computed_signature = [version_number, hex_hash].join('=')
    slack_signature = request.headers['X-Slack-Signature']

    if computed_signature != slack_signature
      render nothing: true, status: :unauthorized
    end
  end

Edit: If this gets added, I imagine it should have an option for changing the 5-minute cutoff to any duration, or no cutoff at all. There should also be an option to provide a different version string.

@dblock
Copy link
Collaborator

dblock commented Nov 30, 2018

Again, I would take a PR along these lines.

@dblock
Copy link
Collaborator

dblock commented Jan 19, 2019

Needed this in slack-strava, so took a stab at it in #245.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants