ginjo-omniauth-slack 2.4.1 → 2.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b3ff842e9cfab56ecf724517abbf5c5b11dcf342
4
- data.tar.gz: eb8b4443126f1544eaf1b73580785a23dcd87512
3
+ metadata.gz: 2b33fbc53d9bc6c29639e03d5900997ac54c0bfc
4
+ data.tar.gz: 5bc99fd04e3c7c328eb36701990dc8362ae7fa90
5
5
  SHA512:
6
- metadata.gz: d99aca16201b6367f87df3989e9c06b928ea7be002faaa9734ae52021a53d9473a238c85afe39a194c18775baefaa455bbdb1c6fe5d7c58c62643164707e9641
7
- data.tar.gz: cebc21d494e97c0a44dacdf428762630e4d2a9f48eb14f09fa38fb7990106d2bb204921276be3f33102d167d0d582cf8f7d43ddb6661270f8d33cb80c89d4850
6
+ metadata.gz: 49175c0e3ce87a46f48a74466043719c3e145310502937a994dc3430d042bd3fd91b94bff2efa17423cd7a4ef0045522ec2c0b014aa1691b514b16b21ae763ff
7
+ data.tar.gz: 90ca2568b8b03fc4a8c0e76271c6a4b0fcc7bf824b61d8e557e644b8944080728553f879c425c406c338653cf5e642feb238e4219dcaccc0a0de00c1363560ab
data/.gitignore CHANGED
@@ -1,3 +1,4 @@
1
+ .DS_Store
1
2
  *.gem
2
3
  *.rbc
3
4
  .bundle
@@ -6,16 +7,16 @@
6
7
  Gemfile.lock
7
8
  InstalledFiles
8
9
  _yardoc
9
- coverage
10
+ coverage/
10
11
  doc/
12
+ rdoc/
13
+ ydoc/
11
14
  lib/bundler/man
12
- pkg
13
- rdoc
15
+ pkg/
14
16
  spec/reports
15
- test/tmp
16
- test/version_tmp
17
17
  tmp
18
18
  .idea/
19
19
  .ruby-version
20
20
  .ruby-gemset
21
21
  .gitchangelog.rc
22
+ empty*
@@ -0,0 +1,33 @@
1
+ # This is a yaml file of rdoc options
2
+ #
3
+ #
4
+ --- !ruby/object:RDoc::Options
5
+ encoding: UTF-8
6
+ static_path: []
7
+ rdoc_include:
8
+ - "."
9
+ - "/OmniAuthSlack"
10
+ charset: UTF-8
11
+ exclude:
12
+ - "vendor/*"
13
+ hyperlink_all: false
14
+ line_numbers: false
15
+ locale:
16
+ locale_dir: locale
17
+ locale_name:
18
+ main_page:
19
+ #markup: rdoc
20
+ markup: markdown
21
+ output_decoration: true
22
+ page_dir:
23
+ show_hash: false
24
+ tab_width: 8
25
+ template_stylesheets: []
26
+ title:
27
+ visibility: :protected
28
+ webcvs:
29
+ #files:
30
+ #- "lib/**/*.rb"
31
+ #- "lib/**/*.erb"
32
+ op_dir: rdoc
33
+
@@ -0,0 +1,14 @@
1
+ # See https://rubydoc.info/gems/yard/YARD/CLI/Yardoc
2
+ # See https://gist.github.com/nesquena/1406718
3
+ # See https://github.com/github/markup
4
+
5
+ --output ydoc
6
+ --plugin tomdoc
7
+ --no-cache
8
+ --exclude vendor\/.*
9
+ --markup-provider=redcarpet
10
+ --markup=markdown
11
+
12
+ lib/**/*.rb
13
+ lib/**/*.erb -
14
+ README.md CHANGELOG.md LICENSE.txt
@@ -1,4 +1,21 @@
1
- ## v2.4.1(2018-09-18)
1
+ ## v2.5.0
2
+
3
+ * Added Slack v2 API support (oauth flow, scopes, tokens).
4
+
5
+ * Removed additional API calls from callback phase.
6
+
7
+ * Removed mapping of specific access-token fields to auth-hash `info` section.
8
+
9
+ * Implemented deep-trace logging, activated with `ENV['OMNIAUTH_SLACK_DEBUG']=true`
10
+
11
+ * Improved `AccessToken#has_scope?` functionality.
12
+
13
+ * Added optional `OmniAuth::Slack::VerifySlackSignature` middleware (experimental).
14
+
15
+ * Numerous code improvements and debugging.
16
+
17
+
18
+ ## v2.4.1 (2018-09-18)
2
19
 
3
20
  * Set `client_options[:auth_scheme]` to `:basic_auth`, as OAuth2 gem does not yet make this the default. [wbr]
4
21
 
data/Gemfile CHANGED
@@ -1,4 +1,8 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in omniauth-slack.gemspec
3
+ # The gem's dependencies are specified in omniauth-slack.gemspec
4
4
  gemspec
5
+
6
+ # Some installations may need oauth2 gem v1.4.4+ to operate
7
+ # correctly with Slack v2 user tokens.
8
+ #gem 'oauth2', '>= 1.4.4'
data/README.md CHANGED
@@ -1,179 +1,201 @@
1
- ⚠ **_WARNING_**: You are viewing the README of the ginjo fork of omniauth-slack.
1
+ ⚠ **NOTICE**: You are viewing the README of **ginjo** fork of the **omniauth-slack** gem.
2
+ This document may refer to features not yet released. Conversely (inversely?) this branch may contain features and changes not yet documented.
2
3
 
