kmrshntr / omniauth-slack

omniauth-slack
MIT License
95 stars 156 forks source link

Using multiple scopes with Devise #62

Open samstarling opened 6 years ago

samstarling commented 6 years ago

Hey @kmrshntr: do you have any pointers on using multiple scopes with Devise? I'd like the users for a Slack team to be able to "Sign in using Slack" (identity.basic scope) and then add my bot (bot scope). At the moment, I'm using a manual "Add to Slack" button (as per their documentation) which produces a link like this:

'https://slack.com/oauth/authorize?client_id=1234.5678&scope=bot

However, when it redirects back to my application, I get:

Started GET "/users/auth/slack/callback?code=snip&state=" for 127.0.0.1 at 2018-06-10 13:07:36 +0200
INFO -- omniauth: (slack) Callback phase initiated.
ERROR -- omniauth: (slack) Authentication failure! csrf_detected: OmniAuth::Strategies::OAuth2::CallbackError, csrf_detected | CSRF detected
Processing by Auth::OmniauthCallbacksController#failure as HTML
  Parameters: {"code"=>"snip", "state"=>""}

Two questions:

  1. Do you know why this is being detected as a CSRF? Ideally, an OAuth token would be returned by that call, that I could associate with the Team in my database.
  2. Can I have two config.omniauth :slack definitions in devise.rb, with different names? If so, how can I use those names when I'm generating links? Can I pass parameters to user_slack_omniauth_authorize_path?
mknarciso commented 5 years ago

Hey @samstarling ! Did you managed to solve that?

samstarling commented 5 years ago

Hey @mknarciso – no, sadly I abandoned the project, and didn't get another chance to investigate this. However, if you find a solution, let me know – I'm still interested. Good luck!

mknarciso commented 5 years ago

Hi @samstarling !! Actually i've done a pretty ugly hack that made it work, but for sure is not the right solution...

I think that the CSRF problem is due to hard coding the link, i've got it when I tried here, maybe because we don't have the state variable. If I call it via the devise path it works.

I created both providers in an omniauth.rb file, as in the documentation.

My problem was that I was getting a false response due to authentication error for the sign_in path. The thing is that this error is on omniauth, and not Slack side, and the answer despite showing an error comes with a valid token. So instead of directly using request.env["omniauth.auth"] I've done this:

  def slack_sign_in
    token = request.env["omniauth.auth"]["credentials"]["token"]
    info = get_info(token)
    Rails.logger.info info
    team = Team.find_by(slack_id: info["team"]["id"])
    ...
  end

where

  def get_info(token)
    require 'net/http'
    require 'uri'

    headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
    uri = URI.parse('https://slack.com/api/users.identity')
    params = { :token => token}
    uri.query = URI.encode_www_form( params )

    res = Net::HTTP.post_form(uri, headers)
    JSON.parse(res.body)
  end

Pretty ugly I now, but after 3 days it worked....

Best!

PS: I tried to use @ginjo fork of omniauth-slack gem, but ran into some strange errors with the new method for Slack module.