omniauth 2.1.3 → 2.2.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.
@@ -1,116 +1,30 @@
1
1
  require 'omniauth/key_store'
2
+ require 'omniauth/strategy/class_methods'
3
+ require 'omniauth/strategy/fetchers'
4
+ require 'omniauth/strategy/hosts'
5
+ require 'omniauth/strategy/paths'
6
+ require 'omniauth/strategy/test_mode'
2
7
 
3
8
  module OmniAuth
4
9
  class NoSessionError < StandardError; end
10
+
5
11
  # The Strategy is the base unit of OmniAuth's ability to
6
12
  # wrangle multiple providers. Each strategy provided by
7
13
  # OmniAuth includes this mixin to gain the default functionality
8
14
  # necessary to be compatible with the OmniAuth library.
9
- module Strategy # rubocop:disable ModuleLength
15
+ module Strategy # rubocop:disable Metrics/ModuleLength
16
+ include Fetchers
17
+ include Hosts
18
+ include Paths
19
+ include TestMode
20
+
10
21
  def self.included(base)
11
22
  OmniAuth.strategies << base
12
23
 
13
24
  base.extend ClassMethods
14
- base.class_eval do
15
- option :setup, false
16
- option :skip_info, false
17
- option :origin_param, 'origin'
18
- end
19
- end
20
-
21
- module ClassMethods
22
- # Returns an inherited set of default options set at the class-level
23
- # for each strategy.
24
- def default_options
25
- # existing = superclass.default_options if superclass.respond_to?(:default_options)
26
- existing = superclass.respond_to?(:default_options) ? superclass.default_options : {}
27
- @default_options ||= OmniAuth::Strategy::Options.new(existing)
28
- end
29
-
30
- # This allows for more declarative subclassing of strategies by allowing
31
- # default options to be set using a simple configure call.
32
- #
33
- # @param options [Hash] If supplied, these will be the default options (deep-merged into the superclass's default options).
34
- # @yield [Options] The options Mash that allows you to set your defaults as you'd like.
35
- #
36
- # @example Using a yield to configure the default options.
37
- #
38
- # class MyStrategy
39
- # include OmniAuth::Strategy
40
- #
41
- # configure do |c|
42
- # c.foo = 'bar'
43
- # end
44
- # end
45
- #
46
- # @example Using a hash to configure the default options.
47
- #
48
- # class MyStrategy
49
- # include OmniAuth::Strategy
50
- # configure foo: 'bar'
51
- # end
52
- def configure(options = nil)
53
- if block_given?
54
- yield default_options
55
- else
56
- default_options.deep_merge!(options)
57
- end
58
- end
59
-
60
- # Directly declare a default option for your class. This is a useful from
61
- # a documentation perspective as it provides a simple line-by-line analysis
62
- # of the kinds of options your strategy provides by default.
63
- #
64
- # @param name [Symbol] The key of the default option in your configuration hash.
65
- # @param value [Object] The value your object defaults to. Nil if not provided.
66
- #
67
- # @example
68
- #
69
- # class MyStrategy
70
- # include OmniAuth::Strategy
71
- #
72
- # option :foo, 'bar'
73
- # option
74
- # end
75
- def option(name, value = nil)
76
- default_options[name] = value
77
- end
78
-
79
- # Sets (and retrieves) option key names for initializer arguments to be
80
- # recorded as. This takes care of 90% of the use cases for overriding
81
- # the initializer in OmniAuth Strategies.
82
- def args(args = nil)
83
- if args
84
- @args = Array(args)
85
- return
86
- end
87
- existing = superclass.respond_to?(:args) ? superclass.args : []
88
- (instance_variable_defined?(:@args) && @args) || existing
89
- end
90
-
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
-
96
- def #{fetcher}(&block)
97
- return #{fetcher}_proc unless block_given?
98
- @#{fetcher}_proc = block
99
- end
100
-
101
- def #{fetcher}_stack(context)
102
- compile_stack(self.ancestors, :#{fetcher}, context)
103
- end
104
- RUBY
105
- end
106
-
107
- def compile_stack(ancestors, method, context)
108
- stack = ancestors.inject([]) do |a, ancestor|
109
- a << context.instance_eval(&ancestor.send(method)) if ancestor.respond_to?(method) && ancestor.send(method)
110
- a
111
- end
112
- stack.reverse!
113
- end
25
+ base.option :setup, false
26
+ base.option :skip_info, false
27
+ base.option :origin_param, 'origin'
114
28
  end
115
29
 
116
30
  attr_reader :app, :env, :options, :response
@@ -130,7 +44,7 @@ module OmniAuth
130
44
  # will be passed through and set to the appropriate values.
131
45
  #
132
46
  # @yield [Options] Yields options to block for further configuration.
133
- def initialize(app, *args, &block) # rubocop:disable UnusedMethodArgument
47
+ def initialize(app, *args)
134
48
  @app = app
135
49
  @env = nil
136
50
  @options = self.class.default_options.dup
@@ -145,7 +59,7 @@ module OmniAuth
145
59
  end
146
60
 
147
61
  # Make sure that all of the args have been dealt with, otherwise error out.
148
- raise(ArgumentError.new("Received wrong number of arguments. #{args.inspect}")) unless args.empty?
62
+ raise(ArgumentError.new("Received wrong number of arguments. #{args}")) unless args.empty?
149
63
 
150
64
  yield options if block_given?
151
65
  end
@@ -160,12 +74,15 @@ module OmniAuth
160
74
  # @example
161
75
  # log :warn, "This is a warning."
162
76
  def log(level, message)
163
- OmniAuth.logger.send(level, "(#{name}) #{message}")
77
+ OmniAuth.logger.public_send(level, "(#{name}) #{message}")
164
78
  end
165
79
 
166
- # Duplicates this instance and runs #call! on it.
80
+ # Duplicates this instance and runs #call! on it. A request that can't be
81
+ # the strategy's goes straight to the app instead, skipping the copy.
167
82
  # @param [Hash] The Rack environment.
168
83
  def call(env)
84
+ return @app.call(env) if passthrough?(env)
85
+
169
86
  dup.call!(env)
170
87
  end
171
88
 
@@ -174,9 +91,9 @@ module OmniAuth
174
91
  # the request path is recognized.
175
92
  #
176
93
  # @param env [Hash] The Rack environment.
177
- def call!(env) # rubocop:disable CyclomaticComplexity, PerceivedComplexity
94
+ def call!(env)
178
95
  unless env['rack.session']
179
- error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.')
96
+ error = NoSessionError.new('You must provide a session to use OmniAuth.')
180
97
  raise(error)
181
98
  end
182
99
 
@@ -184,22 +101,37 @@ module OmniAuth
184
101
 
185
102
  warn_if_using_get_on_request_path
186
103
 
187
- @env['omniauth.strategy'] = self if on_auth_path?
104
+ env['omniauth.strategy'] = self if on_auth_path?
188
105
 
189
106
  return mock_call!(env) if OmniAuth.config.test_mode
190
107
 
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')
108
+ phase_call || @app.call(env)
109
+ end
198
110
 
199
- return fail!(e.message, e)
111
+ # Runs the phase that matches the current request, or returns nil
112
+ # if the request isn't for this strategy.
113
+ def phase_call
114
+ if options_call?
115
+ options_call
116
+ elsif request_call?
117
+ request_call
118
+ elsif on_callback_path?
119
+ callback_call
120
+ elsif respond_to?(:other_phase)
121
+ other_phase
200
122
  end
123
+ rescue StandardError => e
124
+ handle_phase_error(e)
125
+ end
126
+
127
+ # True for an OPTIONS request to the request or callback path.
128
+ def options_call?
129
+ on_auth_path? && options_request?
130
+ end
201
131
 
202
- @app.call(env)
132
+ # True for a request to the request path with an allowed method.
133
+ def request_call?
134
+ on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
203
135
  end
204
136
 
205
137
  def warn_if_using_get_on_request_path
@@ -224,131 +156,79 @@ module OmniAuth
224
156
 
225
157
  # Responds to an OPTIONS request.
226
158
  def options_call
227
- OmniAuth.config.before_options_phase.call(env) if OmniAuth.config.before_options_phase
228
- verbs = OmniAuth.config.allowed_request_methods.collect(&:to_s).collect(&:upcase).join(', ')
159
+ run_hook(:before_options_phase)
160
+ verbs = OmniAuth.config.allowed_request_methods.collect(&:upcase).join(', ')
229
161
  [200, {'Allow' => verbs}, []]
230
162
  end
231
163
 
232
164
  # Performs the steps necessary to run the request phase of a strategy.
233
- def request_call # rubocop:disable CyclomaticComplexity, MethodLength, PerceivedComplexity
165
+ def request_call
234
166
  setup_phase
235
167
  log :debug, 'Request phase initiated.'
168
+ warn_if_using_request_host
169
+ return invalid_host! unless allowed_host?
236
170
 
237
- # store query params from the request url, extracted in the callback_phase
238
- session['omniauth.params'] = request.GET
239
-
240
- OmniAuth.config.request_validation_phase.call(env) if OmniAuth.config.request_validation_phase
241
- OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase
171
+ run_hook(:request_validation_phase)
172
+ session['omniauth.params'] = omniauth_params
173
+ run_hook(:before_request_phase)
174
+ request_response.tap { run_hook(:after_request_phase) }
175
+ rescue OmniAuth::AuthenticityError => e
176
+ fail!(:authenticity_error, e)
177
+ end
242
178
 
179
+ # Renders the login form (from a Rack endpoint or the app itself) if
180
+ # one is configured, or else runs the strategy's request phase.
181
+ def request_response
243
182
  if options.form.respond_to?(:call)
244
183
  log :debug, 'Rendering form from supplied Rack endpoint.'
245
184
  options.form.call(env)
246
185
  elsif options.form
247
186
  log :debug, 'Rendering form from underlying application.'
248
187
  call_app!
249
- elsif !options.origin_param
250
- request_phase
251
188
  else
252
- if request.params[options.origin_param]
253
- env['rack.session']['omniauth.origin'] = request.params[options.origin_param]
254
- elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/)
255
- env['rack.session']['omniauth.origin'] = env['HTTP_REFERER']
256
- end
257
-
189
+ store_origin if options.origin_param
258
190
  request_phase
