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.
# 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
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.
@param app [Rack application] The application on which this middleware is applied.
@overload new(app, options = {})
If nothing but a hash is supplied, initialized with the supplied options overriding the strategy's default options via a deep merge.
@overload new(app, *args, options = {})
If the strategy has supplied custom arguments that it accepts, they may will be passed through and set to the appropriate values.
@yield [Options] Yields options to block for further configuration.
# File lib/omniauth/strategy.rb, line 129 def initialize(app, *args, &block) # rubocop:disable UnusedMethodArgument @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 # Make sure that all of the args have been dealt with, otherwise error out. fail(ArgumentError.new("Received wrong number of arguments. #{args.inspect}")) unless args.empty? yield options if block_given? end
# 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.extra = extra if extra hash end
Duplicates this instance and runs call! on it. @param [Hash] The Rack environment.
# File lib/omniauth/strategy.rb, line 163 def call(env) dup.call!(env) end
The logic for dispatching any additional actions that need to be taken. For instance, calling the request phase if the request path is recognized.
@param env [Hash] The Rack environment.
# File lib/omniauth/strategy.rb, line 172 def call!(env) # rubocop:disable CyclomaticComplexity unless env['rack.session'] error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.') fail(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
# File lib/omniauth/strategy.rb, line 403 def call_app!(env = @env) @app.call(env) end
Performs the steps necessary to run the callback phase of a strategy.
# 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
# File lib/omniauth/strategy.rb, line 383 def callback_path 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
# File lib/omniauth/strategy.rb, line 360 def callback_phase env['omniauth.auth'] = auth_hash call_app! end
# File lib/omniauth/strategy.rb, line 427 def callback_url full_host + script_name + callback_path + query_string end
# File lib/omniauth/strategy.rb, line 324 def credentials merge_stack(self.class.credentials_stack(self)) end
# File lib/omniauth/strategy.rb, line 395 def current_path request.path_info.downcase.sub(/\/$/, '') end
# File lib/omniauth/strategy.rb, line 369 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
# File lib/omniauth/strategy.rb, line 328 def extra merge_stack(self.class.extra_stack(self)) end
# File lib/omniauth/strategy.rb, line 464 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
# File lib/omniauth/strategy.rb, line 407 def full_host case OmniAuth.config.full_host when String OmniAuth.config.full_host when Proc OmniAuth.config.full_host.call(env) else # in Rack 1.3.x, request.url explodes if scheme is nil if request.scheme && request.url.match(URI::ABS_URI) uri = URI.parse(request.url.gsub(/\?.*$/, '')) uri.path = '' # sometimes the url is actually showing http inside rails because the # other layers (like nginx) have handled the ssl termination. uri.scheme = 'https' if ssl? # rubocop:disable BlockNesting uri.to_s else '' end end end
# File lib/omniauth/strategy.rb, line 320 def info merge_stack(self.class.info_stack(self)) end
# File lib/omniauth/strategy.rb, line 148 def inspect "#<#{self.class}>" end
Direct access to the OmniAuth logger, automatically prefixed with this strategy’s name.
@example
log :warn, "This is a warning."
# File lib/omniauth/strategy.rb, line 157 def log(level, message) OmniAuth.logger.send(level, "(#{name}) #{message}") end
This is called in lieu of the normal request process in the event that OmniAuth has been configured to be in test mode.
# 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
# File lib/omniauth/strategy.rb, line 279 def mock_callback_call setup_phase 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') || {} @env['omniauth.origin'] = session.delete('omniauth.origin') @env['omniauth.origin'] = nil if env['omniauth.origin'] == '' OmniAuth.config.before_callback_phase.call(@env) if OmniAuth.config.before_callback_phase call_app! end end
# File lib/omniauth/strategy.rb, line 265 def mock_request_call setup_phase session['omniauth.params'] = request.params 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
Returns true if the environment recognizes either the request or callback path.
# File lib/omniauth/strategy.rb, line 232 def on_auth_path? on_request_path? || on_callback_path? end
# File lib/omniauth/strategy.rb, line 244 def on_callback_path? on_path?(callback_path) end
# File lib/omniauth/strategy.rb, line 248 def on_path?(path) current_path.casecmp(path) == 0 end
# 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
Responds to an OPTIONS request.
# 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
# File lib/omniauth/strategy.rb, line 252 def options_request? request.request_method == 'OPTIONS' end
# File lib/omniauth/strategy.rb, line 365 def path_prefix options[:path_prefix] || OmniAuth.config.path_prefix end
# File lib/omniauth/strategy.rb, line 399 def query_string request.query_string.empty? ? '' : "?#{request.query_string}" end
# File lib/omniauth/strategy.rb, line 447 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
# File lib/omniauth/strategy.rb, line 439 def request @request ||= Rack::Request.new(@env) end
Performs the steps necessary to run the request phase of a strategy.
# File lib/omniauth/strategy.rb, line 197 def request_call # rubocop:disable CyclomaticComplexity, MethodLength setup_phase log :info, 'Request phase initiated.' # store query params from the request url, extracted in the callback_phase session['omniauth.params'] = request.params 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
# File lib/omniauth/strategy.rb, line 379 def request_path options[:request_path].is_a?(String) ? options[:request_path] : "#{path_prefix}/#{name}" end
@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.
# File lib/omniauth/strategy.rb, line 312 def request_phase fail(NotImplementedError) end
# File lib/omniauth/strategy.rb, line 431 def script_name @env['SCRIPT_NAME'] || '' end
# File lib/omniauth/strategy.rb, line 435 def session @env['rack.session'] end
# File lib/omniauth/strategy.rb, line 391 def setup_path options[:setup_path] || "#{path_prefix}/#{name}/setup" end
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`.
# 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
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.
@example
use MyStrategy, :skip_info => lambda{|uid| User.find_by_uid(uid)}
# File lib/omniauth/strategy.rb, line 349 def skip_info? if options.skip_info? if options.skip_info.respond_to?(:call) return options.skip_info.call(uid) else return true end end false end
# File lib/omniauth/strategy.rb, line 482 def merge_stack(stack) stack.inject({}) do |a, e| a.merge!(e) a end end
# File lib/omniauth/strategy.rb, line 489 def ssl? request.env['HTTPS'] == 'on' || request.env['HTTP_X_FORWARDED_SSL'] == 'on' || request.env['HTTP_X_FORWARDED_SCHEME'] == 'https' || (request.env['HTTP_X_FORWARDED_PROTO'] && request.env['HTTP_X_FORWARDED_PROTO'].split(',')[0] == 'https') || request.env['rack.url_scheme'] == 'https' end
Generated with the Darkfish Rdoc Generator 2.