3
- To view the original omniauth-slack from [@kmrshntr](https://github.com/kmrshntr), go [here](https://github.com/kmrshntr/omniauth-slack).
4
4
 
5
- # OmniAuth::Slack
5
+ # OmniAuth Slack, a Ruby Gem
6
6
 
7
- This Gem contains the Slack strategy for OmniAuth and supports most features of
8
- the [Slack OAuth2 authorization API](https://api.slack.com/docs/oauth), including both the
9
- [Sign in with Slack](https://api.slack.com/docs/sign-in-with-slack) and
10
- [Add to Slack](https://api.slack.com/docs/slack-button) approval flows.
7
+ The omniauth-slack gem contains the Slack OAuth2 strategy for [OmniAuth](https://github.com/omniauth/omniauth) and supports
8
+ the Slack [OAuth2 v2 API](https://api.slack.com/authentication/oauth-v2)
9
+ and the Slack OAuth2 v1 API.
11
10
 
12
- This Gem supports Slack "classic" apps and tokens as well as the developer preview of [Workspace apps and tokens](https://api.slack.com/workspace-apps-preview).
11
+ This Gem supports Slack v2 API bot and user tokens, as well as v1 API workspace apps and tokens.
12
+ Slack "classic" apps and tokens should also work but are not fully tested.
13
+
14
+ Omniauth-slack does not enforce a Ruby version constraint. The Gem will work with Ruby versions 2.3 through 2.6.x. Older versions of Ruby may work but are not tested. Ruby version 2.7.x may work but is not yet tested.
13
15
 
14
16
 
15
17
  ## Before You Begin
16
18
 
17
- You should have already installed OmniAuth into your app; if not, read the [OmniAuth README](https://github.com/intridea/omniauth) to get started.
19
+ OmniAuth Slack is implemented through the OmniAuth gem, so you should familiarize yourself with the basics of [OmniAuth](https://github.com/intridea/omniauth).
20
+
21
+ OmniAuth Slack authorizes Slack users on behalf of a defined Slack application. If you don't already have an application defined on Slack, sign into the [Slack application dashboard](https://api.slack.com/applications) and create an application. Take note of your API keys.
18
22
 
19
- Now sign into the [Slack application dashboard](https://api.slack.com/applications) and create an application. Take note of your API keys.
23
+ While you're in the application settings, add a Redirect URL to your application (under the `OAuth2 & Permissions` section), something simple like `http://localhost:3000/` or `https://myslackapp.com/`. The URL doesn't have to be accessible to the public internet, but it should be accessible to your development machine.
20
24
 
21
25
 
22
26
  ## Using This Strategy
23
27
 
24
28
  First start by adding this gem to your Gemfile:
25
29
 
26
- ```ruby
27
- gem 'ginjo-omniauth-slack'
28
- ```
30
+ ```ruby
31
+ gem 'ginjo-omniauth-slack', require:'omniauth-slack'
32
+ ```
33
+
34
+ Or specify the latest HEAD (development) version from the ginjo repository:
29
35
 
30
- Or specify the latest HEAD version from the ginjo repository:
36
+ ```ruby
37
+ gem 'ginjo-omniauth-slack', require:'omniauth-slack', git: 'https://github.com/ginjo/omniauth-slack'
38
+ ```
31
39
 
32
- ```ruby
33
- gem 'ginjo-omniauth-slack', git: 'https://github.com/ginjo/omniauth-slack'
34
- ```
40
+ Next, tell OmniAuth about this provider.
35
41
 
36
- Next, tell OmniAuth about this provider. For a Rails app, your `config/initializers/omniauth.rb` file should look like this:
42
+ For a **[Rails](https://rubyonrails.org)** app, your `config/initializers/omniauth.rb` file should look like this:
37
43
 
38
- ```ruby
39
- Rails.application.config.middleware.use OmniAuth::Builder do
40
- provider :slack, 'API_KEY', 'API_SECRET', scope: 'string-of-scopes'
41
- end
42
- ```
44
+ ```ruby
45
+ Rails.application.config.middleware.use OmniAuth::Builder do
46
+ provider :slack, 'API_KEY', 'API_SECRET', scope: 'string-of-scopes'
47
+ end
48
+ ```
43
49
 
44
- Replace `'API_KEY'` and `'API_SECRET'` with the appropriate values you obtained [earlier](https://api.slack.com/applications).
45
- Replace `'string-of-scopes'` with a comma (or space) separated string of Slack API scopes.
50
+ Replace `'API_KEY'` and `'API_SECRET'` with the relevant values you obtained from the Slack application setup. Replace `'string-of-scopes'` with a space-separated string of Slack API scopes.
46
51
 
47
52
 
48
- For a [Sinatra](http://sinatrarb.com/) app:
53
+ For a **[Sinatra](http://sinatrarb.com/)** app: <span name="sinatra-app" id="sinatra-app"></span>
49
54
 
50
- ```ruby
51
- require 'sinatra'
52
- require 'omniauth-slack'
55
+ ```ruby
56
+ require 'sinatra'
57
+ require 'omniauth-slack'
53
58
 
54
- use OmniAuth::Builder do |env|
55
- provider :slack,
56
- ENV['SLACK_OAUTH_KEY_WS'],
57
- ENV['SLACK_OAUTH_SECRET_WS'],
58
- scope: 'string-of-scopes'
59
- end
60
- ```
59
+ use OmniAuth::Builder do |env|
60
+ provider :slack,
61
+ ENV['SLACK_OAUTH_KEY_WS'],
62
+ ENV['SLACK_OAUTH_SECRET_WS'],
63
+ scope: 'string-of-scopes'
64
+ end
65
+ ```
61
66
 
62
67
 
63
- If you are using [Devise](https://github.com/plataformatec/devise) then it will look like this:
68
+ If you are using **[Devise](https://github.com/plataformatec/devise)** then it *should* look like this:
64
69
 
65
- ```ruby
66
- Devise.setup do |config|
67
- # other stuff...
70
+ ```ruby
71
+ Devise.setup do |config|
72
+ # other stuff...
68
73
 
69
- config.omniauth :slack, ENV['SLACK_APP_ID'], ENV['SLACK_APP_SECRET'], scope: 'string-of-scopes'
74
+ config.omniauth :slack, ENV['SLACK_APP_ID'], ENV['SLACK_APP_SECRET'], scope: 'string-of-scopes'
70
75
 
71
- # other stuff...
72
- end
73
- ```
76
+ # other stuff...
77
+ end
78
+ ```
74
79
 
75
80
 
76
81
  To manually install and require the gem:
77
- ```bash
78
- # shell
79
- gem install ginjo-omniauth-slack
80
- ````
81
82
 
82
- ```ruby
83
- # ruby
84
- require 'omniauth-slack'
85
- ```
83
+ ```bash
84
+ # shell
85
+ gem install ginjo-omniauth-slack
86
+ ```
87
+
88
+ ```ruby
89
+ # ruby
90
+ require 'omniauth-slack'
91
+ ```
86
92
 
87
93
 
88
94
  ## Scopes
89
- Slack lets you choose from a [few different scopes](https://api.slack.com/docs/oauth-scopes#scopes).
90
- *Here's another [table of Slack scopes](https://api.slack.com/scopes) showing classic and new app compatibility.*
95
+ Slack lets you choose from a number of [scopes](https://api.slack.com/scopes) supporting one or more of the **classic**, **workspace**, and **v2** apps and token types.
91
96
 
92
- **Important:** You cannot request both `identity` scopes and regular scopes in a single authorization request.
97
+ **Important:** You cannot request both identity scopes and non-identity scopes in a single authorization request, within the same scope field (`scope` or `user_scope`).
93
98
 
94
- If you need to combine "Add to Slack" scopes with those used for "Sign in with Slack", you should configure two providers:
99
+ If you need to combine *Add to Slack* scopes with those used for *Sign in with Slack*,
100
+ you may want to configure two providers:
95
101
 
96
- ```ruby
97
- provider :slack, 'API_KEY', 'API_SECRET', scope: 'identity.basic', name: :sign_in_with_slack
98
- provider :slack, 'API_KEY', 'API_SECRET', scope: 'team:read,users:read,identify,bot'
99
- ```
102
+ ```ruby
103
+ provider :slack, 'API_KEY', 'API_SECRET', name: :sign_in_with_slack, scope: 'identity.basic'
104
+ provider :slack, 'API_KEY', 'API_SECRET', scope: 'team:read,users:read,identify,bot'
105
+ ```
100
106
 
101
107
  Use the first provider to sign users in and the second to add the application, and deeper capabilities, to their team.
102
108
 
103
- Sign-in-with-Slack handles quick authorization of users with minimally scoped requests.
104
- Deeper scope authorizations are acquired with further passes through the Add-to-Slack authorization process.
109
+ The [Sign-in-with-Slack](https://api.slack.com/docs/sign-in-with-slack) approval flow handles quick authorization of users with minimally scoped requests. Deeper scope authorizations are acquired with further passes through the authorization cycle.
110
+
111
+ This works because Slack scopes are additive: Once you successfully authorize a scope, the token will possess that scope forever, regardless of what flow or scopes are requested at future authorizations (removal of scope requires revocation of the token or uninstallation of the Slack app from the team).
112
+
105
113
 
106
- This works because Slack scopes are additive: Once you successfully authorize a scope, the token will possess that scope forever, regardless of what flow or scopes are requested at future authorizations.
114
+ ## v2 API scope fields
107
115
 
108
- Removal of scope requires revocation of the token.
116
+ The Slack v2 API allows two different scope fields in the authorization request.
109
117
 
118
+ * Scopes passed in the `scope` field are requesting a bot token.
119
+ * Scopes passed in the `user_scope` field are requesting a user token.
110
120
 
111
- ## Authentication Options
121
+ There must be at least one scope listed in either of the fields
122
+ for most (but not all) v2 API requests.
112
123
 
113
- Authentication options are specified in the provider block, as shown above, and all are optional except for `:scope`.
114
- You will need to specify at least one scope to get a successful authentication and authorization.
124
+ The rule mentioned [above](#scopes), "... don't mix identity scopes with other scopes..," applies to v2 API requests as well, however only for the `user_scope` field. The `scope` field in the v2 API does not accept identity scopes.
115
125
 
116
- Some of these options can also be given at runtime in the authorization request url.
117
126
 
118
- `scope`, `team`, `team_domain`, and `redirect_uri` can be given at runtime. `scope`, `team`, and `redirect_uri` will be passed directly through to Slack in the OAuth GET request:
127
+ <!-- *TODO: fix or build this.*
128
+ See *Advanced Techniques* for alternatives to handle multiple sets of scopes and progressive permissions.
129
+ -->
119
130
 
120
- ```ruby
121
- https://slack.com/oauth/authorize?scope=identity.basic,identity.email&team=team-id&redirect_uri=https://different.subdomain/different/callback/path
122
- ```
131
+ ## Options
123
132
 
124
- `team_domain` will be inserted into the GET request as a subdomain `https://team-domain.slack.com/oauth/authorize`.
133
+ Options for omniauth-slack are specified in the provider block, as shown [above](#user-content-sinatra-app),
134
+ and all are optional except for `scope` and/or `user_scope`.
135
+
136
+
137
+ Some of these options can also be given at runtime in the authorization request url
138
+ (see [**pass\_through\_params**](#pass_through_params) below).
125
139
 
126
140
  More information on provider and authentication options can be found in omniauth-slack's supporting gems [omniauth](https://github.com/omniauth/omniauth), [oauth2](https://github.com/oauth-xx/oauth2), and [omniauth-oauth2](https://github.com/omniauth/omniauth-oauth2).
127
141
 
128
142
 
129
- ### Scope
143
+ ### :scope *and/or* :user_scope => space-delimited-string-of-scopes
130
144
  *required*
131
145
 
132
- ```ruby
133
- :scope => 'string-of-comma-or-space-separated-scopes'
134
- ```
146
+ ```ruby
147
+ :scope => 'string-of-space-separated-scopes'
148
+
149
+ # and/or (v2 API only)
150
+ :user_scope => '...'
151
+ ```
152
+
153
+ Specify the scopes for the authorization request.
135
154
 
136
- Specify the scopes you would like to add to the token during this authorization request.
137
155
 
138
-
139
- ### Team
156
+ ### team: string
157
+ *optional*
158
+
159
+ ### team_domain: string
140
160
  *optional*
141
161
 
142
- ```ruby
143
- :team => 'team-id'
144
- # and/or
145
- :team_domain => 'team-subdomain'
146
- ```
162
+ ```ruby
163
+ :team => 'team-id',
164
+
165
+ # and/or
166
+
167
+ :team_domain => 'my_team_domain'
168
+ ```
169
+ Requests authentication against a specific team.
170
+
147
171
 
148
172
  > If you don't pass a team param, the user will be allowed to choose which team they are authenticating against. Passing this param ensures the user will auth against an account on that particular team.
149
173
 
150
- If you need to ensure that the users use the team whose team_id is 'XXXXXXXX', you can do so by passing `:team` option in your `config/initializers/omniauth.rb` like this:
174
+ If you need to ensure that the users are authenticating against a specific team_id, you can pass the `:team` option in your provider block:
151
175
 
152
- ```ruby
153
- Rails.application.config.middleware.use OmniAuth::Builder do
154
- provider :slack, 'API_KEY', 'API_SECRET', scope: 'identify,read,post', team: 'XXXXXXXX'
155
- end
156
- ```
176
+ ```ruby
177
+ provider :slack, 'API_KEY', 'API_SECRET', scope: 'identify,read,post', team: 'XXXXXXXX'
178
+ ```
157
179
 
158
- If your user is not already signed in to the Slack team that you specify, they will be asked to provide the team domain first.
180
+ If the user is not already signed in to the Slack team specified, they will be given an option to select a team first.
159
181
 
160
182
  Another (possibly undocumented) way to specify team is by passing in the `:team_domain` parameter.
161
183
  In contrast to setting `:team`, setting `:team_domain` will force authentication against the specified team (credentials permitting of course), even if the user is not signed in to that team.
162
- However, if you are already signed in to that team, specifying the `:team_domain` alone will not let you skip the Slack authorization dialog, as is possible when you specify `:team`.
184
+ However, if the user is already signed in to that team, specifying the `:team_domain` alone will not let the user skip the Slack authorization dialog, as is possible when you specify `:team`.
163
185
 
164
- Sign in behavior with team settings and signed in state can be confusing. Here is a breakdown based on Slack documentation and observations while using this gem.
186
+ Sign in behavior with team settings and signed in state can be confusing. Here is a breakdown based on Slack documentation and observations while using omniauth-slack.
165
187
 
166
188
 
167
- #### Team settings and sign in state vs Slack OAuth behavior.
189
+ #### Team settings and sign in state vs Slack OAuth2 behavior.
168
190
 
169
191
  | Setting and state | Will authenticate against specific team | Will skip authorization approval<br>-<br>*The elusive unobtrusive<br>[Sign in with Slack](https://api.slack.com/docs/sign-in-with-slack)* |
170
192
  | --- | :---: | :---: |
171
- | using `:team`, already signed in | :heavy_check_mark: | :heavy_check_mark: |
172
- | using `:team`, not signed in | | :heavy_check_mark: |
173
- | using `:team_domain`, already signed in | :heavy_check_mark: | |
174
- | using `:team_domain`, not signed in | :heavy_check_mark: | |
175
- | using `:team` and `:team_domain`, already signed in | :heavy_check_mark: | :heavy_check_mark: |
176
- | using `:team` and `:team_domain`, not signed in | | :heavy_check_mark: |
193
+ | using `:team`, already signed in | :small_blue_diamond: | :small_blue_diamond: |
194
+ | using `:team`, not signed in | | :small_blue_diamond: |
195
+ | using `:team_domain`, already signed in | :small_blue_diamond: | |
196
+ | using `:team_domain`, not signed in | :small_blue_diamond: | |
197
+ | using `:team` and `:team_domain`, already signed in | :small_blue_diamond: | :small_blue_diamond: |
198
+ | using `:team` and `:team_domain`, not signed in | | :small_blue_diamond: |
177
199
  | using no team parameters | | |
178
200
 
179
201
  *Slack's authorization process will only skip the authorization approval step, if in addition to the above settings and state, ALL of the following conditions are met:*
@@ -184,128 +206,434 @@ Sign in behavior with team settings and signed in state can be confusing. Here i
184
206
  * Current authorization is not requesting any non-identity scopes (but it's ok if the token already has non-identity scopes).
185
207
 
186
208
 
187
- ### Redirect URI
188
- *optional*
209
+ ### redirect_uri: string
210
+ String *optional*
189
211
 
190
- ```ruby
191
- :redirect_uri => 'https://<defaults-to-the-app-origin-host-and-port>/auth/slack/callback'
192
- ```
212
+ ```ruby
213
+ :redirect_uri => 'https://<defaults-to-the-app-origin-host-and-port>/auth/slack/callback'
214
+ ```
193
215
 
194
216
  *This setting overrides the `:callback_path` setting.*
195
217
 
196
218
  Set a custom redirect URI in your app, where Slack will redirect-to with an authorization code.
197
219
  The redirect URI, whether default or custom, MUST match a registered redirect URI in [your app settings on api.slack.com](https://api.slack.com/apps).
198
- See the [Slack OAuth docs](https://api.slack.com/docs/oauth) for more details on Redirect URI registration and matching rules.
199
220
 
200
221
 
201
- ### Callback Path
222
+ ### callback_path: string
202
223
  *optional*
203
224
 
204
- ```ruby
205
- :callback_path => '/auth/slack/callback'
206
- ```
225
+ ```ruby
226
+ :callback_path => '/auth/slack/callback'
227
+ ```
207
228
 
208
229
  *This setting is ignored if `:redirect_uri` is set.*
209
230
 
210
231
  Set a custom callback path (path only, not the full URI) for Slack to redirect-to with an authorization code. This will be appended to the default redirect URI only. If you wish to specify a custom redirect URI with a custom callback path, just include both in the `:redirect_uri` setting.
211
232
 
212
233
 
213
- ### Skip Info
234
+ ### skip_info: boolean
214
235
  *optional*
215
236
 
216
- ```ruby
217
- :skip_info => false
218
- ```
237
+ ```ruby
238
+ :skip_info => false
239
+ ```
219
240
 
220
241
  Skip building the `InfoHash` section of the `AuthHash` object.
221
242
 
222
243
  If set, only a single api request will be made for each authorization. The response of that authorization request may or may not contain user and email data.
223
244
 
224
245
 
225
- ### Include/Exclude Data
246
+ ### pass_through_params: array-of-strings
226
247
  *optional*
227
248
 
228
- ```ruby
229
- :include_data => %w(identity user_info user_profile)
230
-
231
- # or
232
-
233
- :exclude_data => %w(user_info team_info bot_info)
234
- ```
235
- *These options are ignored if `:skip_info => true` is set.*
249
+ Options for `scope`, `team`, `team_domain`, and `redirect_uri` can also be given at runtime via the query string of the omniauth-slack authorization endpoint URL `/auth/slack?team=...`. The `scope`, `team`, and `redirect_uri` query parameters will be passed directly through to Slack in the OAuth2 GET request:
250
+
251
+ ```ruby
252
+ https://slack.com/oauth/authorize?scope=identity.basic,identity.email&team=team-id&redirect_uri=https://different.subdomain/different/callback/path
253
+ ```
236
254
 
237
- Specify which API calls to include or exclude after the initial authorization call.
238
- This will affect what data you see in the AuthHash object. These two options are mutually exclusive. Use one or the other but not both. If neither option is declared, all API calls will be made (depending on scope and permissions).
255
+ The `team_domain` query parameter will be inserted into the authorization GET request
256
+ as a subdomain `https://team-domain.slack.com/oauth/authorize`.
239
257
 
240
- The currently available calls are:
258
+ **NOTE:** Allowing `redirect_uri`, `scope`, or `team_domian` to be passed to Slack from your application's public interface (`https://myapp.com/auth/slack?scope=...`) is a potential security risk. As of omniauth-slack version 2.5.0, the default is to NOT allow `scope`, `redirect_uri`, or `team_domain` pass-through options at runtime, *unless* they are listed in the `:pass_through_params` option. The `team` param is allowed to pass through as a default.
241
259
 
242
- * identity
243
- * user_info
244
- * user_profile
245
- * team_info
246
- * bot_info
260
+ To block all pass-through options.
247
261
 
262
+ ```ruby
263
+ provider :slack, KEY, SECRET, pass_through_params:nil
264
+ ```
265
+
266
+ To allow all pass-through options.
248
267
 
249
- ### Preload Data with Threads
268
+ ```ruby
269
+ provider :slack, KEY, SECRET, pass_through_params: %w(team scope redirect_uri team_domain)
270
+ ```
271
+
272
+
273
+ ### client_options: hash-of-client-options
250
274
  *optional*
251
275
 
252
- ```ruby
253
- :preload_data_with_threads => 0
254
- ```
255
- *This option is ignored if `:skip_info => true` is set.*
276
+ Client options control the behavior of the `OAuth2::Client`, which handles the
277
+ http requests and redirects during the OmniAuth OAuth2 cycle.
278
+ Here is the current default `client_options`.
279
+
280
+ ```ruby
281
+ option :client_options, {
282
+ site: 'https://slack.com',
283
+ authorize_url: '/oauth/v2/authorize',
284
+ token_url: '/api/oauth.v2.access',
285
+ auth_scheme: :basic_auth,
286
+ raise_errors: false, # MUST be false to allow Slack's get-token response from v2 API.
287
+ history: Array.new,
288
+ }
289
+ ```
290
+
291
+ Generally, you can leave this option alone, but there is one case where you need it:
292
+ If you want to use **Slack's v1 (legacy, classic, whatever) API**, you need to change
293
+ the authorization and token endpoints.
294
+
295
+ To switch to **Slack v1 API**, change to these options within `client_options`:
296
+
297
+ authorize_url: '/oauth/authorize',
298
+ token_url: '/api/oauth.access',
256
299
 
257
- With passed integer > 0, omniauth-slack preloads the basic identity-and-info API call responses, from Slack, using *<#integer>* pooled threads.
258
300
 
259
- The default `0` skips this feature and only loads those API calls if required, scoped, and authorized, to build the AuthHash.
301
+ ## Slack v2 API
302
+ Slack is recommending the [v2 API](https://api.slack.com/authentication/oauth-v2)
303
+ for all new Slack apps.
304
+ This gem supports Slack's v2 API and its associated tokens and apps.
305
+ The v2 API endpoints are now the default in omniauth-slack.
260
306
 
261
- ```ruby
262
- provider :slack, key, secret, :preload_data_with_threads => 2
263
- ```
307
+ The omniauth-slack gem does not put a version constraint on the OAuth2 gem, so as to
308
+ remain compatible with installations using earlier versions of OAuth2
309
+ (and not needing Slack's v2 API). However, use of omniauth-slack with Slack's new API
310
+ requires a minimum version of the OAuth2 gem.
264
311
 
265
- More threads can potentially give a quicker callback phase.
266
- The caveat is an increase in concurrent request load on Slack, possibly affecting rate limits.
312
+ #### Using omniauth-slack with Slack's v2 API requires OAuth2 gem version 1.4.4+
267
313
 
314
+ Make sure your application is loading the OAuth2 gem version 1.4.4+.
315
+ In most cases, Bundler and the gem dependency tree will sort this out for you.
316
+ But some gems or gem combinations may install an older OAuth2 gem. If so,
317
+ try something like this in your Gemfile:
268
318
 
269
- ### Additional Data
270
- *experimental*
319
+ ```ruby
320
+ gem 'oauth2', '~> 1.4.4'
321
+
322
+ # or
323
+
324
+ gem 'oauth2', '>= 1.4.4'
325
+ ```
271
326
 
272
- This experimental feature allows additional API calls to be made during the omniauth-slack callback phase.
273
- Provide a hash of `{<name>: <proc-that-receives-env>}`, and the result will be attached as a hash
274
- under `additional_data` in the `extra` section of the `AuthHash`.
327
+ #### The reason behind this
328
+ Tokens returned from the v2 API may not always conform to the OAuth2 spec,
329
+ and therefore may raise errors in the OAuth2 gem during the callback phase,
330
+ even if the token response from Slack's v2 API is successful from Slack's point of view.
275
331
 
276
- ```ruby
277
- provider :slack, key, secret,
278
- additional_data: {
279
- channels: proc{|env| env['omniauth.strategy'].access_token.get('/api/conversations.list').parsed['channels'] },
280
- resources: proc{|env| env['omniauth.strategy'].access_token.get('/api/apps.permissions.resources.list').parsed }
281
- }
282
- ```
332
+ To avoid this issue, the omniauth-slack strategy `client_options` must be set
333
+ with `{raise_errors: false}`, which will only have the desired effect
334
+ on the OAuth2 gem version 1.4.4 and above.
335
+ This `raise_errors` option is now the default in the omniauth-slack gem.
283
336
 
284
337
 
285
- ## Workspace Apps and Tokens
286
- This gem provides support for Slack's developer preview of [Workspace apps](https://api.slack.com/workspace-apps-preview). There are some important differences between Slack's classic apps and the new Workspace apps. The main points to be aware of when using omniauth-slack with Workspace Apps are:
338
+ ## Access Tokens
287
339
 
288
- * Workspace app tokens are issued as a single token per team. There are no user or bot tokens. All Workspace app API calls are made with the Workspace token. Calls that act on behalf of a user or bot are made with the same token.
340
+ While the core OAuth2 access-token is a simple string, the OAuth2 gem packages it along with other data returned from the `/api/oauth.access` call, as an AccessToken instance. The AccessToken contains everything you need to make Slack API requests: the actual token string, the expiration data (if any), the team, user, scope, and an OAuth2::Client instance with the API key and secret.
289
341
 
290
- * The available api calls and the scopes required to access them are different in Workspace apps. See Slack's docs on [Scopes](https://api.slack.com/scopes) and [Methods](https://api.slack.com/methods/workspace-tokens) for more details.
342
+ The AccessToken generated by omniauth-slack also has additional features, such as `has_scope?(list-of-scopes)`, which queries the token's awarded scopes. This is handy for Slack Workspace apps and their multi-dimensional scopes, but it works for any Slack token type.
291
343
 
292
- * The OmniAuth::AuthHash.credentials.scope object, returned from a successful authentication, is a hash with each value containing an array of scopes. See below for an example.
344
+ #### Storage
345
+ Use the `AccessToken#to_hash` method to prepare the token for serialization and storage in a database. This method strips off all unnecessary objects and leaves just the data.
293
346
 
347
+ #### Retrieval
348
+ When you want to reconstitute the access-token from a stored hash or string, use the `OmniAuth::Slack::OAuth2::AccessToken.from_hash` method. Or use omniauth-slack's convenience method:
294
349
 
295
- ## Auth Hash
350
+ `access_token = OmniAuth::Slack.build_access_token(key, secret, access_token_string_or_hash)`
296
351
 
297
- The AuthHash from this gem has the standard components of an `OmniAuth::AuthHash` object, with some additional data added to the `:info` and `:extra` sections.
352
+ #### Usage
298
353
 
299
- If the scopes allow, additional api calls *may* be made to gather additional user and team info, unless the `:skip_info => true` is set.
354
+ Once you have a valid AccessToken instance, you can do things like:
300
355
 
301
- The `:extra` section contains the parsed data from each of the api calls made during the authorization.
302
- Also included is a `:raw_info` hash, which in turn contains the raw response object from each of the api calls.
356
+ ```ruby
357
+ access_token.get('/api/apps.permissions.users.list')
303
358
 
304
- The `:extra` section also contains `:scopes_requested`, which are the scopes requested during the current authorization.
359
+ access_token.refresh
305
360
 
306
- See [this gist for an example AuthHash](https://gist.github.com/ginjo/3105cf4e975996c9032bb4725f949cd2) from a workspace token with a mix of identity scopes and regular app scopes applied.
361
+ access_token.post('/api/chat.postMessage', params: {channel: channel_id, text: message})
362
+ ```
363
+
364
+ To extract data from the API response, call `parsed` on the response object.
365
+
366
+ ```ruby
367
+ access_token.get('/api/channels.list').parsed['channels']
368
+
369
+ # => [{'id' => 1, 'name' => ...}, {'id' => ...}]
370
+ ```
371
+
372
+
373
+ ## The Auth Hash
374
+
375
+ Each Successful OmniAuth authorization places an
376
+ [AuthHash](https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema) object in the environment `env['omniauth.auth']`.
377
+ The AuthHash is just an enhanced hash object containing data from the[OAuth2](https://github.com/oauth-xx/oauth2)
378
+ response received from the get-token API call made during the OmniAuth callback phase.
379
+ See OmniAuth's documentation for the AuthHash schema definition.
380
+
381
+ With the growing number of multi-dimensional data structures for the various token response objects,
382
+ mapping of response data to the `AuthHash` object has become increasingly complex.
383
+ To establish a meaningful mapping that serves the downstream application's needs, the functionality
384
+ and goals of the application need to be considered.
385
+
386
+ The omniauth-slack gem will now copy the access-token hash to the AuthHash `info` section,
387
+ but it will no longer be mapping specific data points from the access-token
388
+ to specific fields in the AuthHash `info` section (other than `info` fields that are 'required'
389
+ by the OmniAuth::AuthHash schema spec).
390
+
391
+ Application developers are welcome to define their own **`info`** section directly within the omniauth-slack strategy.
392
+ And the same customization can be done for any of the top-level AuthHash sections.
393
+
394
+ ```ruby
395
+ class OmniAuth::Strategies::Slack
396
+ info do
397
+ # Should return a hash object.
398
+ # Will be called during the callback-phase.
399
+ # Will be evaluated in the context of the strategy instance.
400
+ # Strategy options are available in this context.
401
+ # Current access_token (assuming it was successful) is available in this context.
402
+ end
403
+ end
404
+ ```
405
+
406
+ If you want to build your own `info` section *and* have it appended to omniauth-slack's default
407
+ `info` section, then subclass the strategy and use that subclass as your `OmniAuth` provider.
408
+
409
+ ```ruby
410
+ class MyCustomStrategy < OmniAuth::Strategies::Slack
411
+ info do
412
+ # Should return a hash object.
413
+ # Will be called during the callback-phase.
414
+ # Will be evaluated in the context of the strategy instance.
415
+ # Strategy options are available in this context.
416
+ # Current access_token (assuming it was successful) is available in this context.
417
+ end
418
+ end
419
+
420
+ # ...
421
+
422
+ use OmniAuth::Builder do
423
+ provider MyCustomStrategy, SLACK_OAUTH_KEY, SLACK_OAUTH_SECRET, scope: ...
424
+ end
425
+ ```
426
+
427
+ The **`credentials`** section of the AuthHash will contain the access-token string, the awarded
428
+ scopes, and any other essential authentication information returned in the OAuth2 response.
429
+
430
+ The **`extra`** section contains two hash keys:
431
+ * `:scopes_requested` hash, which are the scopes requested during the current authorization.
432
+ * `:raw_info` hash, which contains the raw response object from any API calls made during the callback phase.
433
+
434
+
435
+ ## The OAuth2 Cycle
436
+
437
+ The OAuth2 cycle is a three-way dance between the user's browser, the OAuth2 provider (Slack API), and the application server (your Slack App). It should work this way for any OAuth2 provider, including Slack.
438
+
439
+ 1. The user/browser makes a request to `https://slack.com/oauth/authorize`, passing the application's client-id, requested-scopes, and optionally state, team-id, and redirect-uri. Slack then runs the user through the authorization dialogs.
440
+
441
+ 2. Upon successful authorization, Slack redirects the browser to the application's callback url (or redirect_uri in Slack's terms) with a short-lived authorization code, for example:
442
+
443
+ `https://yourapp.com/auth/slack/callback?code=ABCDE87364`
444
+
445
+ 3. Omniauth-slack intercepts this request and exchanges the code, via Slack API, for a valid access-token.
446
+
447
+ And that's it. Control is then given to your application's `/auth/slack/callback` action.
448
+
449
+ The next step would be the application storing the access-token, maybe making additional API requests, and then rendering a page to the browser or redirecting to another action. In a working app, a session would store a reference to the token, and the token would be stored in a database. Then for every request from that user, a valid access-token would be accessible and usable to make further API requests.
450
+
451
+
452
+ ## The OAuth2 Cycle with OmniAuth Slack
453
+
454
+ While the browser experience may appear simple, there's quite a lot happening behind
455
+ the scenes in the omniauth-oauth2 library that omniauth-slack is derived from.
456
+ Omiauth-slack is Rack middleware loaded in the stack behind your main app,
457
+ and it handles the [above](#the-oauth2-cycle) sequence(s) before your application receives the request(s).
458
+
459
+ So lets run through the cycle again and take a closer look.
460
+
461
+ 0.
462
+ 1. The user/browser makes a request to your application at `http://yourapp.com/auth/slack`. This URI could be the href of your signin-with-slack or add-to-slack button.
463
+
464
+ Your application's server-side code doesn't need to know about this endpoint, and it doesn't need to define an action for it. Omniauth-slack middleware recognizes this URI as the authorization request.
465
+
466
+ 2. Omniauth-slack intercepts this request, considers local configuration, stores some data in a session variable, and then redirects the browser, with the necessary data embedded in the URI params, to Slack's authorization URI.
467
+
468
+ OmniAuth calls this the **request phase**, and your application sees none of it.
469
+
470
+ 1.
471
+ 1. Having been redirected by omniauth-slack, the browser makes an authorization request to `https://slack.com/oauth/authorize`, passing the application's client-id, requested-scopes, and optionally state, team-id, and redirect-uri. This request contains everything Slack needs to authenticate the user and authorize access to Slack's API functions and data.
472
+
473
+ 2. Slack leads the user through any dialogs necessary to complete the authorization.
474
+
475
+ Depending on the setup, the requested (and awarded) scopes and permissions, and Slack's internal logic, this cycle could appear as a series of dialogs or as a simple request/response. If identity scopes were requested (signin-with-slack flow), and a team-id was passed in the params, *and* the given scopes were previously authorized, Slack may grant authorization without requiring the user to click on any dialogs at all.
476
+
477
+ Meanwhile, the application server and omniauth-slack are patiently waiting and have no idea what Slack, or the user, are doing at this point.
478
+
479
+ 2. Upon successful authorization, Slack redirects the browser to the application's callback url (or redirect_uri) with a short-lived authorization code, for example:
480
+
481
+ `https://yourapp.com/auth/slack/callback?code=ABCDE87364`.
482
+
483
+ Your application needs to define an endpoint for `/auth/slack/callback`, but omniauth-slack does all of its work before your app even sees the request.
484
+
485
+ 3. 1. Omniauth-slack intercepts this request, and exchanges the authorization code for a valid access-token by making an API request to `https://slack.com/api/oauth.access`.
486
+
487
+ The `oauth.access` response contains an access-token (and possibly other data) which omniauth-slack stores in the Rack `env` for later use by your application.
488
+
489
+ OmniAuth refers to this part of the process as the **callback phase**, and you don't see any of it (Rack middleware magic).
490
+
491
+ 2. Rack then passes this callback request to your app, and you are at the logical beginning of whatever action you defined for `/auth/slack/callback`.
492
+
493
+ There is a lot of data available in the request `env['omniauth.auth']` and `env['omniauth.strategy']`. There are also other env variables defined by omniauth and omniauth-slack. See the gem docs for more about those.
494
+
495
+
496
+ At this point, you will likely want to grab the `env['omniauth.auth']` hash and the `env['omniauth.strategy'].access_token` object. Use the access-token to make further API requests, or store the token and auth_hash for later retrieval.
497
+
498
+ <!-- *TODO: Fix this reference to 'below'*: -->
499
+
500
+ See the note about access-tokens below.
501
+
502
+
503
+ ## Slack Workspace Apps
504
+ This gem provides support for Slack's [Workspace apps](https://api.slack.com/workspace-apps-preview) (now legacy). There are some important differences between Slack's classic apps and the new Workspace apps. The main points to be aware of when using omniauth-slack with Workspace Apps are:
505
+
506
+ * Workspace app tokens are issued as a single token per team. There are no user or bot tokens. All Workspace app API calls are made with the Workspace token. Calls that act on behalf of a user or bot are made with the same token.
507
+
508
+ * The available api calls and the scopes required to access them are different in Workspace apps.
509
+
510
+ * The `AuthHash.credentials.scopes` value, returned from a successful authentication, is a hash with each value containing an array of scopes. The usual `scope` key will not have a value.
511
+
512
+
513
+ ## OmniAuth Slack Basic Examples
514
+
515
+ <!-- *TODO: Clean this sentence up, or fix the reference to 'below':* -->
516
+
517
+ Don't forget to set up your Slack app on [api.slack.com](https://api.slack.com/apps).
518
+
519
+ ### Sinatra Example
520
+
521
+ Create a Sinatra project directory, then add these files.
522
+
523
+ #### simple_app.rb
524
+
525
+ ```ruby
526
+ require 'omniauth-slack'
527
+ require 'sinatra'
528
+ require 'yaml'
529
+
530
+ enable :sessions
531
+
532
+ # optional
533
+ #set :port, '9292'
534
+ #set :bind, '0.0.0.0'
535
+
536
+ use OmniAuth::Builder do
537
+ provider :slack, SLACK_OAUTH_KEY, SLACK_OAUTH_SECRET, scope:'identity:read:user'
538
+ end
539
+
540
+ get '/auth/slack/callback' do
541
+ content_type 'text/yaml'
542
+ { auth_hash: env['omniauth.auth'],
543
+ access_token: env['omniauth.strategy'].access_token
544
+ }.to_yaml
545
+ end
546
+ ```
547
+ #### Gemfile
548
+
549
+ ```ruby
550
+ source 'https://rubygems.org'
551
+ gem 'ginjo-omniauth-slack' #, git:'https://github.com/ginjo/omniauth-slack'
552
+ gem 'sinatra'
553
+ gem 'puma'
554
+ ```
555
+
556
+ Put those in their respective files, fill in your Slack OAuth2 credentials, then launch.
557
+
558
+ bundle install
559
+ bundle exec ruby super_simple.rb
560
+
561
+ Then point your browser to
562
+
563
+ http://<host-and-port-recognized-in-slack-redirect-uri-list>/auth/slack
564
+
565
+ When a successful authorization cycle completes, your browser should end up with a yaml representation of the auth_hash and access_token objects. What happens next is entirely up to your application.
566
+
567
+ ### Rails Example
568
+
569
+ Create a rails project, then add or modify these files. Note that this is not necessarily the best way to do this in a production system. It's just a demonstration of the bare necessities to get omniauth-slack working in Rails.
570
+
571
+ #### config/initializers/middleware.rb
572
+
573
+ ```ruby
574
+ require 'omniauth-slack'
575
+
576
+ Rails.application.config.middleware.use OmniAuth::Builder do
577
+ provider :slack, SLACK_OAUTH_KEY, SLACK_OAUTH_SECRET, scope:'identity:read:user'
578
+ end
579
+ ```
580
+ #### app/controllers/auth_controller.rb
581
+
582
+ ```ruby
583
+ class AuthController < ApplicationController
584
+ def callback
585
+ render plain: { access_token: request.env['omniauth.strategy'].access_token.to_hash,
586
+ auth_hash: request.env['omniauth.auth']
587
+ }.to_yaml
588
+ end
589
+ end
590
+ ```
591
+ #### config/routes.rb
592
+
593
+ ```ruby
594
+ get 'auth/slack/callback', to: 'auth#callback'
595
+ ```
596
+ #### Gemfile
597
+
598
+ ```ruby
599
+ gem 'ginjo-omniauth-slack' #, git:'https://github.com/ginjo/omniauth-slack'
600
+ ```
601
+ Don't forget to fill in your Slack API credentials. Then start up Rails, and point your browser to
602
+
603
+ http://<host-and-port-recognized-in-slack-redirect-uri-list>/auth/slack
604
+
605
+ When a successful authorization cycle completes, your browser should end up with a yaml representation of the auth_hash and access_token objects. What happens next is entirely up to your application.
606
+
607
+
608
+ ## Advanced / Experimental
609
+
610
+ * Deep debug with `ENV['OMNIAUTH_SLACK_DEBUG']=true`.
611
+ Will output a LOT of detailed TRACE log items.
612
+ Only use this for debugging during development.
613
+
614
+ * An optional `OmniAuth::Slack::VerifySlackSignature` middleware class handles signature
615
+ verification for incoming Slack requests. This is helpful if you receive Slack
616
+ events in your application.
617
+
618
+ ```ruby
619
+ # In your rack middleware setup file.
620
+
621
+ use OmniAuth::Slack::VerifySlackSignature do |config|
622
+ config.app_id = ENV['SLACK_APP_ID']
623
+ config.signing_secret = ENV['SLACK_SIGNING_SECRET']
624
+ end
625
+
626
+ # When legitimate incoming Slack request is received by your app:
627
+ env['omniauth.slack.verification'] == true
628
+
629
+ # When illegitimate incoming Slack request is received by your app:
630
+ env['omniauth.slack.verification'] == false
631
+
632
+ # When any other request is received by your app:
633
+ env['omniauth.slack.verification'] == nil
634
+
635
+ ```
307
636
 
308
- See <https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema> for more info on the auth_hash schema.
309
637
 
310
638
  ## Contributing
311
639
 
@@ -314,3 +642,4 @@ See for more info o
314
642
  3. Commit your changes (`git commit -am 'Add some feature'`)
315
643
  4. Push to the branch (`git push origin my-new-feature`)
316
644
  5. Create new Pull Request
645
+