259
191
  end
260
- rescue OmniAuth::AuthenticityError => e
261
- fail!(:authenticity_error, e)
262
- end
263
-
264
- # Performs the steps necessary to run the callback phase of a strategy.
265
- def callback_call
266
- setup_phase
267
- log :debug, 'Callback phase initiated.'
268
- @env['omniauth.origin'] = session.delete('omniauth.origin')
269
- @env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
270
- @env['omniauth.params'] = session.delete('omniauth.params') || {}
271
- OmniAuth.config.before_callback_phase.call(@env) if OmniAuth.config.before_callback_phase
272
- callback_phase
273
- end
274
-
275
- # Returns true if the environment recognizes either the
276
- # request or callback path.
277
- def on_auth_path?
278
- on_request_path? || on_callback_path?
279
- end
280
-
281
- def on_request_path?
282
- if options[:request_path].respond_to?(:call)
283
- options[:request_path].call(env)
284
- else
285
- on_path?(request_path)
286
- end
287
192
  end
288
193
 
289
- def on_callback_path?
290
- on_path?(callback_path)
291
- end
194
+ # The authenticity token never goes into omniauth.params, so the app
195
+ # can't leak it by echoing the params back.
196
+ AUTHENTICITY_PARAM = 'authenticity_token'.freeze
292
197
 
