-
Notifications
You must be signed in to change notification settings - Fork 157
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
Better sign_in_with_slack integration #42
Comments
@JustLey, If I understand correctly - which I may not 😄 - it sounds like you are using different omniauth provider 'aliases' (same Slack, but different omniauth provider lable with different scopes) for what is essentially the same Slack account. I went down that road for awhile, thinking I needed different providers for different levels of access. I started keeping multiple 'identity' records for each user and had to sort out which one was the most current, how or when to merge the identities, and what exactly where my user's current access scopes. My app was quickly getting out of control with user/identity management complexity. After digging deeper into the Slack API and the omniauth-slack gem, I started to realize that there is no need to manage separate providers, identities, or sets of scopes for what is really a single user with clearly defined access privileges. The ah-ha moment was after reading a line in Slack's docs that said something to the effect of (paraphrasing here), "Authorize your users in stages, if your app requires different scopes at different points, making multiple passes through the oauth process, each time adding scopes to that users' token. Once a user is "all scoped up", you only need a simple sign-in-with-slack to retrieve the token containing all of their scopes). So I realized that no matter what 'provider' you call, or what scopes you request, the token you get back is always the same token for that user and always has ALL of the scopes ever authorized for that user, forever (or until revoked by the user, admin, or app owner). So I switched to using a single slack provider in omniauth, and now I maintain only a single Identity record for each user, updated each time they log in. This works much better for me, and my app is finally out of the fire-swamps. The caveat to get this working, however, is that I needed the list of authorized scopes returned by each oauth authorization response - and I couldn't find any versions of omniauth-slack that had that information. So I forked the gem and added that feature. I also bridged the perceived divide between "sign in with slack" and "add to slack". In my opinion, the only difference is in the scopes requested and the format of the returned auth_hash. Slack's documentation gives the impression that there is much more of a difference, but the actual API functionality doesn't really have such a divide, in my opinion (ok there are some exceptions, like the scope 'incomming-webhook' which actually creates & returns a new webhook url). So, bottom line: one provider for Slack, and one identity record per user. Authorize your methods/actions/whatever based on real scopes for that user. Use multiple passes through the oauth process, if it suits your app. Ok, wayyy more than I intended to write here. Hopefully it's more helpful than confusing. 😅 |
I get what you're saying. I'm trying to avoid this multiple passes because passing multiple times sequentially in the OAuth process looks terrible from the client's point of view. Also, I have two buttons. The "Add to Slack" ends up passing two times: one for bot/slash commands/whatever, other to sign in the user. The second button is pure sign in (if someone in the team had already installed the application). But in the end, I have only one provider (because obviously my first pass don't need to keep a record yet). Now I'm having another "issue", which is another thing some people tried to fix around here: Add to Slack can't return a users info, though this PR and this one tried to fix it. That forces me to redirect Add to Slack to Sign In with Slack OAuth flow, which is exactly what I was trying not to do because I had some complaints like "why is this asking me twice?" since the user don't know want is happening behind the curtains. Thanks for taking the time to help me :D Edit: forgot to say, I was starting to have the same issue as you with multiple records (although I had only the provider being different, so, two records per user) when I forced the 'sign_in_with_slack' to save as 'slack' in my user's 'provider' column. Edit 2: I didn't meant "client" in the second sentence, I meant "user". Sorry |
I'm still trying to make sense of Slack's different api-flows myself. Even though they have lots of good documentation on each type, I still can't visualize the full difference. It would appear that if you want all three of these
... you will need three passes thru the oauth cycle, as each of those sets of scopes are supposedly incompatible with each other (though I can't find definitive documentation on that). In my own app, I don't use webhooks. I go straight thru the API for all posts, so I only need two passes thru oauth. That's ok with me, as I'll have a "Add to / Sign up / Get started" button for initial setup. Then forever after, for that user, it's just a "Sign in with Slack" button. The max number of oauth passes thru Slack's chooser pages should only be two, for any given user in my app. I have no trouble getting user info during the oauth cycle, long as I'm not requesting the incoming-webhook scope. Incoming-webhook scope would appear to preclude any further user information scopes, at least during that pass thru oauth. I'm also using my own fork of this gem, which should pull any available user info, if at all possible. Give it a run, and see if it helps. I've tried to make it as universally compatible as possible. For example and reference, here is my Identity model, based on the gem's authorization response to a 'incoming-webhook' oauth request. All sensitive data has been xxxxx'd out. Slack added the 'identify' scope automatically. Ultimately, I hope Slack decides to reduce the incompatibilities between different scopes. Otherwise, I'm not sure if there's anything we can do on the ruby side to reduce the complexity of the authorization process. If anyone else has info or opinions, please chime in! 😃
|
Hey @ginjo – sorry to bring up such an old issue, but how do you handle those multiple passes which need different scopes? If I've got Thanks in advance! |
Hi @samst-test , no problem. I'll look into my code and see what I can find. I've been focusing on some other stuff the last few months, but I've been meaning to review my slack project and omniauth-slack fork and compare it with master. I'll post back here, once I've re-loaded my brain 😄 |
Hey @samst-test - Unfortunately, I'm not familiar with Devise, as I use my own authentication management library based on Warden and Omniauth. But here's what I'm doing to handle the multiple-pass complexities of Slack OAUTH in my app. I have two buttons: add-to-slack and sign-in-with-slack. The add-to-slack button uses what I call a 'deep' scope of The sign-in-with-slack button uses what I call a 'shallow' scope of Both scopes use the same omiauth-slack provider definition. The only difference is the In my local database, I keep one identity record for each slack-team-user. I update the record with whatever data comes back from the OAUTH response, regardless of which scope was used. You can see this app-in-progress here. It's a simple translator that forwards Rackspace webhook notifications to a Slack channel. |
I've been reading the issues about how to get both Add to Slack and Sign in with Slack and they've been pretty insightful, but I got a different situation.
My application is a Slack App that keeps a lot of things synced with Slack. Users can both add it to Slack AND sign in to an external web app. When the current workaround is used, you get two registries for the same user, because the provider differs through each button and 'first_or_create' don't find anything in the database already with both provider and uid.
I'm currently forcing my model's 'from_omniauth' method to use 'slack' as a provider when it detects 'sign_in_with slack', but it feels kinda off to force a provider change. Is there any way we can make it better? Or am I missing something?
Thanks for your time and for the great work :D
The text was updated successfully, but these errors were encountered: