slack_sign_in 0.1.3.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d3eedae0b2cfe987cb083c1d056a144fc8ce9f408254bbfed065662c1ac7841e
4
+ data.tar.gz: f50afab462ee8c2d3c0990dad9809d6abd2ddf9503abb13db166588175eb8af0
5
+ SHA512:
6
+ metadata.gz: 53e178b38f88ec229c38ae8771aef4e414c9cffe0d69e26374686aa2b14d37f52a86a5355334b8fc1ee20232a5142fd2a4e40655984855047cab350272b245fd
7
+ data.tar.gz: 3b8e0e581c982d2609bc2e8f664f16ba2fcc44380961725cc59d079f59f0a4b24adc09fd0948f941345d87c61325021c77f03a48c542a0ac66fd4ad2660731b8
@@ -0,0 +1,253 @@
1
+ # Slack Sign-In for Rails
2
+
3
+ The goal of this gem is to get you up and running with Slack sign-ins:
4
+
5
+ - with minimal configuration
6
+ - as quickly as possible
7
+ - without sacrificing on long-term stability and maintainability
8
+
9
+ The creation of this gem was heavily inspired by the awesome
10
+ [basecamp/google_sign_in](https://github.com/basecamp/google_sign_in) project,
11
+ both in its aspirations and in its implementation. If you need to add Google
12
+ sign-in to your Rails project, definitely check it out!
13
+
14
+ This project adheres to the Contributor Covenant
15
+ [code of conduct](./CODE_OF_CONDUCT.md). By participating, you are expected to
16
+ uphold this code. Please report unacceptable behavior to
17
+ research@teecom.com.
18
+
19
+ In addition to the documentation here, we also have a **[Getting Started with `slack_sign_in`](https://vimeo.com/387819353)** video :movie_camera:.
20
+
21
+ ## Installation
22
+
23
+ Add `slack_sign_in` to your Rails app's Gemfile and run `bundle install`:
24
+
25
+ ```ruby
26
+ gem "slack_sign_in"
27
+ ```
28
+
29
+ *Note:* This gem requires Rails 5.2 or newer.
30
+
31
+ ## Creating a Slack App
32
+
33
+ Before getting started, you'll likely need to set up a Slack application:
34
+
35
+ 1. Go to the [Slack applications list](https://api.slack.com/apps)
36
+
37
+ 2. Either click **Create New App**, or select an existing application
38
+
39
+ 3. Take note of your app's **Client ID** and **Client Secret**
40
+
41
+ <details>
42
+ <summary>Slack app credentials visual guide :framed_picture:</summary>
43
+
44
+ ![Slack App Credentials](./doc/images/app_credentials.png)
45
+ </details>
46
+
47
+ 4. Under the **OAuth & Permissions** tab, add your app's callback URLs to the
48
+ list of **Redirect URLs** section.
49
+
50
+ This gem adds a single OAuth callback to your Rails application at
51
+ `/slack_sign_in/callback`. For a production application, you might add a
52
+ redirect URL of:
53
+
54
+ ```
55
+ https://www.example.com/slack_sign_in/callback
56
+ ```
57
+
58
+ To sign in with Slack in development, you would likely also add a redirect
59
+ URL for your local environment. Something like:
60
+
61
+ ```
62
+ http://localhost:3000/slack_sign_in/callback
63
+ ```
64
+
65
+ <details>
66
+ <summary>Slack app redirect URLs visual guide :framed_picture:</summary>
67
+
68
+ ![Slack App Redirect URLs](./doc/images/redirect_urls.png)
69
+ </details>
70
+
71
+ ## Configuration
72
+
73
+ With your Slack application set up, the next step is to configure your Rails
74
+ app to use it. Run `rails credentials:edit` to edit your app's
75
+ [encrypted credentials](https://guides.rubyonrails.org/security.html#custom-credentials)
76
+ and add the following:
77
+
78
+ ```yaml
79
+ slack_sign_in:
80
+ client_id: "[Your client ID here]"
81
+ client_secret: "[Your client secret here]"
82
+ ```
83
+
84
+ You're all set to use Slack sign-in now. The gem will automatically use these
85
+ client credentials! :tada:
86
+
87
+ Alternatively, you can provide the Slack credentials through an initializer
88
+ and environment variables:
89
+
90
+ ```ruby
91
+ # config/initializers/slack_sign_in.rb
92
+ Rails.application.configure do
93
+ config.slack_sign_in.client_id = ENV.fetch("SLACK_CLIENT_ID")
94
+ config.slack_sign_in.client_secret = ENV.fetch("SLACK_CLIENT_SECRET")
95
+ end
96
+ ```
97
+
98
+ **:warning: Important:** Take care to protect your client secret. It's a secret
99
+ after all!
100
+
101
+ ### Scopes
102
+
103
+ By default, this gem will request the following scopes from Slack:
104
+
105
+ - `identity.basic`
106
+ - `identity.email`
107
+ - `identity.avatar`
108
+
109
+ If these scopes don't suit your particular need, you can configure the gem to
110
+ use any of the
111
+ [supported Slack scopes](https://api.slack.com/docs/sign-in-with-slack#identity_scopes)
112
+ through an initializer:
113
+
114
+ ```ruby
115
+ # config/initializers/slack_sign_in.rb
116
+ Rails.application.configure do
117
+ config.slack_sign_in.scopes = %w(identity.basic identity.team)
118
+ end
119
+ ```
120
+
121
+ ### Mounting Root
122
+
123
+ By default, this gem will mount its routes at `/slack_sign_in`. If this doesn't
124
+ suit your needs, it can be configured through an initializer:
125
+
126
+ ```ruby
127
+ # config/initializers/slack_sign_in.rb
128
+ Rails.application.configure do
129
+ config.slack_sign_in.root = "sso/slack"
130
+ end
131
+ ```
132
+
133
+ In this example, the gem would add a callback URL of `/sso/slack/callback`
134
+ rather than the default of `/slack_sign_in/callback`.
135
+
136
+ ## Usage
137
+
138
+ This gem provides a `slack_sign_in_link` helper that generates a link that will
139
+ kick off the sign-in process:
140
+
141
+ ```erb
142
+ <%= slack_sign_in_link proceed_to: create_session_url %>
143
+
144
+ <%= slack_sign_in_link "Sign In!", proceed_to: create_session_url %>
145
+
146
+ <%= slack_sign_in_link proceed_to: create_session_url do %>
147
+ <div style="background: blue; padding: 10px; display: inline-block;">
148
+ <%= slack_sign_in_image %>
149
+ </div>
150
+ <% end %>
151
+ ```
152
+
153
+ <details>
154
+ <summary>Sign in link visuals :framed_picture:</summary>
155
+
156
+ ![Sign in links](./doc/images/sign_in_links.png)
157
+ </details>
158
+
159
+ Regardless of whether you use the default link, a text link, or a block link,
160
+ the `proceed_to` argument is always required. After authenticating with Slack,
161
+ we'll redirect to this URL with information on the authorization's success or
162
+ failure for your application to handle.
163
+
164
+ In most cases, that might look something like this:
165
+
166
+ ```ruby
167
+ # config/routes.rb
168
+ Rails.application.routes.draw do
169
+ # ...
170
+ get "sessions/create", to: "sessions#create", as: :create_session
171
+ end
172
+ ```
173
+
174
+ ```ruby
175
+ # app/controllers/sessions_controller.rb
176
+ class SessionsController < ApplicationController
177
+ include SlackSignIn::Authorization
178
+
179
+ def create
180
+ if slack_authorization.successful?
181
+ render plain: slack_authorization.identity.name
182
+ else
183
+ render plain: slack_authorization.error
184
+ end
185
+ end
186
+ end
187
+ ```
188
+
189
+ #### The `SlackSignIn::Authorization` Concern
190
+
191
+ The `SlackSignIn::Authorization` concern is the primary interface for accessing
192
+ information about the Slack sign-in process. It exposes a single method,
193
+ `slack_authorization`, which will give you a
194
+ [`SlackSignIn::Result`](#slacksigninresult) for the recently completed Slack
195
+ sign-in flow.
196
+
197
+ In the majority of cases, you should be able to use the
198
+ `SlackSignIn::Authorization` concern along with the `slack_authorization`
199
+ method to accomplish what you want. In some cases, you may need direct access to
200
+ the full Slack response, though.
201
+
202
+ Before redirecting to the specified `proceed_to` URL, this gem will either set
203
+ `flash[:slack_sign_in]["success"]` to the Slack response, or
204
+ `flash[:slack_sign_in]["error"]` to an
205
+ [OAuth authorizaton code grant error](https://tools.ietf.org/html/rfc6749#section-4.1.2.1).
206
+ If you need direct access to the Slack response information, this is how you can
207
+ get it.
208
+
209
+ #### `SlackSignIn::Result`
210
+
211
+ The `SlackSignIn::Result` class provides an interface for handling the result of
212
+ a Slack sign-in attempt. It exposes three instance methods:
213
+
214
+ 1. `successful?` - to determine whether the sign-in attempt succeeded or not
215
+
216
+ 2. `identity` - either `nil` or a [`SlackSignIn::Identity`](#slacksigninidentity)
217
+ instance with user identity information from Slack
218
+
219
+ 3. `error` - either `nil` or an
220
+ [OAuth authorizaton code grant error](https://tools.ietf.org/html/rfc6749#section-4.1.2.1)
221
+
222
+ #### `SlackSignIn::Identity`
223
+
224
+ The `SlackSignIn::Identity` class decodes user identity information from Slack.
225
+ It exposes this information through a handful of instance methods:
226
+
227
+ - `unique_id` - a unique identifier from Slack that can be used to look up
228
+ people
229
+
230
+ - `team_id` - the ID of the team used while signing in
231
+
232
+ - `user_id` - the ID of the user who signed in
233
+
234
+ - `name` - the name of the user who signed in
235
+
236
+ - `email` - the email of the user who signed in
237
+
238
+ - `avatar(size: 48)` - the avatar of the user who signed in
239
+ (in a specific size). Typically the sizes provided by slack are
240
+ `24x24`, `32x32`, `48x48`, `72x72`, `192x192`, and `512x512`.
241
+
242
+ ## Contributing
243
+
244
+ For information on how to contribute to this project, check out the
245
+ [contributing guidelines](./CONTRIBUTING.md).
246
+
247
+ ## Questions?
248
+
249
+ If you have any questions about, or if any of the documentation is unclear,
250
+ please feel free to reach out through a
251
+ [new issue](https://github.com/TEECOM/slack_sign_in/issues/new?labels=documentation%20:writing_hand:).
252
+
253
+ :smiley_cat:
@@ -0,0 +1,18 @@
1
+ begin
2
+ require "bundler/setup"
3
+ require "bundler/gem_tasks"
4
+ rescue LoadError
5
+ puts "You must `gem install bundler` and `bundle install` to run rake tasks"
6
+ end
7
+
8
+ require "rake/testtask"
9
+ require "standard/rake"
10
+
11
+ Rake::TestTask.new(:test) do |t|
12
+ t.libs << "test"
13
+ t.pattern = "test/**/*_test.rb"
14
+ t.verbose = false
15
+ t.warning = false
16
+ end
17
+
18
+ task default: [:test, :standard]
@@ -0,0 +1,9 @@
1
+ module SlackSignIn::Authorization
2
+ extend ActiveSupport::Concern
3
+
4
+ private
5
+
6
+ def slack_authorization
7
+ @_result ||= SlackSignIn::Result.new(flash[:slack_sign_in])
8
+ end
9
+ end
@@ -0,0 +1,17 @@
1
+ module SlackSignIn
2
+ class ApplicationController < ActionController::Base
3
+ protect_from_forgery with: :exception
4
+
5
+ private
6
+
7
+ def client
8
+ @_client ||= SlackSignIn.client.new(
9
+ SlackSignIn.client_id,
10
+ SlackSignIn.client_secret,
11
+ authorize_url: SlackSignIn::AUTHORIZE_URL,
12
+ token_url: SlackSignIn::TOKEN_URL,
13
+ redirect_uri: callback_url,
14
+ )
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,23 @@
1
+ class SlackSignIn::AuthorizationsController < SlackSignIn::ApplicationController
2
+ def create
3
+ redirect_to slack_login_url, flash: {proceed_to: proceed_to, state: state}
4
+ end
5
+
6
+ private
7
+
8
+ def slack_login_url
9
+ client.auth_code.authorize_url(scope: scopes, state: state)
10
+ end
11
+
12
+ def scopes
13
+ SlackSignIn.scopes.join(" ")
14
+ end
15
+
16
+ def proceed_to
17
+ params.require(:proceed_to)
18
+ end
19
+
20
+ def state
21
+ @_state ||= SecureRandom.urlsafe_base64(24)
22
+ end
23
+ end
@@ -0,0 +1,39 @@
1
+ class SlackSignIn::CallbacksController < SlackSignIn::ApplicationController
2
+ def show
3
+ return head(:bad_request) if proceed_to_missing?
4
+
5
+ redirect_to proceed_to_url, flash: {slack_sign_in: slack_sign_in_result}
6
+ end
7
+
8
+ private
9
+
10
+ def proceed_to_missing?
11
+ proceed_to_url.blank?
12
+ end
13
+
14
+ def proceed_to_url
15
+ flash[:proceed_to]
16
+ end
17
+
18
+ def slack_sign_in_result
19
+ if valid_request? && params[:code].present?
20
+ {success: identity_information}
21
+ else
22
+ {error: error_for(params[:error])}
23
+ end
24
+ rescue OAuth2::Error => error
25
+ {error: error_for(error.code)}
26
+ end
27
+
28
+ def valid_request?
29
+ flash[:state].present? && params[:state] == flash[:state]
30
+ end
31
+
32
+ def identity_information
33
+ client.auth_code.get_token(params[:code]).params
34
+ end
35
+
36
+ def error_for(error)
37
+ error || "invalid_request"
38
+ end
39
+ end
@@ -0,0 +1,27 @@
1
+ module SlackSignIn::LinkHelper
2
+ def slack_sign_in_link(text = nil, proceed_to:, **options, &block)
3
+ options = options.merge(method: :post)
4
+ auth_url = slack_sign_in.authorization_path(proceed_to: proceed_to)
5
+
6
+ if text
7
+ link_to(text, auth_url, options)
8
+ elsif block_given?
9
+ link_to(auth_url, options, &block)
10
+ else
11
+ link_to(auth_url, options) { slack_sign_in_image }
12
+ end
13
+ end
14
+
15
+ def slack_sign_in_image
16
+ image_tag(
17
+ "https://platform.slack-edge.com/img/sign_in_with_slack.png",
18
+ alt: "Sign in with Slack",
19
+ height: 40,
20
+ width: 172,
21
+ srcset: {
22
+ "https://platform.slack-edge.com/img/sign_in_with_slack.png" => "1x",
23
+ "https://platform.slack-edge.com/img/sign_in_with_slack@2x.png" => "2x",
24
+ },
25
+ )
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ class SlackSignIn::Identity
2
+ def initialize(params)
3
+ @params = params
4
+ end
5
+
6
+ def unique_id
7
+ "#{team_id}-#{user_id}"
8
+ end
9
+
10
+ def team_id
11
+ params["team_id"]
12
+ end
13
+
14
+ def user_id
15
+ params["user_id"]
16
+ end
17
+
18
+ def name
19
+ params.dig("user", "name")
20
+ end
21
+
22
+ def email
23
+ params.dig("user", "email")
24
+ end
25
+
26
+ def avatar(size: 48)
27
+ params.dig("user", "image_#{size}")
28
+ end
29
+
30
+ private
31
+
32
+ attr_reader :params
33
+ end
@@ -0,0 +1,23 @@
1
+ class SlackSignIn::Result
2
+ def initialize(result)
3
+ @result = result || {"error" => "invalid_request"}
4
+ end
5
+
6
+ def successful?
7
+ result.key? "success"
8
+ end
9
+
10
+ def identity
11
+ return unless successful?
12
+
13
+ SlackSignIn::Identity.new(result["success"])
14
+ end
15
+
16
+ def error
17
+ result["error"]
18
+ end
19
+
20
+ private
21
+
22
+ attr_reader :result
23
+ end
@@ -0,0 +1,4 @@
1
+ SlackSignIn::Engine.routes.draw do
2
+ resource :authorization, only: :create
3
+ resource :callback, only: :show
4
+ end
@@ -0,0 +1,11 @@
1
+ require "slack_sign_in/engine"
2
+
3
+ module SlackSignIn
4
+ DEFAULT_SCOPES = %w[identity.basic identity.email identity.avatar]
5
+
6
+ AUTHORIZE_URL = "https://slack.com/oauth/authorize"
7
+ TOKEN_URL = "https://slack.com/api/oauth.access"
8
+
9
+ mattr_accessor :client_id, :client_secret
10
+ mattr_accessor :scopes, :client
11
+ end
@@ -0,0 +1,35 @@
1
+ require "oauth2"
2
+ require "slack_sign_in/test_client"
3
+
4
+ module SlackSignIn
5
+ class Engine < ::Rails::Engine
6
+ isolate_namespace SlackSignIn
7
+
8
+ config.slack_sign_in = ActiveSupport::OrderedOptions.new
9
+
10
+ initializer "slack_sign_in.config" do |app|
11
+ config.after_initialize do
12
+ SlackSignIn.client_id = config.slack_sign_in.client_id || app.credentials.dig(:slack_sign_in, :client_id)
13
+ SlackSignIn.client_secret = config.slack_sign_in.client_secret || app.credentials.dig(:slack_sign_in, :client_secret)
14
+ SlackSignIn.scopes = config.slack_sign_in.scopes || SlackSignIn::DEFAULT_SCOPES
15
+ SlackSignIn.client = config.slack_sign_in.client || OAuth2::Client
16
+ end
17
+ end
18
+
19
+ initializer "slack_sign_in.helpers" do
20
+ ActiveSupport.on_load :action_controller_base do
21
+ helper SlackSignIn::Engine.helpers
22
+ end
23
+ end
24
+
25
+ initializer "slack_sign_in.mount" do |app|
26
+ app.routes.prepend do
27
+ mount SlackSignIn::Engine, at: app.config.slack_sign_in.root || "slack_sign_in"
28
+ end
29
+ end
30
+
31
+ initializer "slack_sign_in.parameter_filters" do |app|
32
+ app.config.filter_parameters << :code
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,15 @@
1
+ require "minitest/mock"
2
+
3
+ module SlackSignIn::SystemTestHelpers
4
+ def mock_successful_authorization(identity_info, &block)
5
+ SlackSignIn::TestClient.stub(
6
+ :identity_info,
7
+ SlackSignIn::TestClient.identity_info.merge(identity_info),
8
+ &block
9
+ )
10
+ end
11
+
12
+ def mock_failed_authorization(error, &block)
13
+ SlackSignIn::TestClient.stub(:error_code, error, &block)
14
+ end
15
+ end
@@ -0,0 +1,45 @@
1
+ module SlackSignIn
2
+ class TestClient
3
+ def self.error_code
4
+ nil
5
+ end
6
+
7
+ def self.identity_info
8
+ {
9
+ team_id: "team_id_123",
10
+ user_id: "user_id_123",
11
+ user: {
12
+ name: "Example User",
13
+ email: "example@email.com",
14
+ image_48: "http://avatar.com",
15
+ },
16
+ }
17
+ end
18
+
19
+ def initialize(_, _, authorize_url:, token_url:, redirect_uri:)
20
+ @redirect_uri = redirect_uri
21
+ end
22
+
23
+ def auth_code
24
+ self
25
+ end
26
+
27
+ def authorize_url(scope:, state:)
28
+ base_url = @redirect_uri + "?state=#{state}&"
29
+
30
+ if (error = self.class.error_code)
31
+ base_url + "&error=#{error}"
32
+ else
33
+ base_url + "&code=123"
34
+ end
35
+ end
36
+
37
+ def get_token(_)
38
+ self
39
+ end
40
+
41
+ def params
42
+ self.class.identity_info
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module SlackSignIn
2
+ VERSION = "0.1.3.rc1"
3
+ end
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slack_sign_in
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3.rc1
5
+ platform: ruby
6
+ authors:
7
+ - Tom Schaefer
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-02-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oauth2
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 1.4.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 1.4.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 5.2.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 5.2.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: standardrb
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: webmock
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description:
98
+ email:
99
+ - tommy.schaefer@teecom.com
100
+ executables: []
101
+ extensions: []
102
+ extra_rdoc_files: []
103
+ files:
104
+ - README.md
105
+ - Rakefile
106
+ - app/controllers/concerns/slack_sign_in/authorization.rb
107
+ - app/controllers/slack_sign_in/application_controller.rb
108
+ - app/controllers/slack_sign_in/authorizations_controller.rb
109
+ - app/controllers/slack_sign_in/callbacks_controller.rb
110
+ - app/helpers/slack_sign_in/link_helper.rb
111
+ - app/models/slack_sign_in/identity.rb
112
+ - app/models/slack_sign_in/result.rb
113
+ - config/routes.rb
114
+ - lib/slack_sign_in.rb
115
+ - lib/slack_sign_in/engine.rb
116
+ - lib/slack_sign_in/minitest.rb
117
+ - lib/slack_sign_in/test_client.rb
118
+ - lib/slack_sign_in/version.rb
119
+ homepage: https://github.com/teecom/slack_sign_in
120
+ licenses:
121
+ - MIT
122
+ metadata: {}
123
+ post_install_message:
124
+ rdoc_options: []
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ required_rubygems_version: !ruby/object:Gem::Requirement
133
+ requirements:
134
+ - - ">"
135
+ - !ruby/object:Gem::Version
136
+ version: 1.3.1
137
+ requirements: []
138
+ rubygems_version: 3.1.2
139
+ signing_key:
140
+ specification_version: 4
141
+ summary: Sign in (or up) with Slack for Rails applications
142
+ test_files: []