293
- def on_path?(path)
294
- current_path.casecmp(path).zero?
198
+ # The params the app sent to the request phase, from both the query
199
+ # string and the form, which the callback phase hands back as
200
+ # env['omniauth.params'].
201
+ def omniauth_params
202
+ request.params.reject { |key, _| key.eql?(AUTHENTICITY_PARAM) }
295
203
  end
296
204
 
297
- def options_request?
298
- request.request_method == 'OPTIONS'
299
- end
300
-
301
- # This is called in lieu of the normal request process
302
- # in the event that OmniAuth has been configured to be
303
- # in test mode.
304
- def mock_call!(*)
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)
205
+ # Remembers where the user came from (the origin param, or else the
206
+ # referer) so the callback phase can send them back there.
207
+ def store_origin
208
+ origin = request.params[options.origin_param]
209
+ referer = env['HTTP_REFERER']
210
+ if origin
211
+ session['omniauth.origin'] = origin
212
+ elsif referer && !referer.match?(/#{request_path}$/)
213
+ session['omniauth.origin'] = referer
312
214
  end
313
-
314
- call_app!
315
215
  end
316
216
 
317
- def mock_request_call
318
- setup_phase
319
-
320
- session['omniauth.params'] = request.GET
321
-
322
- OmniAuth.config.request_validation_phase.call(env) if OmniAuth.config.request_validation_phase
323
- OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase
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
331
- end
332
-
333
- redirect(callback_url)
334
- end
335
-
336
- def mock_callback_call
217
+ # Performs the steps necessary to run the callback phase of a strategy.
218
+ def callback_call
337
219
  setup_phase
220
+ log :debug, 'Callback phase initiated.'
221
+ return invalid_host! unless allowed_host?
338
222
 
339
223
  origin = session.delete('omniauth.origin')
340
- @env['omniauth.origin'] ||= origin
341
- @env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
342
- @env['omniauth.params'] = session.delete('omniauth.params') || {}
224
+ env['omniauth.origin'] = (origin unless origin.eql?(''))
225
+ env['omniauth.params'] = session.delete('omniauth.params') || {}
226
+ run_hook(:before_callback_phase)
227
+ callback_phase
228
+ end
343
229
 
344
- mocked_auth = OmniAuth.mock_auth_for(name.to_s)
345
- if mocked_auth.is_a?(Symbol)
346
- fail!(mocked_auth)
347
- else
348
- @env['omniauth.auth'] = mocked_auth
349
- OmniAuth.config.before_callback_phase.call(@env) if OmniAuth.config.before_callback_phase
350
- call_app!
351
- end
230
+ def options_request?
231
+ request.request_method.eql?('OPTIONS')
352
232
  end
353
233
 
354
234
  # The setup phase looks for the `:setup` option to exist and,
@@ -356,10 +236,11 @@ module OmniAuth
356
236
  # `:setup` option or it will call out to the setup path of the
357
237
  # underlying application. This will default to `/auth/:provider/setup`.
358
238
  def setup_phase
359
- if options[:setup].respond_to?(:call)
239
+ setup = options[:setup]
240
+ if setup.respond_to?(:call)
360
241
  log :debug, 'Setup endpoint detected, running now.'
361
- options[:setup].call(env)
362
- elsif options[:setup]
242
+ setup.call(env)
243
+ elsif setup
363
244
  log :debug, 'Calling through to underlying application for setup.'
364
245
  setup_env = env.merge('PATH_INFO' => setup_path, 'REQUEST_METHOD' => 'GET')
365
246
  call_app!(setup_env)
@@ -373,147 +254,28 @@ module OmniAuth
373
254
  raise(NotImplementedError)
374
255
  end
375
256
 
376
- def uid
377
- self.class.uid_stack(self).last
378
- end
379
-
380
- def info
381
- merge_stack(self.class.info_stack(self))
382
- end
383
-
384
- def credentials
385
- merge_stack(self.class.credentials_stack(self))
386
- end
387
-
388
- def extra
389
- merge_stack(self.class.extra_stack(self))
390
- end
391
-
392
- def auth_hash
393
- credentials_data = credentials
394
- extra_data = extra
395
- AuthHash.new(:provider => name, :uid => uid).tap do |auth|
396
- auth.info = info unless skip_info?
397
- auth.credentials = credentials_data if credentials_data
398
- auth.extra = extra_data if extra_data
399
- end
400
- end
401
-
402
- # Determines whether or not user info should be retrieved. This
403
- # allows some strategies to save a call to an external API service
404
- # for existing users. You can use it either by setting the `:skip_info`
405
- # to true or by setting `:skip_info` to a Proc that takes a uid and
406
- # evaluates to true when you would like to skip info.
407
- #
408
- # @example
409
- #
410
- # use MyStrategy, :skip_info => lambda{|uid| User.find_by_uid(uid)}
411
- def skip_info?
412
- return false unless options.skip_info?
413
- return true unless options.skip_info.respond_to?(:call)
414
-
415
- options.skip_info.call(uid)
416
- end
417
-
418
257
  def callback_phase
419
258
  env['omniauth.auth'] = auth_hash
420
259
  call_app!
421
260
  end
422
261
 
423
- def path_prefix
424
- options[:path_prefix] || OmniAuth.config.path_prefix
425
- end
426
-
427
- def custom_path(kind)
428
- if options[kind].respond_to?(:call)
429
- result = options[kind].call(env)
430
- return nil unless result.is_a?(String)
431
-
432
- result
433
- else
434
- options[kind]
435
- end
436
- end
437
-
438
- def request_path
439
- @request_path ||=
440
- if options[:request_path].is_a?(String)
441
- options[:request_path]
442
- else
443
- "#{script_name}#{path_prefix}/#{name}"
444
- end
445
- end
446
-
447
- def callback_path
448
- @callback_path ||= begin
449
- path = options[:callback_path] if options[:callback_path].is_a?(String)
450
- path ||= current_path if options[:callback_path].respond_to?(:call) && options[:callback_path].call(env)
451
- path ||= custom_path(:request_path)
452
- path ||= "#{script_name}#{path_prefix}/#{name}/callback"
453
- path
454
- end
455
- end
456
-
457
- def setup_path
458
- options[:setup_path] || "#{path_prefix}/#{name}/setup"
459
- end
460
-
461
- CURRENT_PATH_REGEX = %r{/$}.freeze
462
- EMPTY_STRING = ''.freeze
463
- def current_path
464
- @current_path ||= request.path.downcase.sub(CURRENT_PATH_REGEX, EMPTY_STRING)
465
- end
466
-
467
- def query_string
468
- request.query_string.empty? ? '' : "?#{request.query_string}"
469
- end
470
-
471
- def call_app!(env = @env)
472
- @app.call(env)
473
- rescue StandardError => e
474
- env['omniauth.error.app'] = true
475
- raise e
476
- end
477
-
478
- def full_host
479
- case OmniAuth.config.full_host
480
- when String
481
- OmniAuth.config.full_host
482
- when Proc
483
- OmniAuth.config.full_host.call(env)
484
- else
485
- # in Rack 1.3.x, request.url explodes if scheme is nil
486
- if request.scheme && URI.parse(request.url).absolute?
487
- uri = URI.parse(request.url.gsub(/\?.*$/, ''))
488
- uri.path = ''
489
- # sometimes the url is actually showing http inside rails because the
490
- # other layers (like nginx) have handled the ssl termination.
491
- uri.scheme = 'https' if ssl? # rubocop:disable BlockNesting
492
- uri.to_s
493
- else ''
494
- end
495
- end
496
- end
497
-
498
- def callback_url
499
- full_host + callback_path + query_string
500
- end
501
-
502
- def script_name
503
- return '' if @env.nil?
504
- @env['SCRIPT_NAME'] || ''
262
+ def call_app!(app_env = env)
263
+ @app.call(app_env)
264
+ rescue StandardError
265
+ app_env['omniauth.error.app'] = true
266
+ raise
505
267
  end
506
268
 
507
269
  def session
508
- @env['rack.session']
270
+ env['rack.session']
509
271
  end
510
272
 
511
273
  def request
512
- @request ||= Rack::Request.new(@env)
274
+ @request ||= Rack::Request.new(env)
513
275
  end
514
276
 
515
277
  def name
516
- options[:name]
278
+ options.fetch(:name)
517
279
  end
518
280
 
519
281
  def redirect(uri)
@@ -551,24 +313,53 @@ module OmniAuth
551
313
 
552
314
  protected
553
315
 
316
+ # Re-raises errors from the downstream app; reports anything else
317
+ # raised during a phase as an authentication failure.
318
+ def handle_phase_error(error)
319
+ raise error if env.delete('omniauth.error.app')
320
+
321
+ fail!(error.message, error)
322
+ end
323
+
324
+ # Calls the named OmniAuth.config hook (such as :before_request_phase)
325
+ # with the Rack env. A hook set to nil or false is skipped.
326
+ def run_hook(name)
327
+ hook = OmniAuth.config.public_send(name)
328
+ return unless hook # not hook&.call: a hook can be set to false
329
+
330
+ hook.call(env)
331
+ end
332
+
554
333
  def initialize_copy(*args)
555
334
  super
556
335
  @options = @options.dup
557
336
  end
558
337
 
559
- def merge_stack(stack)
560
- stack.inject({}) do |a, e|
561
- a.merge!(e)
562
- a
563
- end
338
+ # True when #call! would only hand env to the app: there's a session, the
339
+ # path alone decides, and env isn't on the strategy's paths. The
340
+ # strategy's own path methods check, on a copy that shares its options.
341
+ def passthrough?(env)
342
+ return false unless env['rack.session'] && dispatch_by_path?
343
+ return false if path_probe(env).on_auth_path?
344
+
345
+ true
346
+ end
347
+
348
+ # True when OmniAuth's own dispatch runs, with no test mode or
349
+ # other_phase, and no path lambdas, which would otherwise run twice on
350
+ # the strategy's own paths.
351
+ def dispatch_by_path?
352
+ self.class.default_dispatch? && !OmniAuth.config.test_mode && !respond_to?(:other_phase) &&
353
+ !options[:request_path].respond_to?(:call) && !options[:callback_path].respond_to?(:call)
564
354
  end
565
355
 
566
- def ssl?
567
- request.env['HTTPS'] == 'on' ||
568
- request.env['HTTP_X_FORWARDED_SSL'] == 'on' ||
569
- request.env['HTTP_X_FORWARDED_SCHEME'] == 'https' ||
570
- (request.env['HTTP_X_FORWARDED_PROTO'] && request.env['HTTP_X_FORWARDED_PROTO'].split(',')[0] == 'https') ||
571
- request.env['rack.url_scheme'] == 'https'
356
+ # A copy like #dup makes, but sharing this instance's options, so the
357
+ # path methods can memoize on it instead of on this shared instance.
358
+ def path_probe(env)
359
+ probe = self.class.allocate
360
+ instance_variables.each { |ivar| probe.instance_variable_set(ivar, instance_variable_get(ivar)) }
361
+ probe.instance_variable_set(:@env, env)
362
+ probe
572
363
  end
573
364
  end
574
365
  end
@@ -6,7 +6,7 @@ module OmniAuth
6
6
  end
7
7
 
8
8
  def call(env)
9
- @session ||= (env['rack.session'] || {})
9
+ @session ||= env['rack.session'] || {}
10
10
  env['rack.session'] = @session
11
11
  @app.call(env)
12
12
  end
@@ -18,18 +18,17 @@ module OmniAuth
18
18
  # end
19
19
  module StrategyTestCase
20
20
  def app
21
- strat = strategy
22
21
  resp = app_response
23
- Rack::Builder.new do
24
- use(OmniAuth::Test::PhonySession)
25
- use(*strat)
26
- run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [resp || env.key?('omniauth.auth').to_s]] }
27
- end.to_app
22
+ builder = Rack::Builder.new
23
+ builder.use(PhonySession)
24
+ builder.use(*strategy)
25
+ # @type var endpoint: ^(Rack::env) -> Rack::response
26
+ endpoint = lambda { |env| [404, {'Content-Type' => 'text/plain'}, [resp || env.key?('omniauth.auth').to_s]] }
27
+ builder.run(endpoint)
28
+ builder.to_app
28
29
  end
29
30
 
30
- def app_response
31
- nil
32
- end
31
+ def app_response; end
33
32
 
34
33
  def session
35
34
  last_request.env['rack.session']
@@ -1,3 +1,3 @@
1
1
  module OmniAuth
2
- VERSION = '2.1.3'.freeze
2
+ VERSION = '2.2.0'.freeze
3
3
  end