Module: OmniAuth::Strategy
Overview
The Strategy is the base unit of OmniAuth's ability to
wrangle multiple providers. Each strategy provided by
OmniAuth includes this mixin to gain the default functionality
necessary to be compatible with the OmniAuth library.
Defined Under Namespace
Modules: ClassMethods
Classes: Options
Constant Summary
collapse
- CURRENT_PATH_REGEX =
%r{/$}
- EMPTY_STRING =
''.freeze
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Instance Attribute Details
#app ⇒ Object
Returns the value of attribute app.
112
113
114
|
# File 'lib/omniauth/strategy.rb', line 112
def app
@app
end
|
#env ⇒ Object
Returns the value of attribute env.
112
113
114
|
# File 'lib/omniauth/strategy.rb', line 112
def env
@env
end
|
#options ⇒ Object
Returns the value of attribute options.
112
113
114
|
# File 'lib/omniauth/strategy.rb', line 112
def options
@options
end
|
#response ⇒ Object
Returns the value of attribute response.
112
113
114
|
# File 'lib/omniauth/strategy.rb', line 112
def response
@response
end
|
Class Method Details
.included(base) ⇒ Object
rubocop:disable ModuleLength
10
11
12
13
14
15
16
17
18
|
# File 'lib/omniauth/strategy.rb', line 10
def self.included(base)
OmniAuth.strategies << base
base.extend ClassMethods
base.class_eval do
option :setup, false
option :skip_info, false
end
end
|
Instance Method Details
#auth_hash ⇒ Object
332
333
334
335
336
337
338
|
# File 'lib/omniauth/strategy.rb', line 332
def auth_hash
hash = AuthHash.new(:provider => name, :uid => uid)
hash.info = info unless skip_info?
hash.credentials = credentials if credentials
hash. = if
hash
end
|
#call(env) ⇒ Object
Duplicates this instance and runs #call! on it.
163
164
165
|
# File 'lib/omniauth/strategy.rb', line 163
def call(env)
dup.call!(env)
end
|
#call!(env) ⇒ Object
The logic for dispatching any additional actions that need
to be taken. For instance, calling the request phase if
the request path is recognized.
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
# File 'lib/omniauth/strategy.rb', line 172
def call!(env) unless env['rack.session']
error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.')
raise(error)
end
@env = env
@env['omniauth.strategy'] = self if on_auth_path?
return mock_call!(env) if OmniAuth.config.test_mode
return options_call if on_auth_path? && options_request?
return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym)
return callback_call if on_callback_path?
return other_phase if respond_to?(:other_phase)
@app.call(env)
end
|
#call_app!(env = @env) ⇒ Object
402
403
404
|
# File 'lib/omniauth/strategy.rb', line 402
def call_app!(env = @env)
@app.call(env)
end
|
#callback_call ⇒ Object
Performs the steps necessary to run the callback phase of a strategy.
220
221
222
223
224
225
226
227
228
|
# File 'lib/omniauth/strategy.rb', line 220
def callback_call
setup_phase
log :info, 'Callback phase initiated.'
@env['omniauth.origin'] = session.delete('omniauth.origin')
@env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
@env['omniauth.params'] = session.delete('omniauth.params') || {}
OmniAuth.config.before_callback_phase.call(@env) if OmniAuth.config.before_callback_phase
callback_phase
end
|
#callback_path ⇒ Object
378
379
380
381
382
383
384
385
386
|
# File 'lib/omniauth/strategy.rb', line 378
def callback_path
@callback_path ||= begin
path = options[:callback_path] if options[:callback_path].is_a?(String)
path ||= current_path if options[:callback_path].respond_to?(:call) && options[:callback_path].call(env)
path ||= custom_path(:request_path)
path ||= "#{path_prefix}/#{name}/callback"
path
end
end
|
#callback_phase ⇒ Object
355
356
357
358
|
# File 'lib/omniauth/strategy.rb', line 355
def callback_phase
env['omniauth.auth'] = auth_hash
call_app!
end
|
#callback_url ⇒ Object
426
427
428
|
# File 'lib/omniauth/strategy.rb', line 426
def callback_url
full_host + script_name + callback_path + query_string
end
|
#credentials ⇒ Object
324
325
326
|
# File 'lib/omniauth/strategy.rb', line 324
def credentials
merge_stack(self.class.credentials_stack(self))
end
|
#current_path ⇒ Object
394
395
396
|
# File 'lib/omniauth/strategy.rb', line 394
def current_path
@current_path ||= request.path_info.downcase.sub(CURRENT_PATH_REGEX, EMPTY_STRING)
end
|
#custom_path(kind) ⇒ Object
364
365
366
367
368
369
370
371
372
|
# File 'lib/omniauth/strategy.rb', line 364
def custom_path(kind)
if options[kind].respond_to?(:call)
result = options[kind].call(env)
return nil unless result.is_a?(String)
result
else
options[kind]
end
end
|
#dup ⇒ Object
477
478
479
480
481
|
# File 'lib/omniauth/strategy.rb', line 477
def dup
super.tap do
@options = @options.dup
end
end
|
328
329
330
|
# File 'lib/omniauth/strategy.rb', line 328
def
merge_stack(self.class.(self))
end
|
#fail!(message_key, exception = nil) ⇒ Object
463
464
465
466
467
468
469
470
471
472
473
474
475
|
# File 'lib/omniauth/strategy.rb', line 463
def fail!(message_key, exception = nil)
env['omniauth.error'] = exception
env['omniauth.error.type'] = message_key.to_sym
env['omniauth.error.strategy'] = self
if exception
log :error, "Authentication failure! #{message_key}: #{exception.class}, #{exception.message}"
else
log :error, "Authentication failure! #{message_key} encountered."
end
OmniAuth.config.on_failure.call(env)
end
|
#full_host ⇒ Object
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
|
# File 'lib/omniauth/strategy.rb', line 406
def full_host
case OmniAuth.config.full_host
when String
OmniAuth.config.full_host
when Proc
OmniAuth.config.full_host.call(env)
else
if request.scheme && request.url.match(URI::ABS_URI)
uri = URI.parse(request.url.gsub(/\?.*$/, ''))
uri.path = ''
uri.scheme = 'https' if ssl? uri.to_s
else ''
end
end
end
|
#info ⇒ Object
320
321
322
|
# File 'lib/omniauth/strategy.rb', line 320
def info
merge_stack(self.class.info_stack(self))
end
|
#new(app, options = {}) ⇒ Object
#new(app, *args, options = {}) ⇒ Object
Initializes the strategy by passing in the Rack endpoint,
the unique URL segment name for this strategy, and any
additional arguments. An options
hash is automatically
created from the last argument if it is a hash.
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
# File 'lib/omniauth/strategy.rb', line 129
def initialize(app, *args, &block) @app = app
@env = nil
@options = self.class.default_options.dup
options.deep_merge!(args.pop) if args.last.is_a?(Hash)
options.name ||= self.class.to_s.split('::').last.downcase
self.class.args.each do |arg|
break if args.empty?
options[arg] = args.shift
end
raise(ArgumentError.new("Received wrong number of arguments. #{args.inspect}")) unless args.empty?
yield options if block_given?
end
|
#inspect ⇒ Object
148
149
150
|
# File 'lib/omniauth/strategy.rb', line 148
def inspect
"#<#{self.class}>"
end
|
#log(level, message) ⇒ Object
Direct access to the OmniAuth logger, automatically prefixed
with this strategy's name.
157
158
159
|
# File 'lib/omniauth/strategy.rb', line 157
def log(level, message)
OmniAuth.logger.send(level, "(#{name}) #{message}")
end
|
#mock_call! ⇒ Object
This is called in lieu of the normal request process
in the event that OmniAuth has been configured to be
in test mode.
259
260
261
262
263
|
# File 'lib/omniauth/strategy.rb', line 259
def mock_call!(*)
return mock_request_call if on_request_path?
return mock_callback_call if on_callback_path?
call_app!
end
|
#mock_callback_call ⇒ Object
279
280
281
282
283
284
285
286
287
288
289
290
291
292
|
# File 'lib/omniauth/strategy.rb', line 279
def mock_callback_call
setup_phase
@env['omniauth.origin'] = session.delete('omniauth.origin')
@env['omniauth.origin'] = nil if env['omniauth.origin'] == ''
mocked_auth = OmniAuth.mock_auth_for(name.to_s)
if mocked_auth.is_a?(Symbol)
fail!(mocked_auth)
else
@env['omniauth.auth'] = mocked_auth
@env['omniauth.params'] = session.delete('omniauth.params') || {}
OmniAuth.config.before_callback_phase.call(@env) if OmniAuth.config.before_callback_phase
call_app!
end
end
|
#mock_request_call ⇒ Object
265
266
267
268
269
270
271
272
273
274
275
276
277
|
# File 'lib/omniauth/strategy.rb', line 265
def mock_request_call
setup_phase
session['omniauth.params'] = request.GET
OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase
if request.params['origin']
@env['rack.session']['omniauth.origin'] = request.params['origin']
elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/)
@env['rack.session']['omniauth.origin'] = env['HTTP_REFERER']
end
redirect(callback_url)
end
|
#name ⇒ Object
442
443
444
|
# File 'lib/omniauth/strategy.rb', line 442
def name
options.name
end
|
#on_auth_path? ⇒ Boolean
Returns true if the environment recognizes either the
request or callback path.
232
233
234
|
# File 'lib/omniauth/strategy.rb', line 232
def on_auth_path?
on_request_path? || on_callback_path?
end
|
#on_callback_path? ⇒ Boolean
244
245
246
|
# File 'lib/omniauth/strategy.rb', line 244
def on_callback_path?
on_path?(callback_path)
end
|
#on_path?(path) ⇒ Boolean
248
249
250
|
# File 'lib/omniauth/strategy.rb', line 248
def on_path?(path)
current_path.casecmp(path).zero?
end
|
#on_request_path? ⇒ Boolean
236
237
238
239
240
241
242
|
# File 'lib/omniauth/strategy.rb', line 236
def on_request_path?
if options.request_path.respond_to?(:call)
options.request_path.call(env)
else
on_path?(request_path)
end
end
|
#options_call ⇒ Object
Responds to an OPTIONS request.
190
191
192
193
194
|
# File 'lib/omniauth/strategy.rb', line 190
def options_call
OmniAuth.config.before_options_phase.call(env) if OmniAuth.config.before_options_phase
verbs = OmniAuth.config.allowed_request_methods.collect(&:to_s).collect(&:upcase).join(', ')
[200, {'Allow' => verbs}, []]
end
|
#options_request? ⇒ Boolean
252
253
254
|
# File 'lib/omniauth/strategy.rb', line 252
def options_request?
request.request_method == 'OPTIONS'
end
|
#path_prefix ⇒ Object
360
361
362
|
# File 'lib/omniauth/strategy.rb', line 360
def path_prefix
options[:path_prefix] || OmniAuth.config.path_prefix
end
|
#query_string ⇒ Object
398
399
400
|
# File 'lib/omniauth/strategy.rb', line 398
def query_string
request.query_string.empty? ? '' : "?#{request.query_string}"
end
|
#redirect(uri) ⇒ Object
446
447
448
449
450
451
452
453
454
455
456
457
|
# File 'lib/omniauth/strategy.rb', line 446
def redirect(uri)
r = Rack::Response.new
if options[:iframe]
r.write("<script type='text/javascript' charset='utf-8'>top.location.href = '#{uri}';</script>")
else
r.write("Redirecting to #{uri}...")
r.redirect(uri)
end
r.finish
end
|
#request ⇒ Object
438
439
440
|
# File 'lib/omniauth/strategy.rb', line 438
def request
@request ||= Rack::Request.new(@env)
end
|
#request_call ⇒ Object
Performs the steps necessary to run the request phase of a strategy.
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
# File 'lib/omniauth/strategy.rb', line 197
def request_call setup_phase
log :info, 'Request phase initiated.'
session['omniauth.params'] = request.GET
OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase
if options.form.respond_to?(:call)
log :info, 'Rendering form from supplied Rack endpoint.'
options.form.call(env)
elsif options.form
log :info, 'Rendering form from underlying application.'
call_app!
else
if request.params['origin']
env['rack.session']['omniauth.origin'] = request.params['origin']
elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/)
env['rack.session']['omniauth.origin'] = env['HTTP_REFERER']
end
request_phase
end
end
|
#request_path ⇒ Object
374
375
376
|
# File 'lib/omniauth/strategy.rb', line 374
def request_path
@request_path ||= options[:request_path].is_a?(String) ? options[:request_path] : "#{path_prefix}/#{name}"
end
|
#request_phase ⇒ Object
This method is abstract.
This method is called when the user is on the request path. You should
perform any information gathering you need to be able to authenticate
the user in this phase.
312
313
314
|
# File 'lib/omniauth/strategy.rb', line 312
def request_phase
raise(NotImplementedError)
end
|
#script_name ⇒ Object
430
431
432
|
# File 'lib/omniauth/strategy.rb', line 430
def script_name
@env['SCRIPT_NAME'] || ''
end
|
#session ⇒ Object
434
435
436
|
# File 'lib/omniauth/strategy.rb', line 434
def session
@env['rack.session']
end
|
#setup_path ⇒ Object
388
389
390
|
# File 'lib/omniauth/strategy.rb', line 388
def setup_path
options[:setup_path] || "#{path_prefix}/#{name}/setup"
end
|
#setup_phase ⇒ Object
The setup phase looks for the :setup
option to exist and,
if it is, will call either the Rack endpoint supplied to the
:setup
option or it will call out to the setup path of the
underlying application. This will default to /auth/:provider/setup
.
298
299
300
301
302
303
304
305
306
307
|
# File 'lib/omniauth/strategy.rb', line 298
def setup_phase
if options[:setup].respond_to?(:call)
log :info, 'Setup endpoint detected, running now.'
options[:setup].call(env)
elsif options.setup?
log :info, 'Calling through to underlying application for setup.'
setup_env = env.merge('PATH_INFO' => setup_path, 'REQUEST_METHOD' => 'GET')
call_app!(setup_env)
end
end
|
#skip_info? ⇒ Boolean
Determines whether or not user info should be retrieved. This
allows some strategies to save a call to an external API service
for existing users. You can use it either by setting the :skip_info
to true or by setting :skip_info
to a Proc that takes a uid and
evaluates to true when you would like to skip info.
349
350
351
352
353
|
# File 'lib/omniauth/strategy.rb', line 349
def skip_info?
return false unless options.skip_info?
return true unless options.skip_info.respond_to?(:call)
options.skip_info.call(uid)
end
|
#uid ⇒ Object
316
317
318
|
# File 'lib/omniauth/strategy.rb', line 316
def uid
self.class.uid_stack(self).last
end
|
#user_info ⇒ Object
459
460
461
|
# File 'lib/omniauth/strategy.rb', line 459
def user_info
{}
end
|