omniauth 1.2.2 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/.github/FUNDING.yml +2 -0
- data/.github/ISSUE_TEMPLATE.md +20 -0
- data/.github/workflows/main.yml +89 -0
- data/.gitignore +3 -0
- data/.rubocop.yml +43 -55
- data/Gemfile +15 -20
- data/LICENSE.md +1 -1
- data/README.md +141 -44
- data/Rakefile +38 -2
- data/SECURITY.md +17 -0
- data/lib/omniauth/auth_hash.rb +7 -8
- data/lib/omniauth/authenticity_token_protection.rb +32 -0
- data/lib/omniauth/builder.rb +5 -20
- data/lib/omniauth/failure_endpoint.rb +13 -2
- data/lib/omniauth/form.css +1 -1
- data/lib/omniauth/form.rb +3 -2
- data/lib/omniauth/key_store.rb +22 -0
- data/lib/omniauth/strategies/developer.rb +2 -2
- data/lib/omniauth/strategy.rb +141 -67
- data/lib/omniauth/test/strategy_test_case.rb +2 -2
- data/lib/omniauth/version.rb +1 -1
- data/lib/omniauth.rb +30 -22
- data/omniauth.gemspec +11 -8
- metadata +51 -45
- data/.gemtest +0 -0
- data/.travis.yml +0 -37
- data/Gemfile.rack-1.3.x +0 -25
- data/Guardfile +0 -10
- data/spec/helper.rb +0 -55
- data/spec/omniauth/auth_hash_spec.rb +0 -111
- data/spec/omniauth/builder_spec.rb +0 -50
- data/spec/omniauth/failure_endpoint_spec.rb +0 -58
- data/spec/omniauth/form_spec.rb +0 -23
- data/spec/omniauth/strategies/developer_spec.rb +0 -73
- data/spec/omniauth/strategy_spec.rb +0 -768
- data/spec/omniauth_spec.rb +0 -145
data/lib/omniauth/auth_hash.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
require '
|
1
|
+
require 'omniauth/key_store'
|
2
2
|
|
3
3
|
module OmniAuth
|
4
4
|
# The AuthHash is a normalized schema returned by all OmniAuth
|
5
5
|
# strategies. It maps as much user information as the provider
|
6
6
|
# is able to provide into the InfoHash (stored as the `'info'`
|
7
7
|
# key).
|
8
|
-
class AuthHash <
|
8
|
+
class AuthHash < OmniAuth::KeyStore
|
9
9
|
def self.subkey_class
|
10
10
|
Hashie::Mash
|
11
11
|
end
|
@@ -20,13 +20,11 @@ module OmniAuth
|
|
20
20
|
end
|
21
21
|
|
22
22
|
def regular_writer(key, value)
|
23
|
-
if key.to_s == 'info' && !value.is_a?(InfoHash)
|
24
|
-
value = InfoHash.new(value)
|
25
|
-
end
|
23
|
+
value = InfoHash.new(value) if key.to_s == 'info' && value.is_a?(::Hash) && !value.is_a?(InfoHash)
|
26
24
|
super
|
27
25
|
end
|
28
26
|
|
29
|
-
class InfoHash <
|
27
|
+
class InfoHash < OmniAuth::KeyStore
|
30
28
|
def self.subkey_class
|
31
29
|
Hashie::Mash
|
32
30
|
end
|
@@ -36,13 +34,14 @@ module OmniAuth
|
|
36
34
|
return "#{first_name} #{last_name}".strip if first_name? || last_name?
|
37
35
|
return nickname if nickname?
|
38
36
|
return email if email?
|
37
|
+
|
39
38
|
nil
|
40
39
|
end
|
41
40
|
|
42
41
|
def name?
|
43
|
-
!!name
|
42
|
+
!!name
|
44
43
|
end
|
45
|
-
|
44
|
+
alias valid? name?
|
46
45
|
|
47
46
|
def to_hash
|
48
47
|
hash = super
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rack-protection'
|
2
|
+
|
3
|
+
module OmniAuth
|
4
|
+
class AuthenticityError < StandardError; end
|
5
|
+
class AuthenticityTokenProtection < Rack::Protection::AuthenticityToken
|
6
|
+
def initialize(options = {})
|
7
|
+
@options = default_options.merge(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.call(env)
|
11
|
+
new.call!(env)
|
12
|
+
end
|
13
|
+
|
14
|
+
def call!(env)
|
15
|
+
return if accepts?(env)
|
16
|
+
|
17
|
+
instrument env
|
18
|
+
react env
|
19
|
+
end
|
20
|
+
|
21
|
+
alias_method :call, :call!
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def deny(_env)
|
26
|
+
OmniAuth.logger.send(:warn, "Attack prevented by #{self.class}")
|
27
|
+
raise AuthenticityError.new(options[:message])
|
28
|
+
end
|
29
|
+
|
30
|
+
alias default_reaction deny
|
31
|
+
end
|
32
|
+
end
|
data/lib/omniauth/builder.rb
CHANGED
@@ -1,20 +1,5 @@
|
|
1
1
|
module OmniAuth
|
2
2
|
class Builder < ::Rack::Builder
|
3
|
-
def initialize(app, &block)
|
4
|
-
@options = nil
|
5
|
-
if rack14?
|
6
|
-
super
|
7
|
-
else
|
8
|
-
@app = app
|
9
|
-
super(&block)
|
10
|
-
@ins << @app
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
def rack14?
|
15
|
-
Rack.release.split('.')[1].to_i >= 4
|
16
|
-
end
|
17
|
-
|
18
3
|
def on_failure(&block)
|
19
4
|
OmniAuth.config.on_failure = block
|
20
5
|
end
|
@@ -36,23 +21,23 @@ module OmniAuth
|
|
36
21
|
end
|
37
22
|
|
38
23
|
def options(options = false)
|
39
|
-
return @options
|
24
|
+
return @options ||= {} if options == false
|
25
|
+
|
40
26
|
@options = options
|
41
27
|
end
|
42
28
|
|
43
|
-
def provider(klass, *args, &block)
|
29
|
+
def provider(klass, *args, **opts, &block)
|
44
30
|
if klass.is_a?(Class)
|
45
31
|
middleware = klass
|
46
32
|
else
|
47
33
|
begin
|
48
|
-
middleware = OmniAuth::Strategies.const_get(
|
34
|
+
middleware = OmniAuth::Strategies.const_get(OmniAuth::Utils.camelize(klass.to_s).to_s, false)
|
49
35
|
rescue NameError
|
50
36
|
raise(LoadError.new("Could not find matching strategy for #{klass.inspect}. You may need to install an additional gem (such as omniauth-#{klass})."))
|
51
37
|
end
|
52
38
|
end
|
53
39
|
|
54
|
-
|
55
|
-
use middleware, *args, &block
|
40
|
+
use middleware, *args, **options.merge(opts), &block
|
56
41
|
end
|
57
42
|
|
58
43
|
def call(env)
|
@@ -22,22 +22,33 @@ module OmniAuth
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def raise_out!
|
25
|
-
|
25
|
+
raise(env['omniauth.error'] || OmniAuth::Error.new(env['omniauth.error.type']))
|
26
26
|
end
|
27
27
|
|
28
28
|
def redirect_to_failure
|
29
29
|
message_key = env['omniauth.error.type']
|
30
|
-
|
30
|
+
|
31
|
+
new_path = "#{env['SCRIPT_NAME']}#{strategy_path_prefix}/failure?message=#{Rack::Utils.escape(message_key)}#{origin_query_param}#{strategy_name_query_param}"
|
31
32
|
Rack::Response.new(['302 Moved'], 302, 'Location' => new_path).finish
|
32
33
|
end
|
33
34
|
|
35
|
+
def strategy_path_prefix
|
36
|
+
if env['omniauth.error.strategy']
|
37
|
+
env['omniauth.error.strategy'].path_prefix
|
38
|
+
else
|
39
|
+
OmniAuth.config.path_prefix
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
34
43
|
def strategy_name_query_param
|
35
44
|
return '' unless env['omniauth.error.strategy']
|
45
|
+
|
36
46
|
"&strategy=#{env['omniauth.error.strategy'].name}"
|
37
47
|
end
|
38
48
|
|
39
49
|
def origin_query_param
|
40
50
|
return '' unless env['omniauth.origin']
|
51
|
+
|
41
52
|
"&origin=#{Rack::Utils.escape(env['omniauth.origin'])}"
|
42
53
|
end
|
43
54
|
end
|
data/lib/omniauth/form.css
CHANGED
data/lib/omniauth/form.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
module OmniAuth
|
2
|
-
class Form
|
2
|
+
class Form
|
3
3
|
DEFAULT_CSS = File.read(File.expand_path('../form.css', __FILE__))
|
4
4
|
|
5
5
|
attr_accessor :options
|
@@ -9,7 +9,7 @@ module OmniAuth
|
|
9
9
|
options[:header_info] ||= ''
|
10
10
|
self.options = options
|
11
11
|
|
12
|
-
@html = ''
|
12
|
+
@html = +'' # unary + string allows it to be mutable if strings are frozen
|
13
13
|
@with_custom_button = false
|
14
14
|
@footer = nil
|
15
15
|
header(options[:title], options[:header_info])
|
@@ -82,6 +82,7 @@ module OmniAuth
|
|
82
82
|
|
83
83
|
def footer
|
84
84
|
return self if @footer
|
85
|
+
|
85
86
|
@html << "\n<button type='submit'>Connect</button>" unless @with_custom_button
|
86
87
|
@html << <<-HTML
|
87
88
|
</form>
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'hashie/mash'
|
2
|
+
|
3
|
+
module OmniAuth
|
4
|
+
# Generic helper hash that allows method access on deeply nested keys.
|
5
|
+
class KeyStore < ::Hashie::Mash
|
6
|
+
# Disables warnings on Hashie 3.5.0+ for overwritten keys
|
7
|
+
def self.override_logging
|
8
|
+
require 'hashie/version'
|
9
|
+
return unless Gem::Version.new(Hashie::VERSION) >= Gem::Version.new('3.5.0')
|
10
|
+
|
11
|
+
if respond_to?(:disable_warnings)
|
12
|
+
disable_warnings
|
13
|
+
else
|
14
|
+
define_method(:log_built_in_message) { |*| }
|
15
|
+
private :log_built_in_message
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# Disable on loading of the class
|
20
|
+
override_logging
|
21
|
+
end
|
22
|
+
end
|
@@ -31,13 +31,13 @@ module OmniAuth
|
|
31
31
|
class Developer
|
32
32
|
include OmniAuth::Strategy
|
33
33
|
|
34
|
-
option :fields, [
|
34
|
+
option :fields, %i[name email]
|
35
35
|
option :uid_field, :email
|
36
36
|
|
37
37
|
def request_phase
|
38
38
|
form = OmniAuth::Form.new(:title => 'User Info', :url => callback_path)
|
39
39
|
options.fields.each do |field|
|
40
|
-
form.text_field field.to_s.capitalize.
|
40
|
+
form.text_field field.to_s.capitalize.tr('_', ' '), field.to_s
|
41
41
|
end
|
42
42
|
form.button 'Sign In'
|
43
43
|
form.to_response
|
data/lib/omniauth/strategy.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'omniauth/key_store'
|
2
2
|
|
3
3
|
module OmniAuth
|
4
4
|
class NoSessionError < StandardError; end
|
@@ -6,7 +6,7 @@ module OmniAuth
|
|
6
6
|
# wrangle multiple providers. Each strategy provided by
|
7
7
|
# OmniAuth includes this mixin to gain the default functionality
|
8
8
|
# necessary to be compatible with the OmniAuth library.
|
9
|
-
module Strategy
|
9
|
+
module Strategy # rubocop:disable ModuleLength
|
10
10
|
def self.included(base)
|
11
11
|
OmniAuth.strategies << base
|
12
12
|
|
@@ -14,6 +14,7 @@ module OmniAuth
|
|
14
14
|
base.class_eval do
|
15
15
|
option :setup, false
|
16
16
|
option :skip_info, false
|
17
|
+
option :origin_param, 'origin'
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
@@ -21,9 +22,9 @@ module OmniAuth
|
|
21
22
|
# Returns an inherited set of default options set at the class-level
|
22
23
|
# for each strategy.
|
23
24
|
def default_options
|
24
|
-
|
25
|
+
# existing = superclass.default_options if superclass.respond_to?(:default_options)
|
25
26
|
existing = superclass.respond_to?(:default_options) ? superclass.default_options : {}
|
26
|
-
@default_options
|
27
|
+
@default_options ||= OmniAuth::Strategy::Options.new(existing)
|
27
28
|
end
|
28
29
|
|
29
30
|
# This allows for more declarative subclassing of strategies by allowing
|
@@ -87,10 +88,13 @@ module OmniAuth
|
|
87
88
|
(instance_variable_defined?(:@args) && @args) || existing
|
88
89
|
end
|
89
90
|
|
90
|
-
%w
|
91
|
-
class_eval <<-RUBY
|
91
|
+
%w[uid info extra credentials].each do |fetcher|
|
92
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
93
|
+
attr_reader :#{fetcher}_proc
|
94
|
+
private :#{fetcher}_proc
|
95
|
+
|
92
96
|
def #{fetcher}(&block)
|
93
|
-
return
|
97
|
+
return #{fetcher}_proc unless block_given?
|
94
98
|
@#{fetcher}_proc = block
|
95
99
|
end
|
96
100
|
|
@@ -132,15 +136,16 @@ module OmniAuth
|
|
132
136
|
@options = self.class.default_options.dup
|
133
137
|
|
134
138
|
options.deep_merge!(args.pop) if args.last.is_a?(Hash)
|
135
|
-
options
|
139
|
+
options[:name] ||= self.class.to_s.split('::').last.downcase
|
136
140
|
|
137
141
|
self.class.args.each do |arg|
|
138
142
|
break if args.empty?
|
143
|
+
|
139
144
|
options[arg] = args.shift
|
140
145
|
end
|
141
146
|
|
142
147
|
# Make sure that all of the args have been dealt with, otherwise error out.
|
143
|
-
|
148
|
+
raise(ArgumentError.new("Received wrong number of arguments. #{args.inspect}")) unless args.empty?
|
144
149
|
|
145
150
|
yield options if block_given?
|
146
151
|
end
|
@@ -169,23 +174,54 @@ module OmniAuth
|
|
169
174
|
# the request path is recognized.
|
170
175
|
#
|
171
176
|
# @param env [Hash] The Rack environment.
|
172
|
-
def call!(env) # rubocop:disable CyclomaticComplexity
|
177
|
+
def call!(env) # rubocop:disable CyclomaticComplexity, PerceivedComplexity
|
173
178
|
unless env['rack.session']
|
174
179
|
error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.')
|
175
|
-
|
180
|
+
raise(error)
|
176
181
|
end
|
177
182
|
|
178
183
|
@env = env
|
184
|
+
|
185
|
+
warn_if_using_get_on_request_path
|
186
|
+
|
179
187
|
@env['omniauth.strategy'] = self if on_auth_path?
|
180
188
|
|
181
189
|
return mock_call!(env) if OmniAuth.config.test_mode
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
190
|
+
|
191
|
+
begin
|
192
|
+
return options_call if on_auth_path? && options_request?
|
193
|
+
return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
|
194
|
+
return callback_call if on_callback_path?
|
195
|
+
return other_phase if respond_to?(:other_phase)
|
196
|
+
rescue StandardError => e
|
197
|
+
raise e if env.delete('omniauth.error.app')
|
198
|
+
|
199
|
+
return fail!(e.message, e)
|
200
|
+
end
|
201
|
+
|
186
202
|
@app.call(env)
|
187
203
|
end
|
188
204
|
|
205
|
+
def warn_if_using_get_on_request_path
|
206
|
+
return unless on_request_path?
|
207
|
+
return unless OmniAuth.config.allowed_request_methods.include?(:get)
|
208
|
+
return if OmniAuth.config.silence_get_warning
|
209
|
+
|
210
|
+
log :warn, <<-WARN
|
211
|
+
You are using GET as an allowed request method for OmniAuth. This may leave
|
212
|
+
you open to CSRF attacks. As of v2.0.0, OmniAuth by default allows only POST
|
213
|
+
to its own routes. You should review the following resources to guide your
|
214
|
+
mitigation:
|
215
|
+
https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284
|
216
|
+
https://github.com/omniauth/omniauth/issues/960
|
217
|
+
https://nvd.nist.gov/vuln/detail/CVE-2015-9284
|
218
|
+
https://github.com/omniauth/omniauth/pull/809
|
219
|
+
|
220
|
+
You can ignore this warning by setting:
|
221
|
+
OmniAuth.config.silence_get_warning = true
|
222
|
+
WARN
|
223
|
+
end
|
224
|
+
|
189
225
|
# Responds to an OPTIONS request.
|
190
226
|
def options_call
|
191
227
|
OmniAuth.config.before_options_phase.call(env) if OmniAuth.config.before_options_phase
|
@@ -194,32 +230,41 @@ module OmniAuth
|
|
194
230
|
end
|
195
231
|
|
196
232
|
# Performs the steps necessary to run the request phase of a strategy.
|
197
|
-
def request_call # rubocop:disable CyclomaticComplexity, MethodLength
|
233
|
+
def request_call # rubocop:disable CyclomaticComplexity, MethodLength, PerceivedComplexity
|
198
234
|
setup_phase
|
199
|
-
log :
|
235
|
+
log :debug, 'Request phase initiated.'
|
236
|
+
|
200
237
|
# store query params from the request url, extracted in the callback_phase
|
201
|
-
session['omniauth.params'] = request.
|
238
|
+
session['omniauth.params'] = request.GET
|
239
|
+
|
240
|
+
OmniAuth.config.request_validation_phase.call(env) if OmniAuth.config.request_validation_phase
|
202
241
|
OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase
|
242
|
+
|
203
243
|
if options.form.respond_to?(:call)
|
204
|
-
log :
|
244
|
+
log :debug, 'Rendering form from supplied Rack endpoint.'
|
205
245
|
options.form.call(env)
|
206
246
|
elsif options.form
|
207
|
-
log :
|
247
|
+
log :debug, 'Rendering form from underlying application.'
|
208
248
|
call_app!
|
249
|
+
elsif !options.origin_param
|
250
|
+
request_phase
|
209
251
|
else
|
210
|
-
if request.params[
|
211
|
-
env['rack.session']['omniauth.origin'] = request.params[
|
252
|
+
if request.params[options.origin_param]
|
253
|
+
env['rack.session']['omniauth.origin'] = request.params[options.origin_param]
|
212
254
|
elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/)
|
213
255
|
env['rack.session']['omniauth.origin'] = env['HTTP_REFERER']
|
214
256
|
end
|
257
|
+
|
215
258
|
request_phase
|
216
259
|
end
|
260
|
+
rescue OmniAuth::AuthenticityError => e
|
261
|
+
fail!(:authenticity_error, e)
|
217
262
|
end
|
218
263
|
|
219
264
|
# Performs the steps necessary to run the callback phase of a strategy.
|
220
265
|
def callback_call
|
221
266
|
setup_phase
|
222
|
-
log :
|
267
|
+
log :debug, 'Callback phase initiated.'
|
223
268
|
@env['omniauth.origin'] = session.delete('omniauth.origin')
|
224
269
|
@env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
|
225
270
|
@env['omniauth.params'] = session.delete('omniauth.params') || {}
|
@@ -234,8 +279,8 @@ module OmniAuth
|
|
234
279
|
end
|
235
280
|
|
236
281
|
def on_request_path?
|
237
|
-
if options
|
238
|
-
options
|
282
|
+
if options[:request_path].respond_to?(:call)
|
283
|
+
options[:request_path].call(env)
|
239
284
|
else
|
240
285
|
on_path?(request_path)
|
241
286
|
end
|
@@ -246,7 +291,7 @@ module OmniAuth
|
|
246
291
|
end
|
247
292
|
|
248
293
|
def on_path?(path)
|
249
|
-
current_path.casecmp(path)
|
294
|
+
current_path.casecmp(path).zero?
|
250
295
|
end
|
251
296
|
|
252
297
|
def options_request?
|
@@ -257,20 +302,32 @@ module OmniAuth
|
|
257
302
|
# in the event that OmniAuth has been configured to be
|
258
303
|
# in test mode.
|
259
304
|
def mock_call!(*)
|
260
|
-
|
261
|
-
|
305
|
+
begin
|
306
|
+
return mock_request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
|
307
|
+
return mock_callback_call if on_callback_path?
|
308
|
+
rescue StandardError => e
|
309
|
+
raise e if env.delete('omniauth.error.app')
|
310
|
+
|
311
|
+
return fail!(e.message, e)
|
312
|
+
end
|
313
|
+
|
262
314
|
call_app!
|
263
315
|
end
|
264
316
|
|
265
317
|
def mock_request_call
|
266
318
|
setup_phase
|
267
319
|
|
268
|
-
session['omniauth.params'] = request.
|
320
|
+
session['omniauth.params'] = request.GET
|
321
|
+
|
322
|
+
OmniAuth.config.request_validation_phase.call(env) if OmniAuth.config.request_validation_phase
|
269
323
|
OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
324
|
+
|
325
|
+
if options.origin_param
|
326
|
+
if request.params[options.origin_param]
|
327
|
+
session['omniauth.origin'] = request.params[options.origin_param]
|
328
|
+
elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/)
|
329
|
+
session['omniauth.origin'] = env['HTTP_REFERER']
|
330
|
+
end
|
274
331
|
end
|
275
332
|
|
276
333
|
redirect(callback_url)
|
@@ -278,14 +335,15 @@ module OmniAuth
|
|
278
335
|
|
279
336
|
def mock_callback_call
|
280
337
|
setup_phase
|
338
|
+
@env['omniauth.origin'] = session.delete('omniauth.origin')
|
339
|
+
@env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
|
340
|
+
@env['omniauth.params'] = session.delete('omniauth.params') || {}
|
341
|
+
|
281
342
|
mocked_auth = OmniAuth.mock_auth_for(name.to_s)
|
282
343
|
if mocked_auth.is_a?(Symbol)
|
283
344
|
fail!(mocked_auth)
|
284
345
|
else
|
285
346
|
@env['omniauth.auth'] = mocked_auth
|
286
|
-
@env['omniauth.params'] = session.delete('omniauth.params') || {}
|
287
|
-
@env['omniauth.origin'] = session.delete('omniauth.origin')
|
288
|
-
@env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
|
289
347
|
OmniAuth.config.before_callback_phase.call(@env) if OmniAuth.config.before_callback_phase
|
290
348
|
call_app!
|
291
349
|
end
|
@@ -297,10 +355,10 @@ module OmniAuth
|
|
297
355
|
# underlying application. This will default to `/auth/:provider/setup`.
|
298
356
|
def setup_phase
|
299
357
|
if options[:setup].respond_to?(:call)
|
300
|
-
log :
|
358
|
+
log :debug, 'Setup endpoint detected, running now.'
|
301
359
|
options[:setup].call(env)
|
302
|
-
elsif options
|
303
|
-
log :
|
360
|
+
elsif options[:setup]
|
361
|
+
log :debug, 'Calling through to underlying application for setup.'
|
304
362
|
setup_env = env.merge('PATH_INFO' => setup_path, 'REQUEST_METHOD' => 'GET')
|
305
363
|
call_app!(setup_env)
|
306
364
|
end
|
@@ -310,7 +368,7 @@ module OmniAuth
|
|
310
368
|
# perform any information gathering you need to be able to authenticate
|
311
369
|
# the user in this phase.
|
312
370
|
def request_phase
|
313
|
-
|
371
|
+
raise(NotImplementedError)
|
314
372
|
end
|
315
373
|
|
316
374
|
def uid
|
@@ -330,11 +388,13 @@ module OmniAuth
|
|
330
388
|
end
|
331
389
|
|
332
390
|
def auth_hash
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
391
|
+
credentials_data = credentials
|
392
|
+
extra_data = extra
|
393
|
+
AuthHash.new(:provider => name, :uid => uid).tap do |auth|
|
394
|
+
auth.info = info unless skip_info?
|
395
|
+
auth.credentials = credentials_data if credentials_data
|
396
|
+
auth.extra = extra_data if extra_data
|
397
|
+
end
|
338
398
|
end
|
339
399
|
|
340
400
|
# Determines whether or not user info should be retrieved. This
|
@@ -347,14 +407,10 @@ module OmniAuth
|
|
347
407
|
#
|
348
408
|
# use MyStrategy, :skip_info => lambda{|uid| User.find_by_uid(uid)}
|
349
409
|
def skip_info?
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
return true
|
355
|
-
end
|
356
|
-
end
|
357
|
-
false
|
410
|
+
return false unless options.skip_info?
|
411
|
+
return true unless options.skip_info.respond_to?(:call)
|
412
|
+
|
413
|
+
options.skip_info.call(uid)
|
358
414
|
end
|
359
415
|
|
360
416
|
def callback_phase
|
@@ -370,6 +426,7 @@ module OmniAuth
|
|
370
426
|
if options[kind].respond_to?(:call)
|
371
427
|
result = options[kind].call(env)
|
372
428
|
return nil unless result.is_a?(String)
|
429
|
+
|
373
430
|
result
|
374
431
|
else
|
375
432
|
options[kind]
|
@@ -377,23 +434,32 @@ module OmniAuth
|
|
377
434
|
end
|
378
435
|
|
379
436
|
def request_path
|
380
|
-
|
437
|
+
@request_path ||=
|
438
|
+
if options[:request_path].is_a?(String)
|
439
|
+
options[:request_path]
|
440
|
+
else
|
441
|
+
"#{script_name}#{path_prefix}/#{name}"
|
442
|
+
end
|
381
443
|
end
|
382
444
|
|
383
445
|
def callback_path
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
446
|
+
@callback_path ||= begin
|
447
|
+
path = options[:callback_path] if options[:callback_path].is_a?(String)
|
448
|
+
path ||= current_path if options[:callback_path].respond_to?(:call) && options[:callback_path].call(env)
|
449
|
+
path ||= custom_path(:request_path)
|
450
|
+
path ||= "#{script_name}#{path_prefix}/#{name}/callback"
|
451
|
+
path
|
452
|
+
end
|
389
453
|
end
|
390
454
|
|
391
455
|
def setup_path
|
392
456
|
options[:setup_path] || "#{path_prefix}/#{name}/setup"
|
393
457
|
end
|
394
458
|
|
459
|
+
CURRENT_PATH_REGEX = %r{/$}.freeze
|
460
|
+
EMPTY_STRING = ''.freeze
|
395
461
|
def current_path
|
396
|
-
request.
|
462
|
+
@current_path ||= request.path.downcase.sub(CURRENT_PATH_REGEX, EMPTY_STRING)
|
397
463
|
end
|
398
464
|
|
399
465
|
def query_string
|
@@ -402,6 +468,9 @@ module OmniAuth
|
|
402
468
|
|
403
469
|
def call_app!(env = @env)
|
404
470
|
@app.call(env)
|
471
|
+
rescue StandardError => e
|
472
|
+
env['omniauth.error.app'] = true
|
473
|
+
raise e
|
405
474
|
end
|
406
475
|
|
407
476
|
def full_host
|
@@ -425,7 +494,7 @@ module OmniAuth
|
|
425
494
|
end
|
426
495
|
|
427
496
|
def callback_url
|
428
|
-
full_host +
|
497
|
+
full_host + callback_path + query_string
|
429
498
|
end
|
430
499
|
|
431
500
|
def script_name
|
@@ -441,7 +510,7 @@ module OmniAuth
|
|
441
510
|
end
|
442
511
|
|
443
512
|
def name
|
444
|
-
options
|
513
|
+
options[:name]
|
445
514
|
end
|
446
515
|
|
447
516
|
def redirect(uri)
|
@@ -475,10 +544,15 @@ module OmniAuth
|
|
475
544
|
OmniAuth.config.on_failure.call(env)
|
476
545
|
end
|
477
546
|
|
478
|
-
class Options <
|
547
|
+
class Options < OmniAuth::KeyStore; end
|
479
548
|
|
480
549
|
protected
|
481
550
|
|
551
|
+
def initialize_copy(*args)
|
552
|
+
super
|
553
|
+
@options = @options.dup
|
554
|
+
end
|
555
|
+
|
482
556
|
def merge_stack(stack)
|
483
557
|
stack.inject({}) do |a, e|
|
484
558
|
a.merge!(e)
|
@@ -488,10 +562,10 @@ module OmniAuth
|
|
488
562
|
|
489
563
|
def ssl?
|
490
564
|
request.env['HTTPS'] == 'on' ||
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
565
|
+
request.env['HTTP_X_FORWARDED_SSL'] == 'on' ||
|
566
|
+
request.env['HTTP_X_FORWARDED_SCHEME'] == 'https' ||
|
567
|
+
(request.env['HTTP_X_FORWARDED_PROTO'] && request.env['HTTP_X_FORWARDED_PROTO'].split(',')[0] == 'https') ||
|
568
|
+
request.env['rack.url_scheme'] == 'https'
|
495
569
|
end
|
496
570
|
end
|
497
571
|
end
|
@@ -10,7 +10,7 @@ module OmniAuth
|
|
10
10
|
# include OmniAuth::Test::StrategyTestCase
|
11
11
|
# def strategy
|
12
12
|
# # return the parameters to a Rack::Builder map call:
|
13
|
-
# [MyStrategy
|
13
|
+
# [MyStrategy, :some, :configuration, :options => 'here']
|
14
14
|
# end
|
15
15
|
# setup do
|
16
16
|
# post '/auth/my_strategy/callback', :user => { 'name' => 'Dylan', 'id' => '445' }
|
@@ -37,7 +37,7 @@ module OmniAuth
|
|
37
37
|
|
38
38
|
def strategy
|
39
39
|
error = NotImplementedError.new('Including specs must define #strategy')
|
40
|
-
|
40
|
+
raise(error)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
end
|