omniauth-2.1.1/0000755000175000017500000000000014362554334012676 5ustar nileshnileshomniauth-2.1.1/.rspec0000644000175000017500000000002714362554334014012 0ustar nileshnilesh--color --order random omniauth-2.1.1/.rubocop.yml0000644000175000017500000000177314362554334015160 0ustar nileshnileshAllCops: TargetRubyVersion: 2.2 Layout/AccessModifierIndentation: EnforcedStyle: outdent Layout/AlignHash: Enabled: false Layout/DotPosition: EnforcedStyle: trailing Layout/SpaceInsideHashLiteralBraces: EnforcedStyle: no_space Lint/HandleExceptions: Enabled: false Metrics/BlockLength: Enabled: false Metrics/BlockNesting: Max: 2 Metrics/LineLength: AllowURI: true Enabled: false Metrics/MethodLength: CountComments: false Max: 15 Metrics/ParameterLists: Max: 4 CountKeywordArgs: true Metrics/AbcSize: Enabled: false Style/CollectionMethods: PreferredMethods: map: 'collect' reduce: 'inject' find: 'detect' find_all: 'select' Style/Documentation: Enabled: false Style/DoubleNegation: Enabled: false Style/EachWithObject: Enabled: false Style/Encoding: Enabled: false Style/ExpandPathArguments: Enabled: false Style/HashSyntax: EnforcedStyle: hash_rockets Style/Lambda: Enabled: false Style/RaiseArgs: EnforcedStyle: compact omniauth-2.1.1/.gitignore0000644000175000017500000000020014362554334014656 0ustar nileshnilesh*.gem *~ .bundle .rvmrc .yardoc Gemfile.lock Gemfile.*.lock coverage/* doc/* log/* measurement/* pkg/* .DS_Store .tool-versions omniauth-2.1.1/.yardopts0000644000175000017500000000007014362554334014541 0ustar nileshnilesh--markup markdown --markup-provider maruku - LICENSE.md omniauth-2.1.1/Rakefile0000644000175000017500000000216714362554334014351 0ustar nileshnileshrequire 'bundler' Bundler::GemHelper.install_tasks require 'rspec/core/rake_task' RSpec::Core::RakeTask.new(:spec) task :test => :spec begin require 'rubocop/rake_task' RuboCop::RakeTask.new rescue LoadError task :rubocop do warn 'RuboCop is disabled' end end task :default => %i[spec rubocop] namespace :perf do task :setup do require 'omniauth' require 'rack/test' app = Rack::Builder.new do |b| b.use Rack::Session::Cookie, :secret => 'abc123' b.use OmniAuth::Strategies::Developer b.run lambda { |_env| [200, {}, ['Not Found']] } end.to_app @app = Rack::MockRequest.new(app) def call_app(path = ENV['GET_PATH'] || '/') result = @app.get(path) raise "Did not succeed #{result.body}" unless result.status == 200 result end end task :ips => :setup do require 'benchmark/ips' Benchmark.ips do |x| x.report('ips') { call_app } end end task :mem => :setup do require 'memory_profiler' num = Integer(ENV['CNT'] || 1) report = MemoryProfiler.report do num.times { call_app } end report.pretty_print end end omniauth-2.1.1/lib/0000755000175000017500000000000014362554334013444 5ustar nileshnileshomniauth-2.1.1/lib/omniauth.rb0000644000175000017500000001146114362554334015620 0ustar nileshnileshrequire 'rack' require 'singleton' require 'logger' module OmniAuth class Error < StandardError; end module Strategies autoload :Developer, 'omniauth/strategies/developer' end autoload :Builder, 'omniauth/builder' autoload :Strategy, 'omniauth/strategy' autoload :Test, 'omniauth/test' autoload :Form, 'omniauth/form' autoload :AuthHash, 'omniauth/auth_hash' autoload :FailureEndpoint, 'omniauth/failure_endpoint' autoload :AuthenticityTokenProtection, 'omniauth/authenticity_token_protection' def self.strategies @strategies ||= [] end class Configuration include Singleton def self.default_logger logger = Logger.new(STDOUT) logger.progname = 'omniauth' logger end def self.defaults # rubocop:disable MethodLength @defaults ||= { :camelizations => {}, :path_prefix => '/auth', :on_failure => OmniAuth::FailureEndpoint, :failure_raise_out_environments => ['development'], :request_validation_phase => OmniAuth::AuthenticityTokenProtection, :before_request_phase => nil, :before_callback_phase => nil, :before_options_phase => nil, :form_css => Form::DEFAULT_CSS, :test_mode => false, :logger => default_logger, :allowed_request_methods => %i[post], :mock_auth => {:default => AuthHash.new('provider' => 'default', 'uid' => '1234', 'info' => {'name' => 'Example User'})}, :silence_get_warning => false } end def initialize self.class.defaults.each_pair { |k, v| send("#{k}=", v) } end def on_failure(&block) if block_given? @on_failure = block else @on_failure end end def before_callback_phase(&block) if block_given? @before_callback_phase = block else @before_callback_phase end end def before_options_phase(&block) if block_given? @before_options_phase = block else @before_options_phase end end def request_validation_phase(&block) if block_given? @request_validation_phase = block else @request_validation_phase end end def before_request_phase(&block) if block_given? @before_request_phase = block else @before_request_phase end end def add_mock(provider, original = {}) # Create key-stringified new hash from given auth hash mock = {} original.each_pair do |key, val| mock[key.to_s] = if val.is_a? Hash Hash[val.each_pair { |k, v| [k.to_s, v] }] else val end end # Merge with the default mock and ensure provider is correct. mock = mock_auth[:default].dup.merge(mock) mock['provider'] = provider.to_s # Add it to the mocks. mock_auth[provider.to_sym] = mock end # This is a convenience method to be used by strategy authors # so that they can add special cases to the camelization utility # method that allows OmniAuth::Builder to work. # # @param name [String] The underscored name, e.g. `oauth` # @param camelized [String] The properly camelized name, e.g. 'OAuth' def add_camelization(name, camelized) camelizations[name.to_s] = camelized.to_s end attr_writer :on_failure, :before_callback_phase, :before_options_phase, :before_request_phase, :request_validation_phase attr_accessor :failure_raise_out_environments, :path_prefix, :allowed_request_methods, :form_css, :test_mode, :mock_auth, :full_host, :camelizations, :logger, :silence_get_warning end def self.config Configuration.instance end def self.configure yield config end def self.logger config.logger end def self.mock_auth_for(provider) config.mock_auth[provider.to_sym] || config.mock_auth[:default] end module Utils module_function # rubocop:disable Layout/IndentationWidth def form_css "" end def deep_merge(hash, other_hash) target = hash.dup other_hash.each_key do |key| if other_hash[key].is_a?(::Hash) && hash[key].is_a?(::Hash) target[key] = deep_merge(target[key], other_hash[key]) next end target[key] = other_hash[key] end target end def camelize(word, first_letter_in_uppercase = true) return OmniAuth.config.camelizations[word.to_s] if OmniAuth.config.camelizations[word.to_s] if first_letter_in_uppercase word.to_s.gsub(%r{/(.?)}) { '::' + Regexp.last_match[1].upcase }.gsub(/(^|_)(.)/) { Regexp.last_match[2].upcase } else camelize(word).tap { |w| w[0] = w[0].downcase } end end end end omniauth-2.1.1/lib/omniauth/0000755000175000017500000000000014362554334015270 5ustar nileshnileshomniauth-2.1.1/lib/omniauth/strategies/0000755000175000017500000000000014362554334017442 5ustar nileshnileshomniauth-2.1.1/lib/omniauth/strategies/developer.rb0000644000175000017500000000324114362554334021754 0ustar nileshnileshmodule OmniAuth module Strategies # The Developer strategy is a very simple strategy that can be used as a # placeholder in your application until a different authentication strategy # is swapped in. It has zero security and should *never* be used in a # production setting. # # ## Usage # # To use the Developer strategy, all you need to do is put it in like any # other strategy: # # @example Basic Usage # # use OmniAuth::Builder do # provider :developer # end # # @example Custom Fields # # use OmniAuth::Builder do # provider :developer, # :fields => [:first_name, :last_name], # :uid_field => :last_name # end # # This will create a strategy that, when the user visits `/auth/developer` # they will be presented a form that prompts for (by default) their name # and email address. The auth hash will be populated with these fields and # the `uid` will simply be set to the provided email. class Developer include OmniAuth::Strategy option :fields, %i[name email] option :uid_field, :email def request_phase form = OmniAuth::Form.new(:title => 'User Info', :url => callback_path) options.fields.each do |field| form.text_field field.to_s.capitalize.tr('_', ' '), field.to_s end form.button 'Sign In' form.to_response end uid do request.params[options.uid_field.to_s] end info do options.fields.inject({}) do |hash, field| hash[field] = request.params[field.to_s] hash end end end end end omniauth-2.1.1/lib/omniauth/test/0000755000175000017500000000000014362554334016247 5ustar nileshnileshomniauth-2.1.1/lib/omniauth/test/phony_session.rb0000644000175000017500000000041414362554334021473 0ustar nileshnileshmodule OmniAuth module Test class PhonySession def initialize(app) @app = app end def call(env) @session ||= (env['rack.session'] || {}) env['rack.session'] = @session @app.call(env) end end end end omniauth-2.1.1/lib/omniauth/test/strategy_test_case.rb0000644000175000017500000000220114362554334022463 0ustar nileshnileshrequire 'rack' require 'omniauth/test' module OmniAuth module Test # Support for testing OmniAuth strategies. # # @example Usage # class MyStrategyTest < Test::Unit::TestCase # include OmniAuth::Test::StrategyTestCase # def strategy # # return the parameters to a Rack::Builder map call: # [MyStrategy, :some, :configuration, :options => 'here'] # end # setup do # post '/auth/my_strategy/callback', :user => { 'name' => 'Dylan', 'id' => '445' } # end # end module StrategyTestCase def app strat = strategy resp = app_response Rack::Builder.new do use(OmniAuth::Test::PhonySession) use(*strat) run lambda { |env| [404, {'Content-Type' => 'text/plain'}, [resp || env.key?('omniauth.auth').to_s]] } end.to_app end def app_response nil end def session last_request.env['rack.session'] end def strategy error = NotImplementedError.new('Including specs must define #strategy') raise(error) end end end end omniauth-2.1.1/lib/omniauth/test/strategy_macros.rb0000644000175000017500000000143214362554334022002 0ustar nileshnileshmodule OmniAuth module Test module StrategyMacros def sets_an_auth_hash it 'sets an auth hash' do expect(last_request.env['omniauth.auth']).to be_kind_of(Hash) end end def sets_provider_to(provider) it "sets the provider to #{provider}" do expect((last_request.env['omniauth.auth'] || {})['provider']).to eq provider end end def sets_uid_to(uid) it "sets the UID to #{uid}" do expect((last_request.env['omniauth.auth'] || {})['uid']).to eq uid end end def sets_user_info_to(user_info) it "sets the user_info to #{user_info}" do expect((last_request.env['omniauth.auth'] || {})['user_info']).to eq user_info end end end end end omniauth-2.1.1/lib/omniauth/version.rb0000644000175000017500000000005714362554334017304 0ustar nileshnileshmodule OmniAuth VERSION = '2.1.1'.freeze end omniauth-2.1.1/lib/omniauth/builder.rb0000644000175000017500000000222314362554334017242 0ustar nileshnileshmodule OmniAuth class Builder < ::Rack::Builder def on_failure(&block) OmniAuth.config.on_failure = block end def before_options_phase(&block) OmniAuth.config.before_options_phase = block end def before_request_phase(&block) OmniAuth.config.before_request_phase = block end def before_callback_phase(&block) OmniAuth.config.before_callback_phase = block end def configure(&block) OmniAuth.configure(&block) end def options(options = false) return @options ||= {} if options == false @options = options end def provider(klass, *args, **opts, &block) if klass.is_a?(Class) middleware = klass else begin middleware = OmniAuth::Strategies.const_get(OmniAuth::Utils.camelize(klass.to_s).to_s, false) rescue NameError raise(LoadError.new("Could not find matching strategy for #{klass.inspect}. You may need to install an additional gem (such as omniauth-#{klass}).")) end end use middleware, *args, **options.merge(opts), &block end def call(env) to_app.call(env) end end end omniauth-2.1.1/lib/omniauth/test.rb0000644000175000017500000000042614362554334016576 0ustar nileshnileshmodule OmniAuth # Support for testing OmniAuth strategies. module Test autoload :PhonySession, 'omniauth/test/phony_session' autoload :StrategyMacros, 'omniauth/test/strategy_macros' autoload :StrategyTestCase, 'omniauth/test/strategy_test_case' end end omniauth-2.1.1/lib/omniauth/auth_hash.rb0000644000175000017500000000243514362554334017565 0ustar nileshnileshrequire 'omniauth/key_store' module OmniAuth # The AuthHash is a normalized schema returned by all OmniAuth # strategies. It maps as much user information as the provider # is able to provide into the InfoHash (stored as the `'info'` # key). class AuthHash < OmniAuth::KeyStore def self.subkey_class Hashie::Mash end # Tells you if this is considered to be a valid # OmniAuth AuthHash. The requirements for that # are that it has a provider name, a uid, and a # valid info hash. See InfoHash#valid? for # more details there. def valid? uid? && provider? && info? && info.valid? end def regular_writer(key, value) value = InfoHash.new(value) if key.to_s == 'info' && value.is_a?(::Hash) && !value.is_a?(InfoHash) super end class InfoHash < OmniAuth::KeyStore def self.subkey_class Hashie::Mash end def name return self[:name] if self[:name] return "#{first_name} #{last_name}".strip if first_name? || last_name? return nickname if nickname? return email if email? nil end def name? !!name end alias valid? name? def to_hash hash = super hash['name'] ||= name hash end end end end omniauth-2.1.1/lib/omniauth/form.rb0000644000175000017500000000500614362554334016561 0ustar nileshnileshmodule OmniAuth class Form DEFAULT_CSS = File.read(File.expand_path('../form.css', __FILE__)) attr_accessor :options def initialize(options = {}) options[:title] ||= 'Authentication Info Required' options[:header_info] ||= '' self.options = options @html = +'' # unary + string allows it to be mutable if strings are frozen @with_custom_button = false @footer = nil header(options[:title], options[:header_info]) end def self.build(options = {}, &block) form = OmniAuth::Form.new(options) if block.arity > 0 yield form else form.instance_eval(&block) end form end def label_field(text, target) @html << "\n" self end def input_field(type, name) @html << "\n" self end def text_field(label, name) label_field(label, name) input_field('text', name) self end def password_field(label, name) label_field(label, name) input_field('password', name) self end def button(text) @with_custom_button = true @html << "\n" end def html(html) @html << html end def fieldset(legend, options = {}, &block) @html << "\n\n #{legend}\n" instance_eval(&block) @html << "\n" self end def header(title, header_info) @html << <<-HTML #{title} #{css} #{header_info}

#{title}

HTML self end def footer return self if @footer @html << "\n" unless @with_custom_button @html << <<-HTML
HTML @footer = true self end def to_html footer @html end def to_response footer Rack::Response.new(@html, 200, 'content-type' => 'text/html').finish end protected def css "\n" end end end omniauth-2.1.1/lib/omniauth/authenticity_token_protection.rb0000644000175000017500000000120014362554334023766 0ustar nileshnileshrequire 'rack-protection' module OmniAuth class AuthenticityError < StandardError; end class AuthenticityTokenProtection < Rack::Protection::AuthenticityToken def initialize(options = {}) @options = default_options.merge(options) end def self.call(env) new.call!(env) end def call!(env) return if accepts?(env) instrument env react env end alias_method :call, :call! private def deny(_env) OmniAuth.logger.send(:warn, "Attack prevented by #{self.class}") raise AuthenticityError.new(options[:message]) end alias default_reaction deny end end omniauth-2.1.1/lib/omniauth/form.css0000644000175000017500000000306714362554334016753 0ustar nileshnileshbody { background: #ccc; font-family: "Lucida Grande", "Lucida Sans", Helvetica, Arial, sans-serif; } h1 { text-align: center; margin: 30px auto 0px; font-size: 18px; padding: 10px 10px 15px; background: #555; color: white; width: 320px; border: 10px solid #444; border-bottom: 0; -moz-border-radius-topleft: 10px; -moz-border-radius-topright: 10px; -webkit-border-top-left-radius: 10px; -webkit-border-top-right-radius: 10px; border-top-left-radius: 10px; border-top-right-radius: 10px; } h1, form { -moz-box-shadow: 2px 2px 7px rgba(0,0,0,0.3); -webkit-box-shadow: 2px 2px 7px rgba(0,0,0,0.3); } form { background: white; border: 10px solid #eee; border-top: 0; padding: 20px; margin: 0px auto 40px; width: 300px; -moz-border-radius-bottomleft: 10px; -moz-border-radius-bottomright: 10px; -webkit-border-bottom-left-radius: 10px; -webkit-border-bottom-right-radius: 10px; border-bottom-left-radius: 10px; border-bottom-right-radius: 10px; } label { display: block; font-weight: bold; margin-bottom: 5px; } input { font-size: 18px; padding: 4px 8px; display: block; margin-bottom: 10px; width: 280px; } input#identifier, input#openid_url { background: url(https://openid.net/images/login-bg.gif) no-repeat; background-position: 0 50%; padding-left: 18px; } button { font-size: 22px; padding: 4px 8px; display: block; margin: 20px auto 0; } fieldset { border: 1px solid #ccc; border-left: 0; border-right: 0; padding: 10px 0; } fieldset input { width: 260px; font-size: 16px; } omniauth-2.1.1/lib/omniauth/failure_endpoint.rb0000644000175000017500000000303714362554334021147 0ustar nileshnileshmodule OmniAuth # This simple Rack endpoint that serves as the default # 'failure' mechanism for OmniAuth. If a strategy fails for # any reason this endpoint will be invoked. The default behavior # is to redirect to `/auth/failure` except in the case of # a development `RACK_ENV`, in which case an exception will # be raised. class FailureEndpoint attr_reader :env def self.call(env) new(env).call end def initialize(env) @env = env end def call raise_out! if OmniAuth.config.failure_raise_out_environments.include?(ENV['RACK_ENV'].to_s) redirect_to_failure end def raise_out! raise(env['omniauth.error'] || OmniAuth::Error.new(env['omniauth.error.type'])) end def redirect_to_failure message_key = env['omniauth.error.type'] new_path = "#{env['SCRIPT_NAME']}#{strategy_path_prefix}/failure?message=#{Rack::Utils.escape(message_key)}#{origin_query_param}#{strategy_name_query_param}" Rack::Response.new(['302 Moved'], 302, 'Location' => new_path).finish end def strategy_path_prefix if env['omniauth.error.strategy'] env['omniauth.error.strategy'].path_prefix else OmniAuth.config.path_prefix end end def strategy_name_query_param return '' unless env['omniauth.error.strategy'] "&strategy=#{env['omniauth.error.strategy'].name}" end def origin_query_param return '' unless env['omniauth.origin'] "&origin=#{Rack::Utils.escape(env['omniauth.origin'])}" end end end omniauth-2.1.1/lib/omniauth/key_store.rb0000644000175000017500000000114014362554334017615 0ustar nileshnileshrequire 'hashie/mash' module OmniAuth # Generic helper hash that allows method access on deeply nested keys. class KeyStore < ::Hashie::Mash # Disables warnings on Hashie 3.5.0+ for overwritten keys def self.override_logging require 'hashie/version' return unless Gem::Version.new(Hashie::VERSION) >= Gem::Version.new('3.5.0') if respond_to?(:disable_warnings) disable_warnings else define_method(:log_built_in_message) { |*| } private :log_built_in_message end end # Disable on loading of the class override_logging end end omniauth-2.1.1/lib/omniauth/strategy.rb0000644000175000017500000004336614362554334017473 0ustar nileshnileshrequire 'omniauth/key_store' module OmniAuth class NoSessionError < StandardError; end # 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. module Strategy # rubocop:disable ModuleLength def self.included(base) OmniAuth.strategies << base base.extend ClassMethods base.class_eval do option :setup, false option :skip_info, false option :origin_param, 'origin' end end module ClassMethods # Returns an inherited set of default options set at the class-level # for each strategy. def default_options # existing = superclass.default_options if superclass.respond_to?(:default_options) existing = superclass.respond_to?(:default_options) ? superclass.default_options : {} @default_options ||= OmniAuth::Strategy::Options.new(existing) end # This allows for more declarative subclassing of strategies by allowing # default options to be set using a simple configure call. # # @param options [Hash] If supplied, these will be the default options (deep-merged into the superclass's default options). # @yield [Options] The options Mash that allows you to set your defaults as you'd like. # # @example Using a yield to configure the default options. # # class MyStrategy # include OmniAuth::Strategy # # configure do |c| # c.foo = 'bar' # end # end # # @example Using a hash to configure the default options. # # class MyStrategy # include OmniAuth::Strategy # configure foo: 'bar' # end def configure(options = nil) if block_given? yield default_options else default_options.deep_merge!(options) end end # Directly declare a default option for your class. This is a useful from # a documentation perspective as it provides a simple line-by-line analysis # of the kinds of options your strategy provides by default. # # @param name [Symbol] The key of the default option in your configuration hash. # @param value [Object] The value your object defaults to. Nil if not provided. # # @example # # class MyStrategy # include OmniAuth::Strategy # # option :foo, 'bar' # option # end def option(name, value = nil) default_options[name] = value end # Sets (and retrieves) option key names for initializer arguments to be # recorded as. This takes care of 90% of the use cases for overriding # the initializer in OmniAuth Strategies. def args(args = nil) if args @args = Array(args) return end existing = superclass.respond_to?(:args) ? superclass.args : [] (instance_variable_defined?(:@args) && @args) || existing end %w[uid info extra credentials].each do |fetcher| class_eval <<-RUBY, __FILE__, __LINE__ + 1 attr_reader :#{fetcher}_proc private :#{fetcher}_proc def #{fetcher}(&block) return #{fetcher}_proc unless block_given? @#{fetcher}_proc = block end def #{fetcher}_stack(context) compile_stack(self.ancestors, :#{fetcher}, context) end RUBY end def compile_stack(ancestors, method, context) stack = ancestors.inject([]) do |a, ancestor| a << context.instance_eval(&ancestor.send(method)) if ancestor.respond_to?(method) && ancestor.send(method) a end stack.reverse! end end attr_reader :app, :env, :options, :response # 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. 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. raise(ArgumentError.new("Received wrong number of arguments. #{args.inspect}")) unless args.empty? yield options if block_given? end 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." def log(level, message) OmniAuth.logger.send(level, "(#{name}) #{message}") end # Duplicates this instance and runs #call! on it. # @param [Hash] The Rack environment. 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. def call!(env) # rubocop:disable CyclomaticComplexity, PerceivedComplexity unless env['rack.session'] error = OmniAuth::NoSessionError.new('You must provide a session to use OmniAuth.') raise(error) end @env = env warn_if_using_get_on_request_path @env['omniauth.strategy'] = self if on_auth_path? return mock_call!(env) if OmniAuth.config.test_mode begin 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) rescue StandardError => e raise e if env.delete('omniauth.error.app') return fail!(e.message, e) end @app.call(env) end def warn_if_using_get_on_request_path return unless on_request_path? return unless OmniAuth.config.allowed_request_methods.include?(:get) return if OmniAuth.config.silence_get_warning log :warn, <<-WARN You are using GET as an allowed request method for OmniAuth. This may leave you open to CSRF attacks. As of v2.0.0, OmniAuth by default allows only POST to its own routes. You should review the following resources to guide your mitigation: https://github.com/omniauth/omniauth/wiki/Resolving-CVE-2015-9284 https://github.com/omniauth/omniauth/issues/960 https://nvd.nist.gov/vuln/detail/CVE-2015-9284 https://github.com/omniauth/omniauth/pull/809 You can ignore this warning by setting: OmniAuth.config.silence_get_warning = true WARN end # Responds to an OPTIONS request. 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 # Performs the steps necessary to run the request phase of a strategy. def request_call # rubocop:disable CyclomaticComplexity, MethodLength, PerceivedComplexity setup_phase log :debug, 'Request phase initiated.' # store query params from the request url, extracted in the callback_phase session['omniauth.params'] = request.GET OmniAuth.config.request_validation_phase.call(env) if OmniAuth.config.request_validation_phase OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase if options.form.respond_to?(:call) log :debug, 'Rendering form from supplied Rack endpoint.' options.form.call(env) elsif options.form log :debug, 'Rendering form from underlying application.' call_app! elsif !options.origin_param request_phase else if request.params[options.origin_param] env['rack.session']['omniauth.origin'] = request.params[options.origin_param] elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/) env['rack.session']['omniauth.origin'] = env['HTTP_REFERER'] end request_phase end rescue OmniAuth::AuthenticityError => e fail!(:authenticity_error, e) end # Performs the steps necessary to run the callback phase of a strategy. def callback_call setup_phase log :debug, '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 # Returns true if the environment recognizes either the # request or callback path. def on_auth_path? on_request_path? || on_callback_path? end def on_request_path? if options[:request_path].respond_to?(:call) options[:request_path].call(env) else on_path?(request_path) end end def on_callback_path? on_path?(callback_path) end def on_path?(path) current_path.casecmp(path).zero? end def options_request? request.request_method == 'OPTIONS' end # This is called in lieu of the normal request process # in the event that OmniAuth has been configured to be # in test mode. def mock_call!(*) begin return mock_request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym) return mock_callback_call if on_callback_path? rescue StandardError => e raise e if env.delete('omniauth.error.app') return fail!(e.message, e) end call_app! end def mock_request_call setup_phase session['omniauth.params'] = request.GET OmniAuth.config.request_validation_phase.call(env) if OmniAuth.config.request_validation_phase OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase if options.origin_param if request.params[options.origin_param] session['omniauth.origin'] = request.params[options.origin_param] elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/) session['omniauth.origin'] = env['HTTP_REFERER'] end end redirect(callback_url) end def mock_callback_call setup_phase @env['omniauth.origin'] = session.delete('omniauth.origin') @env['omniauth.origin'] = nil if env['omniauth.origin'] == '' @env['omniauth.params'] = session.delete('omniauth.params') || {} mocked_auth = OmniAuth.mock_auth_for(name.to_s) if mocked_auth.is_a?(Symbol) fail!(mocked_auth) else @env['omniauth.auth'] = mocked_auth OmniAuth.config.before_callback_phase.call(@env) if OmniAuth.config.before_callback_phase call_app! end 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`. def setup_phase if options[:setup].respond_to?(:call) log :debug, 'Setup endpoint detected, running now.' options[:setup].call(env) elsif options[:setup] log :debug, 'Calling through to underlying application for setup.' setup_env = env.merge('PATH_INFO' => setup_path, 'REQUEST_METHOD' => 'GET') call_app!(setup_env) end 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. def request_phase raise(NotImplementedError) end def uid self.class.uid_stack(self).last end def info merge_stack(self.class.info_stack(self)) end def credentials merge_stack(self.class.credentials_stack(self)) end def extra merge_stack(self.class.extra_stack(self)) end def auth_hash credentials_data = credentials extra_data = extra AuthHash.new(:provider => name, :uid => uid).tap do |auth| auth.info = info unless skip_info? auth.credentials = credentials_data if credentials_data auth.extra = extra_data if extra_data 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)} def skip_info? return false unless options.skip_info? return true unless options.skip_info.respond_to?(:call) options.skip_info.call(uid) end def callback_phase env['omniauth.auth'] = auth_hash call_app! end def path_prefix options[:path_prefix] || OmniAuth.config.path_prefix end 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 def request_path @request_path ||= if options[:request_path].is_a?(String) options[:request_path] else "#{script_name}#{path_prefix}/#{name}" end end 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 ||= "#{script_name}#{path_prefix}/#{name}/callback" path end end def setup_path options[:setup_path] || "#{path_prefix}/#{name}/setup" end CURRENT_PATH_REGEX = %r{/$}.freeze EMPTY_STRING = ''.freeze def current_path @current_path ||= request.path.downcase.sub(CURRENT_PATH_REGEX, EMPTY_STRING) end def query_string request.query_string.empty? ? '' : "?#{request.query_string}" end def call_app!(env = @env) @app.call(env) rescue StandardError => e env['omniauth.error.app'] = true raise e end 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 def callback_url full_host + callback_path + query_string end def script_name return '' if @env.nil? @env['SCRIPT_NAME'] || '' end def session @env['rack.session'] end def request @request ||= Rack::Request.new(@env) end def name options[:name] end def redirect(uri) r = Rack::Response.new if options[:iframe] r.write("") else r.write("Redirecting to #{uri}...") r.redirect(uri) end r.finish end def user_info {} end 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 class Options < OmniAuth::KeyStore; end protected def initialize_copy(*args) super @options = @options.dup end def merge_stack(stack) stack.inject({}) do |a, e| a.merge!(e) a end end 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 end end omniauth-2.1.1/omniauth.gemspec0000644000175000017500000000210514362554334016065 0ustar nileshnilesh# coding: utf-8 lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) require 'omniauth/version' Gem::Specification.new do |spec| spec.add_dependency 'hashie', ['>= 3.4.6'] spec.add_dependency 'rack', '>= 2.2.3' spec.add_development_dependency 'bundler', '~> 2.0' spec.add_dependency 'rack-protection' spec.add_development_dependency 'rake', '~> 12.0' spec.authors = ['Michael Bleigh', 'Erik Michaels-Ober', 'Tom Milewski'] spec.description = 'A generalized Rack framework for multiple-provider authentication.' spec.email = ['michael@intridea.com', 'sferik@gmail.com', 'tmilewski@gmail.com'] spec.files = `git ls-files -z`.split("\x0").reject { |f| f.start_with?('spec/') } spec.homepage = 'https://github.com/omniauth/omniauth' spec.licenses = %w[MIT] spec.name = 'omniauth' spec.require_paths = %w[lib] spec.required_rubygems_version = '>= 1.3.5' spec.required_ruby_version = '>= 2.2' spec.summary = spec.description spec.version = OmniAuth::VERSION end omniauth-2.1.1/spec/0000755000175000017500000000000014362554334013630 5ustar nileshnileshomniauth-2.1.1/spec/helper.rb0000644000175000017500000000314614362554334015440 0ustar nileshnileshif RUBY_VERSION >= '1.9' require 'simplecov' require 'coveralls' require 'simplecov-lcov' SimpleCov::Formatter::LcovFormatter.config.report_with_single_file = true SimpleCov.formatters = [ SimpleCov::Formatter::HTMLFormatter, SimpleCov::Formatter::LcovFormatter, Coveralls::SimpleCov::Formatter ] SimpleCov.start do add_filter ['/spec/', '/vendor/', 'strategy_macros.rb'] minimum_coverage(92.5) maximum_coverage_drop(0.05) end end require 'rspec' require 'rack/test' require 'rack/freeze' require 'omniauth' require 'omniauth/test' OmniAuth.config.logger = Logger.new('/dev/null') OmniAuth.config.request_validation_phase = nil RSpec.configure do |config| config.include Rack::Test::Methods config.extend OmniAuth::Test::StrategyMacros, :type => :strategy config.expect_with :rspec do |c| c.syntax = :expect end end class ExampleStrategy include OmniAuth::Strategy attr_reader :last_env option :name, 'test' def call(env) options[:dup] ? super : call!(env) end def initialize(*args, &block) super @fail = nil end def request_phase options[:mutate_on_request].call(options) if options[:mutate_on_request] @fail = fail!(options[:failure], options[:failure_exception]) if options[:failure] @last_env = env return @fail if @fail raise('Request Phase') end def callback_phase options[:mutate_on_callback].call(options) if options[:mutate_on_callback] @fail = fail!(options[:failure], options[:failure_exception]) if options[:failure] @last_env = env return @fail if @fail raise('Callback Phase') end end omniauth-2.1.1/spec/omniauth/0000755000175000017500000000000014362554334015454 5ustar nileshnileshomniauth-2.1.1/spec/omniauth/builder_spec.rb0000644000175000017500000000720314362554334020443 0ustar nileshnileshrequire 'helper' describe OmniAuth::Builder do describe '#provider' do it 'translates a symbol to a constant' do expect(OmniAuth::Strategies).to receive(:const_get).with('MyStrategy', false).and_return(Class.new) OmniAuth::Builder.new(nil) do provider :my_strategy end end it 'accepts a class' do class ExampleClass; end expect do OmniAuth::Builder.new(nil) do provider ::ExampleClass end end.not_to raise_error end it "raises a helpful LoadError message if it can't find the class" do expect do OmniAuth::Builder.new(nil) do provider :lorax end end.to raise_error(LoadError, 'Could not find matching strategy for :lorax. You may need to install an additional gem (such as omniauth-lorax).') end it "doesn't translate a symbol to a top-level constant" do class MyStrategy; end expect do OmniAuth::Builder.new(nil) do provider :my_strategy end end.to raise_error(LoadError, 'Could not find matching strategy for :my_strategy. You may need to install an additional gem (such as omniauth-my_strategy).') end end describe '#options' do it 'merges provided options in' do k = Class.new b = OmniAuth::Builder.new(nil) expect(b).to receive(:use).with(k, :foo => 'bar', :baz => 'tik') b.options :foo => 'bar' b.provider k, :baz => 'tik' end it 'adds an argument if no options are provided' do k = Class.new b = OmniAuth::Builder.new(nil) expect(b).to receive(:use).with(k, :foo => 'bar') b.options :foo => 'bar' b.provider k end end describe '#on_failure' do it 'passes the block to the config' do prok = proc {} with_config_reset(:on_failure) do OmniAuth::Builder.new(nil).on_failure(&prok) expect(OmniAuth.config.on_failure).to eq(prok) end end end describe '#before_options_phase' do it 'passes the block to the config' do prok = proc {} with_config_reset(:before_options_phase) do OmniAuth::Builder.new(nil).before_options_phase(&prok) expect(OmniAuth.config.before_options_phase).to eq(prok) end end end describe '#before_request_phase' do it 'passes the block to the config' do prok = proc {} with_config_reset(:before_request_phase) do OmniAuth::Builder.new(nil).before_request_phase(&prok) expect(OmniAuth.config.before_request_phase).to eq(prok) end end end describe '#before_callback_phase' do it 'passes the block to the config' do prok = proc {} with_config_reset(:before_callback_phase) do OmniAuth::Builder.new(nil).before_callback_phase(&prok) expect(OmniAuth.config.before_callback_phase).to eq(prok) end end end describe '#configure' do it 'passes the block to the config' do prok = proc {} allow(OmniAuth).to receive(:configure).and_call_original OmniAuth::Builder.new(nil).configure(&prok) expect(OmniAuth).to have_received(:configure) do |&block| expect(block).to eq(prok) end end end describe '#call' do it 'passes env to to_app.call' do app = lambda { |env| [200, {}, env['CUSTOM_ENV_VALUE']] } builder = OmniAuth::Builder.new(app) env = {'REQUEST_METHOD' => 'GET', 'PATH_INFO' => '/some/path', 'CUSTOM_ENV_VALUE' => 'VALUE'} expect(builder.call(env)).to eq([200, {}, 'VALUE']) end end def with_config_reset(option) old_config = OmniAuth.config.send(option) yield OmniAuth.config.send("#{option}=", old_config) end end omniauth-2.1.1/spec/omniauth/strategies/0000755000175000017500000000000014362554334017626 5ustar nileshnileshomniauth-2.1.1/spec/omniauth/strategies/developer_spec.rb0000644000175000017500000000412714362554334023156 0ustar nileshnileshrequire 'helper' describe OmniAuth::Strategies::Developer do let(:app) do Rack::Builder.new do |b| b.use Rack::Session::Cookie, :secret => 'abc123' b.use OmniAuth::Strategies::Developer b.run lambda { |_env| [200, {}, ['Not Found']] } end.to_app end context 'request phase' do before(:each) { post '/auth/developer' } it 'displays a form' do expect(last_response.status).to eq(200) expect(last_response.body).to be_include(' 'Example User', :email => 'user@example.com' end it 'sets the name in the auth hash' do expect(auth_hash.info.name).to eq('Example User') end it 'sets the email in the auth hash' do expect(auth_hash.info.email).to eq('user@example.com') end it 'sets the uid to the email' do expect(auth_hash.uid).to eq('user@example.com') end end context 'with custom options' do let(:app) do Rack::Builder.new do |b| b.use Rack::Session::Cookie, :secret => 'abc123' b.use OmniAuth::Strategies::Developer, :fields => %i[first_name last_name], :uid_field => :last_name b.run lambda { |_env| [200, {}, ['Not Found']] } end.to_app end before do @options = {:uid_field => :last_name, :fields => %i[first_name last_name]} post '/auth/developer/callback', :first_name => 'Example', :last_name => 'User' end it 'sets info fields properly' do expect(auth_hash.info.name).to eq('Example User') end it 'sets the uid properly' do expect(auth_hash.uid).to eq('User') end end end end omniauth-2.1.1/spec/omniauth/strategy_spec.rb0000644000175000017500000011650214362554334020662 0ustar nileshnileshrequire 'helper' def make_env(path = '/auth/test', props = {}) { 'REQUEST_METHOD' => 'POST', 'PATH_INFO' => path, 'rack.session' => {}, 'rack.input' => StringIO.new('test=true') }.merge(props) end describe OmniAuth::Strategy do let(:app) do lambda { |_env| [404, {}, ['Awesome']] } end let(:fresh_strategy) do c = Class.new c.send(:include, OmniAuth::Strategy) end describe '.default_options' do it 'is inherited from a parent class' do superklass = Class.new superklass.send :include, OmniAuth::Strategy superklass.configure do |c| c.foo = 'bar' end klass = Class.new(superklass) expect(klass.default_options.foo).to eq('bar') end end describe 'user_info' do it 'should default to an empty hash' do expect(fresh_strategy.new(app, :skip_info => true).user_info).to eq({}) end end describe '.configure' do subject do c = Class.new c.send(:include, OmniAuth::Strategy) end context 'when block is passed' do it 'allows for default options setting' do subject.configure do |c| c.wakka = 'doo' end expect(subject.default_options['wakka']).to eq('doo') end it "works when block doesn't evaluate to true" do environment_variable = nil subject.configure do |c| c.abc = '123' c.hgi = environment_variable end expect(subject.default_options['abc']).to eq('123') end end it 'takes a hash and deep merge it' do subject.configure :abc => {:def => 123} subject.configure :abc => {:hgi => 456} expect(subject.default_options['abc']).to eq('def' => 123, 'hgi' => 456) end end describe '#fail!' do it 'provides exception information when one is provided' do env = make_env exception = RuntimeError.new('No session!') expect(OmniAuth.logger).to receive(:error).with( "(test) Authentication failure! failed: #{exception.class}, #{exception.message}" ) ExampleStrategy.new(app, :failure => :failed, :failure_exception => exception).call(env) end it 'provides a generic message when not provided an exception' do env = make_env expect(OmniAuth.logger).to receive(:error).with( '(test) Authentication failure! Some Issue encountered.' ) ExampleStrategy.new(app, :failure => 'Some Issue').call(env) end end describe '#skip_info?' do it 'is true if options.skip_info is true' do expect(ExampleStrategy.new(app, :skip_info => true)).to be_skip_info end it 'is false if options.skip_info is false' do expect(ExampleStrategy.new(app, :skip_info => false)).not_to be_skip_info end it 'is false by default' do expect(ExampleStrategy.new(app)).not_to be_skip_info end it 'is true if options.skip_info is a callable that evaluates to truthy' do instance = ExampleStrategy.new(app, :skip_info => lambda { |uid| uid }) expect(instance).to receive(:uid).and_return(true) expect(instance).to be_skip_info end end describe '.option' do subject do c = Class.new c.send(:include, OmniAuth::Strategy) end it 'sets a default value' do subject.option :abc, 123 expect(subject.default_options.abc).to eq(123) end it 'sets the default value to nil if none is provided' do subject.option :abc expect(subject.default_options.abc).to be_nil end end describe '.args' do subject do c = Class.new c.send(:include, OmniAuth::Strategy) end it 'sets args to the specified argument if there is one' do subject.args %i[abc def] expect(subject.args).to eq(%i[abc def]) end it 'is inheritable' do subject.args %i[abc def] c = Class.new(subject) expect(c.args).to eq(%i[abc def]) end it 'accepts corresponding options as default arg values' do subject.args %i[a b] subject.option :a, '1' subject.option :b, '2' expect(subject.new(nil).options.a).to eq '1' expect(subject.new(nil).options.b).to eq '2' expect(subject.new(nil, '3', '4').options.b).to eq '4' expect(subject.new(nil, nil, '4').options.a).to eq nil end end context 'fetcher procs' do subject { fresh_strategy } %w[uid info credentials extra].each do |fetcher| describe ".#{fetcher}" do it 'sets and retrieve a proc' do proc = lambda { 'Hello' } subject.send(fetcher, &proc) expect(subject.send(fetcher)).to eq(proc) end end end end context 'fetcher stacks' do subject { fresh_strategy } %w[uid info credentials extra].each do |fetcher| describe ".#{fetcher}_stack" do it 'is an array of called ancestral procs' do fetchy = proc { 'Hello' } subject.send(fetcher, &fetchy) expect(subject.send("#{fetcher}_stack", subject.new(app))).to eq(['Hello']) end end end end %w[request_phase].each do |abstract_method| context abstract_method.to_s do it 'raises a NotImplementedError' do strat = Class.new strat.send :include, OmniAuth::Strategy expect { strat.new(app).send(abstract_method) }.to raise_error(NotImplementedError) end end end describe '#auth_hash' do subject do klass = Class.new klass.send :include, OmniAuth::Strategy klass.option :name, 'auth_hasher' klass end let(:instance) { subject.new(app) } it 'calls through to uid, info, credentials, and extra' do expect(instance).to receive(:uid) expect(instance).to receive(:info) expect(instance).to receive(:credentials).and_return(expires: true).once expect(instance).to receive(:extra).and_return(something: 'else').once instance.auth_hash end it 'returns an AuthHash' do allow(instance).to receive(:uid).and_return('123') allow(instance).to receive(:info).and_return(:name => 'Hal Awesome') allow(instance).to receive(:credentials).and_return(expires: true) allow(instance).to receive(:extra).and_return(something: 'else') hash = instance.auth_hash expect(hash).to be_kind_of(OmniAuth::AuthHash) expect(hash.uid).to eq('123') expect(hash.info.name).to eq('Hal Awesome') expect(hash.credentials.expires).to eq(true) expect(hash.extra.something).to eq('else') end end describe '#initialize' do context 'options extraction' do it 'is the last argument if the last argument is a Hash' do expect(ExampleStrategy.new(app, :abc => 123).options[:abc]).to eq(123) end it 'is the default options if any are provided' do allow(ExampleStrategy).to receive(:default_options).and_return(OmniAuth::Strategy::Options.new(:abc => 123)) expect(ExampleStrategy.new(app).options.abc).to eq(123) end end context 'custom args' do subject do c = Class.new c.send(:include, OmniAuth::Strategy) end it 'sets options based on the arguments if they are supplied' do subject.args %i[abc def] s = subject.new app, 123, 456 expect(s.options[:abc]).to eq(123) expect(s.options[:def]).to eq(456) end end end describe '#call' do it 'duplicates and calls' do klass = Class.new klass.send :include, OmniAuth::Strategy instance = klass.new(app) expect(instance).to receive(:dup).and_return(instance) instance.call('rack.session' => {}) end it 'raises NoSessionError if rack.session isn\'t set' do klass = Class.new klass.send :include, OmniAuth::Strategy instance = klass.new(app) expect { instance.call({}) }.to raise_error(OmniAuth::NoSessionError) end end describe '#inspect' do it 'returns the class name' do expect(ExampleStrategy.new(app).inspect).to eq('#') end end describe '#redirect' do it 'uses javascript if :iframe is true' do response = ExampleStrategy.new(app, :iframe => true).redirect('http://abc.com') expected_body = "" expect(response.last).to include(expected_body) end end describe '#callback_phase' do subject do c = Class.new c.send(:include, OmniAuth::Strategy) c.new(app) end it 'sets the auth hash' do env = make_env allow(subject).to receive(:env).and_return(env) allow(subject).to receive(:auth_hash).and_return('AUTH HASH') subject.callback_phase expect(env['omniauth.auth']).to eq('AUTH HASH') end end describe '#full_host' do let(:strategy) { ExampleStrategy.new(app, {}) } it 'remains calm when there is a pipe in the URL' do strategy.call!(make_env('/whatever', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'facebook.lame', 'QUERY_STRING' => 'code=asofibasf|asoidnasd', 'SCRIPT_NAME' => '', 'SERVER_PORT' => 80)) expect { strategy.full_host }.not_to raise_error end end describe '#uid' do subject { fresh_strategy } it "is the current class's uid if one exists" do subject.uid { 'Hi' } expect(subject.new(app).uid).to eq('Hi') end it 'inherits if it can' do subject.uid { 'Hi' } c = Class.new(subject) expect(c.new(app).uid).to eq('Hi') end end %w[info credentials extra].each do |fetcher| subject { fresh_strategy } it "is the current class's proc call if one exists" do subject.send(fetcher) { {:abc => 123} } expect(subject.new(app).send(fetcher)).to eq(:abc => 123) end it 'inherits by merging with preference for the latest class' do subject.send(fetcher) { {:abc => 123, :def => 456} } c = Class.new(subject) c.send(fetcher) { {:abc => 789} } expect(c.new(app).send(fetcher)).to eq(:abc => 789, :def => 456) end end describe '#call' do before(:all) do @options = nil end let(:strategy) { ExampleStrategy.new(app, @options || {}) } context 'omniauth.origin' do context 'disabled' do it 'does not set omniauth.origin' do @options = {:origin_param => false} expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'return=/foo')) expect(strategy.last_env['rack.session']['omniauth.origin']).to eq(nil) end end context 'custom' do it 'sets from a custom param' do @options = {:origin_param => 'return'} expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'return=/foo')) expect(strategy.last_env['rack.session']['omniauth.origin']).to eq('/foo') end end context 'default flow' do it 'is set on the request phase' do expect(strategy).to receive(:fail!).with("Request Phase", kind_of(StandardError)) strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin')) expect(strategy.last_env['rack.session']['omniauth.origin']).to eq('http://example.com/origin') end it 'is turned into an env variable on the callback phase' do expect(strategy).to receive(:fail!).with("Callback Phase", kind_of(StandardError)) strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'})) expect(strategy.last_env['omniauth.origin']).to eq('http://example.com/origin') end it 'sets from the params if provided' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo')) expect(strategy.last_env['rack.session']['omniauth.origin']).to eq('/foo') end it 'is set on the failure env' do expect(OmniAuth.config).to receive(:on_failure).and_return(lambda { |env| env }) @options = {:failure => :forced_fail} strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => '/awesome'})) end context 'with script_name' do it 'is set on the request phase, containing full path' do env = {'HTTP_REFERER' => 'http://example.com/sub_uri/origin', 'SCRIPT_NAME' => '/sub_uri'} expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test', env)) expect(strategy.last_env['rack.session']['omniauth.origin']).to eq('http://example.com/sub_uri/origin') end it 'is turned into an env variable on the callback phase, containing full path' do env = { 'rack.session' => {'omniauth.origin' => 'http://example.com/sub_uri/origin'}, 'SCRIPT_NAME' => '/sub_uri' } expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test/callback', env)) expect(strategy.last_env['omniauth.origin']).to eq('http://example.com/sub_uri/origin') end end end end context 'default paths' do it 'uses the default request path' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env) end it 'is case insensitive on request path' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/AUTH/Test')) end it 'is case insensitive on callback path' do expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/AUTH/TeSt/CaLlBAck')) end it 'uses the default callback path' do expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test/callback')) end it 'strips trailing spaces on request' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test/')) end it 'strips trailing spaces on callback' do expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test/callback/')) end context 'callback_url' do it 'uses the default callback_path' do expect(strategy).to receive(:full_host).and_return('http://example.com') expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env) expect(strategy.callback_url).to eq('http://example.com/auth/test/callback') end it 'preserves the query parameters' do allow(strategy).to receive(:full_host).and_return('http://example.com') begin strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5')) rescue RuntimeError end expect(strategy.callback_url).to eq('http://example.com/auth/test/callback?id=5') end it 'consider script name' do allow(strategy).to receive(:full_host).and_return('http://example.com') begin strategy.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri')) rescue RuntimeError end expect(strategy.callback_url).to eq('http://example.com/sub_uri/auth/test/callback') end end end context ':form option' do it 'calls through to the supplied form option if one exists' do strategy.options.form = lambda { |_env| 'Called me!' } expect(strategy.call(make_env('/auth/test'))).to eq('Called me!') end it 'calls through to the app if :form => true is set as an option' do strategy.options.form = true expect(strategy.call(make_env('/auth/test'))).to eq(app.call(make_env('/auth/test'))) end end context 'dynamic paths' do it 'runs the request phase if the custom request path evaluator is truthy' do @options = {:request_path => lambda { |_env| true }} expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/asoufibasfi')) end it 'runs the callback phase if the custom callback path evaluator is truthy' do @options = {:callback_path => lambda { |_env| true }} expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/asoufiasod')) end it 'provides a custom callback path if request_path evals to a string' do strategy_instance = fresh_strategy.new(nil, :request_path => lambda { |_env| '/auth/boo/callback/22' }) expect(strategy_instance.callback_path).to eq('/auth/boo/callback/22') end it 'correctly reports the callback path when the custom callback path evaluator is truthy' do strategy_instance = ExampleStrategy.new(app, :callback_path => lambda { |env| env['PATH_INFO'] == '/auth/bish/bosh/callback' }) expect(strategy_instance).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy_instance.call(make_env('/auth/bish/bosh/callback')) expect(strategy_instance.callback_path).to eq('/auth/bish/bosh/callback') end end context 'custom paths' do it 'uses a custom request_path if one is provided' do @options = {:request_path => '/awesome'} expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/awesome')) end it 'uses a custom callback_path if one is provided' do @options = {:callback_path => '/radical'} expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/radical')) end context 'callback_url' do it 'uses a custom callback_path if one is provided' do @options = {:callback_path => '/radical'} expect(strategy).to receive(:full_host).and_return('http://example.com') expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/radical')) expect(strategy.callback_url).to eq('http://example.com/radical') end it 'preserves the query parameters' do @options = {:callback_path => '/radical'} allow(strategy).to receive(:full_host).and_return('http://example.com') begin strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5')) rescue RuntimeError end expect(strategy.callback_url).to eq('http://example.com/radical?id=5') end end end context 'custom prefix' do before do @options = {:path_prefix => '/wowzers'} end it 'uses a custom prefix for request' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/wowzers/test')) end it 'uses a custom prefix for callback' do expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/wowzers/test/callback')) end context 'callback_url' do it 'uses a custom prefix' do expect(strategy).to receive(:full_host).and_return('http://example.com') expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/wowzers/test')) expect(strategy.callback_url).to eq('http://example.com/wowzers/test/callback') end it 'preserves the query parameters' do allow(strategy).to receive(:full_host).and_return('http://example.com') begin strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5')) rescue RuntimeError end expect(strategy.callback_url).to eq('http://example.com/wowzers/test/callback?id=5') end end end context 'with relative url root' do let(:props) { {'SCRIPT_NAME' => '/myapp'} } it 'accepts the request' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test', props)) expect(strategy.request_path).to eq('/myapp/auth/test') end it 'accepts the callback' do expect(strategy).to receive(:fail!).with('Callback Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test/callback', props)) end context 'callback_url' do it 'redirects to the correctly prefixed callback' do expect(strategy).to receive(:full_host).and_return('http://example.com') expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test', props)) expect(strategy.callback_url).to eq('http://example.com/myapp/auth/test/callback') end end context 'custom request' do before do @options = {:request_path => '/myapp/override', :callback_path => '/myapp/override/callback'} end it 'does not prefix a custom request path' do expect(strategy).to receive(:full_host).and_return('http://example.com') expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) expect(strategy.request_path).to eq('/myapp/override') strategy.call(make_env('/override', props)) expect(strategy.callback_url).to eq('http://example.com/myapp/override/callback') end end context 'error during call_app!' do class OtherPhaseStrategy < ExampleStrategy def other_phase call_app! end end class AppError < StandardError; end let(:app) { ->(_env) { raise(AppError.new('Some error in the app!')) } } let(:strategy) { OtherPhaseStrategy.new(app) } it 'raises the application error' do expect { strategy.call(make_env('/some/path')) }.to raise_error(AppError, 'Some error in the app!') end end context 'error during auth phase' do class SomeStrategy < ExampleStrategy def request_phase raise AuthError.new('Some error in authentication') end end class AuthError < StandardError; end let(:strategy) { SomeStrategy.new(app) } it 'passes the error to fail!()' do expect(strategy).to receive(:fail!).with('Some error in authentication', kind_of(AuthError)) strategy.call(make_env('/auth/test', props)) end end end context 'request method restriction' do before(:context) do OmniAuth.config.allowed_request_methods = %i[put post] end it 'does not allow a request method of the wrong type' do expect { strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'GET')) }.not_to raise_error end it 'allows a request method of the correct type' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(make_env('/auth/test')) end after(:context) do OmniAuth.config.allowed_request_methods = %i[post] end end context 'receiving an OPTIONS request' do shared_examples_for 'an OPTIONS request' do it 'responds with 200' do expect(response[0]).to eq(200) end it 'sets the Allow header properly' do expect(response[1]['Allow']).to eq('POST') end end context 'to the request path' do let(:response) { strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'OPTIONS')) } it_behaves_like 'an OPTIONS request' end context 'to the request path' do let(:response) { strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'OPTIONS')) } it_behaves_like 'an OPTIONS request' end context 'to some other path' do it 'does not short-circuit the request' do env = make_env('/other', 'REQUEST_METHOD' => 'OPTIONS') expect(strategy.call(env)).to eq(app.call(env)) end end end context 'options mutation' do before do @options = {:dup => true} end context 'in request phase' do it 'does not affect original options' do @options[:test_option] = true @options[:mutate_on_request] = proc { |options| options.delete(:test_option) } strategy.call(make_env) expect(strategy.options).to have_key(:test_option) end it 'does not affect deep options' do @options[:deep_option] = {:test_option => true} @options[:mutate_on_request] = proc { |options| options[:deep_option].delete(:test_option) } strategy.call(make_env) expect(strategy.options[:deep_option]).to have_key(:test_option) end end context 'in callback phase' do it 'does not affect original options' do @options[:test_option] = true @options[:mutate_on_callback] = proc { |options| options.delete(:test_option) } strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'POST')) expect(strategy.options).to have_key(:test_option) end it 'does not affect deep options' do @options[:deep_option] = {:test_option => true} @options[:mutate_on_callback] = proc { |options| options[:deep_option].delete(:test_option) } strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'POST')) expect(strategy.options[:deep_option]).to have_key(:test_option) end end end context 'test mode' do let(:app) do # In test mode, the underlying app shouldn't be called on request phase. lambda { |_env| [404, {'Content-Type' => 'text/html'}, []] } end before do OmniAuth.config.test_mode = true end it 'short circuits the request phase entirely' do response = strategy.call(make_env) expect(response[0]).to eq(302) expect(response[1]['Location']).to eq('/auth/test/callback') end it "doesn't short circuit the request if request method is not allowed" do response = strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'DELETE')) expect(response[0]).to eq(404) end it 'is case insensitive on request path' do expect(strategy.call(make_env('/AUTH/Test'))[0]).to eq(302) end it 'respects SCRIPT_NAME (a.k.a. BaseURI)' do response = strategy.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri')) expect(response[1]['Location']).to eq('/sub_uri/auth/test/callback') end it 'redirects on failure' do response = OmniAuth.config.on_failure.call(make_env('/auth/test', 'omniauth.error.type' => 'error')) expect(response[0]).to eq(302) expect(response[1]['Location']).to eq('/auth/failure?message=error') end it 'respects SCRIPT_NAME (a.k.a. BaseURI) on failure' do response = OmniAuth.config.on_failure.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri', 'omniauth.error.type' => 'error')) expect(response[0]).to eq(302) expect(response[1]['Location']).to eq('/sub_uri/auth/failure?message=error') end it 'is case insensitive on callback path' do expect(strategy.call(make_env('/AUTH/TeSt/CaLlBAck')).first).to eq(strategy.call(make_env('/auth/test/callback')).first) end it 'maintains host and port' do response = strategy.call(make_env('/auth/test', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'example.org', 'SERVER_PORT' => 9292)) expect(response[1]['Location']).to eq('http://example.org:9292/auth/test/callback') end it 'maintains query string parameters' do response = strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'cheese=stilton')) expect(response[1]['Location']).to eq('/auth/test/callback?cheese=stilton') end it 'does not short circuit requests outside of authentication' do expect(strategy.call(make_env('/'))).to eq(app.call(make_env('/'))) end it 'responds with the default hash if none is set' do OmniAuth.config.mock_auth[:test] = nil strategy.call make_env('/auth/test/callback') expect(strategy.env['omniauth.auth']['uid']).to eq('1234') end it 'responds with a provider-specific hash if one is set' do OmniAuth.config.mock_auth[:test] = { 'uid' => 'abc' } strategy.call make_env('/auth/test/callback') expect(strategy.env['omniauth.auth']['uid']).to eq('abc') end it 'simulates login failure if mocked data is set as a symbol' do OmniAuth.config.mock_auth[:test] = :invalid_credentials strategy.call make_env('/auth/test/callback') expect(strategy.env['omniauth.error.type']).to eq(:invalid_credentials) end context 'omniauth.origin' do context 'disabled' do it 'does not set omniauth.origin' do @options = {:origin_param => false} strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin')) expect(strategy.env['rack.session']['omniauth.origin']).to be_nil end end context 'default flow' do it 'sets omniauth.origin to the HTTP_REFERER on the request phase by default' do strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin')) expect(strategy.env['rack.session']['omniauth.origin']).to eq('http://example.com/origin') end it 'sets omniauth.origin from the params if provided' do strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo')) expect(strategy.env['rack.session']['omniauth.origin']).to eq('/foo') end end context 'custom' do it 'sets omniauth.origin from a custom param' do @options = {:origin_param => 'return'} strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'return=/foo')) expect(strategy.env['rack.session']['omniauth.origin']).to eq('/foo') end end end it 'turns omniauth.origin into an env variable on the callback phase' do OmniAuth.config.mock_auth[:test] = {} strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'})) expect(strategy.env['omniauth.origin']).to eq('http://example.com/origin') end it 'executes callback hook on the callback phase' do OmniAuth.config.mock_auth[:test] = {} OmniAuth.config.before_callback_phase do |env| env['foobar'] = 'baz' end strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'})) expect(strategy.env['foobar']).to eq('baz') end it 'sets omniauth.params with query params on the request phase' do OmniAuth.config.mock_auth[:test] = {} strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'foo=bar')) expect(strategy.env['rack.session']['omniauth.params']).to eq('foo' => 'bar') end it 'does not set body parameters of POST request on the request phase' do OmniAuth.config.mock_auth[:test] = {} props = { 'REQUEST_METHOD' => 'POST', 'rack.input' => StringIO.new('foo=bar') } strategy.call(make_env('/auth/test', props)) expect(strategy.env['rack.session']['omniauth.params']).to eq({}) end it 'executes request hook on the request phase' do OmniAuth.config.mock_auth[:test] = {} OmniAuth.config.before_request_phase do |env| env['foobar'] = 'baz' end strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'foo=bar')) expect(strategy.env['foobar']).to eq('baz') end it 'turns omniauth.params into an env variable on the callback phase' do OmniAuth.config.mock_auth[:test] = {} strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.params' => {'foo' => 'bar'}})) expect(strategy.env['omniauth.params']).to eq('foo' => 'bar') end it 'rescues errors in request_call' do allow(strategy).to receive(:mock_request_call).and_raise(StandardError.new('Oh no')) expect(strategy).to receive(:fail!).with('Oh no', kind_of(StandardError)) strategy.call(make_env) end after do OmniAuth.config.test_mode = false end end context 'custom full_host' do before do OmniAuth.config.test_mode = true end it 'is the string when a string is there' do OmniAuth.config.full_host = 'my.host.com' expect(strategy.full_host).to eq('my.host.com') end it 'runs the proc with the env when it is a proc' do OmniAuth.config.full_host = proc { |env| env['HOST'] } strategy.call(make_env('/auth/test', 'HOST' => 'my.host.net')) expect(strategy.full_host).to eq('my.host.net') end it "is based on the request if it's not a string nor a proc" do OmniAuth.config.full_host = nil strategy.call(make_env('/whatever', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'my.host.net', 'SERVER_PORT' => 80)) expect(strategy.full_host).to eq('http://my.host.net') end it 'honors HTTP_X_FORWARDED_PROTO if present' do OmniAuth.config.full_host = nil strategy.call(make_env('/whatever', 'HTTP_X_FORWARDED_PROTO' => 'https', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'my.host.net', 'SERVER_PORT' => 443)) expect(strategy.full_host).to eq('https://my.host.net') end after do OmniAuth.config.full_host = nil OmniAuth.config.test_mode = false end end context 'authenticity validation' do let(:app) { lambda { |_env| [200, {}, ['reached our target']] } } let(:strategy) { ExampleStrategy.new(app, :request_path => '/auth/test') } before do OmniAuth.config.request_validation_phase = OmniAuth::AuthenticityTokenProtection end context 'with default POST only request methods' do let!(:csrf_token) { SecureRandom.base64(32) } let(:escaped_token) { URI.encode_www_form_component(csrf_token, Encoding::UTF_8) } it 'allows a request with matching authenticity_token' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) post_env = make_env('/auth/test', 'rack.session' => {:csrf => csrf_token}, 'rack.input' => StringIO.new("authenticity_token=#{escaped_token}")) strategy.call(post_env) end it 'does not allow a request without a matching authenticity token' do post_env = make_env('/auth/test', 'rack.input' => StringIO.new("authenticity_token=#{escaped_token}")) expect(strategy.call(post_env)[0]).to eq(302) expect(strategy.call(post_env)[2]).to eq(['302 Moved']) end end context 'with allowed GET' do let(:path) { '/auth/test' } let(:get_env) { make_env(path, 'REQUEST_METHOD' => 'GET') } before(:context) do @old_allowed_request_methods = OmniAuth.config.allowed_request_methods OmniAuth.config.allowed_request_methods = %i[post get] end it 'allows a request without authenticity token' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) strategy.call(get_env) end describe 'warning message logging' do before { allow(strategy).to receive(:log) } it 'logs warning message' do strategy.call(get_env) expect(strategy).to have_received(:log).with(:warn, a_string_matching('You are using GET as an allowed request method')).once end context 'when not login path is requested' do let(:path) { '/example/path' } it 'does not log warning message' do strategy.call(get_env) expect(strategy).not_to have_received(:log).with(:warn, a_string_matching('You are using GET as an allowed request method')) end end end after(:context) do OmniAuth.config.allowed_request_methods = @old_allowed_request_methods end end context 'with custom allow_if proc' do before do OmniAuth.config.request_validation_phase = OmniAuth::AuthenticityTokenProtection.new(allow_if: ->(env) { true }) end it 'allows a valid request' do expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError)) post_env = make_env('/auth/test') strategy.call(post_env) end end after do OmniAuth.config.request_validation_phase = nil end end it 'calls fail! when encountering an unhandled exception' do allow(strategy).to receive(:request_phase).and_raise(Errno::ECONNREFUSED) expect(strategy).to receive(:fail!).with('Connection refused', kind_of(Errno::ECONNREFUSED)) strategy.call(make_env) end it 'redirects to the fail! result when encountering an unhandled exception' do OmniAuth.config.test_mode = false expect(strategy.call(make_env).first).to eq 302 end context 'when in test mode and path not on request path' do let(:path) { '/foo/bar' } before do OmniAuth.config.test_mode = true OmniAuth.config.request_validation_phase = OmniAuth::AuthenticityTokenProtection allow(OmniAuth::AuthenticityTokenProtection).to receive(:call).and_raise(OmniAuth::AuthenticityError) end it 'does not verify token' do expect(strategy).not_to receive(:fail!) strategy.call(make_env(path)) end after do OmniAuth.config.test_mode = false OmniAuth.config.request_validation_phase = false end end end context 'setup phase' do before do OmniAuth.config.test_mode = true end context 'when options[:setup] = true' do let(:strategy) do ExampleStrategy.new(app, :setup => true) end let(:app) do lambda do |env| env['omniauth.strategy'].options[:awesome] = 'sauce' if env['PATH_INFO'] == '/auth/test/setup' [404, {}, 'Awesome'] end end it 'calls through to /auth/:provider/setup' do strategy.call(make_env('/auth/test')) expect(strategy.options[:awesome]).to eq('sauce') end it 'does not call through on a non-omniauth endpoint' do strategy.call(make_env('/somewhere/else')) expect(strategy.options[:awesome]).not_to eq('sauce') end end context 'when options[:setup] is an app' do let(:setup_proc) do proc do |env| env['omniauth.strategy'].options[:awesome] = 'sauce' end end let(:strategy) { ExampleStrategy.new(app, :setup => setup_proc) } it 'does not call the app on a non-omniauth endpoint' do strategy.call(make_env('/somehwere/else')) expect(strategy.options[:awesome]).not_to eq('sauce') end it 'calls the rack app' do strategy.call(make_env('/auth/test')) expect(strategy.options[:awesome]).to eq('sauce') end end after do OmniAuth.config.test_mode = false end end end omniauth-2.1.1/spec/omniauth/failure_endpoint_spec.rb0000644000175000017500000000447114362554334022350 0ustar nileshnileshrequire 'helper' describe OmniAuth::FailureEndpoint do subject { OmniAuth::FailureEndpoint } context 'raise-out environment' do before do @rack_env = ENV['RACK_ENV'] ENV['RACK_ENV'] = 'test' @default = OmniAuth.config.failure_raise_out_environments OmniAuth.config.failure_raise_out_environments = ['test'] end it 'raises out the error' do expect do subject.call('omniauth.error' => StandardError.new('Blah')) end.to raise_error(StandardError, 'Blah') end it 'raises out an OmniAuth::Error if no omniauth.error is set' do expect { subject.call('omniauth.error.type' => 'example') }.to raise_error(OmniAuth::Error, 'example') end after do ENV['RACK_ENV'] = @rack_env OmniAuth.config.failure_raise_out_environments = @default end end context 'non-raise-out environment' do let(:env) do {'omniauth.error.type' => 'invalid_request', 'omniauth.error.strategy' => ExampleStrategy.new({})} end it 'is a redirect' do status, = *subject.call(env) expect(status).to eq(302) end it 'includes the SCRIPT_NAME' do _, head, = *subject.call(env.merge('SCRIPT_NAME' => '/random')) expect(head['Location']).to eq('/random/auth/failure?message=invalid_request&strategy=test') end it 'respects the globally configured path prefix' do allow(OmniAuth.config).to receive(:path_prefix).and_return('/boo') _, head, = *subject.call(env) expect(head['Location']).to eq('/boo/failure?message=invalid_request&strategy=test') end it 'respects the custom path prefix configured on the strategy' do env['omniauth.error.strategy'] = ExampleStrategy.new({}, path_prefix: "/some/custom/path") _, head, = *subject.call(env) expect(head['Location']).to eq('/some/custom/path/failure?message=invalid_request&strategy=test') end it 'includes the origin (escaped) if one is provided' do env['omniauth.origin'] = '/origin-example' _, head, = *subject.call(env) expect(head['Location']).to be_include('&origin=%2Forigin-example') end it 'escapes the message key' do _, head = *subject.call(env.merge('omniauth.error.type' => 'Connection refused!')) expect(head['Location']).to be_include('message=Connection+refused%21') end end end omniauth-2.1.1/spec/omniauth/auth_hash_spec.rb0000644000175000017500000001040514362554334020757 0ustar nileshnileshrequire 'helper' describe OmniAuth::AuthHash do subject { OmniAuth::AuthHash.new } it 'converts a supplied info key into an InfoHash object' do subject.info = {:first_name => 'Awesome'} expect(subject.info).to be_kind_of(OmniAuth::AuthHash::InfoHash) expect(subject.info.first_name).to eq('Awesome') end it 'does not try to parse `string` as InfoHash' do subject.weird_field = {:info => 'string'} expect(subject.weird_field.info).to eq 'string' end it 'has a subkey_class' do expect(OmniAuth::AuthHash.subkey_class).to eq Hashie::Mash end describe '#valid?' do subject { OmniAuth::AuthHash.new(:uid => '123', :provider => 'example', :info => {:name => 'Steven'}) } it 'is valid with the right parameters' do expect(subject).to be_valid end it 'requires a uid' do subject.uid = nil expect(subject).not_to be_valid end it 'requires a provider' do subject.provider = nil expect(subject).not_to be_valid end it 'requires a name in the user info hash' do subject.info.name = nil expect(subject).not_to be_valid end end describe '#name' do subject do OmniAuth::AuthHash.new(:info => { :name => 'Phillip J. Fry', :first_name => 'Phillip', :last_name => 'Fry', :nickname => 'meatbag', :email => 'fry@planetexpress.com' }) end it 'defaults to the name key' do expect(subject.info.name).to eq('Phillip J. Fry') end it 'falls back to go to first_name last_name concatenation' do subject.info.name = nil expect(subject.info.name).to eq('Phillip Fry') end it 'displays only a first or last name if only that is available' do subject.info.name = nil subject.info.first_name = nil expect(subject.info.name).to eq('Fry') end it 'displays the nickname if no name, first, or last is available' do subject.info.name = nil %w[first_name last_name].each { |k| subject.info[k] = nil } expect(subject.info.name).to eq('meatbag') end it 'displays the email if no name, first, last, or nick is available' do subject.info.name = nil %w[first_name last_name nickname].each { |k| subject.info[k] = nil } expect(subject.info.name).to eq('fry@planetexpress.com') end end describe '#to_hash' do subject { OmniAuth::AuthHash.new(:uid => '123', :provider => 'test', :name => 'Example User') } let(:hash) { subject.to_hash } it 'is a plain old hash' do expect(hash.class).to eq(::Hash) end it 'has string keys' do expect(hash.keys).to be_include('uid') end it 'converts an info hash as well' do subject.info = {:first_name => 'Example', :last_name => 'User'} expect(subject.info.class).to eq(OmniAuth::AuthHash::InfoHash) expect(subject.to_hash['info'].class).to eq(::Hash) end it 'supplies the calculated name in the converted hash' do subject.info = {:first_name => 'Examplar', :last_name => 'User'} expect(hash['info']['name']).to eq('Examplar User') end it "does not pollute the URL hash with 'name' etc" do subject.info = {'urls' => {'Homepage' => 'http://homepage.com'}} expect(subject.to_hash['info']['urls']).to eq('Homepage' => 'http://homepage.com') end end describe OmniAuth::AuthHash::InfoHash do describe '#valid?' do it 'is valid if there is a name' do expect(OmniAuth::AuthHash::InfoHash.new(:name => 'Awesome')).to be_valid end end it 'has a subkey_class' do expect(OmniAuth::AuthHash::InfoHash.subkey_class).to eq Hashie::Mash end require 'hashie/version' if Gem::Version.new(Hashie::VERSION) >= Gem::Version.new('3.5.1') context 'with Hashie 3.5.1+' do around(:each) do |example| original_logger = Hashie.logger example.run Hashie.logger = original_logger end it 'does not log anything in Hashie 3.5.1+' do logger = double('Logger') expect(logger).not_to receive(:warn) Hashie.logger = logger subject.name = 'test' end end end end end omniauth-2.1.1/spec/omniauth/form_spec.rb0000644000175000017500000000341514362554334017761 0ustar nileshnileshrequire 'helper' describe OmniAuth::Form do describe '.build' do it 'yields the instance when called with a block and argument' do OmniAuth::Form.build { |f| expect(f).to be_kind_of(OmniAuth::Form) } end it 'evaluates in the instance when called with a block and no argument' do f = OmniAuth::Form.build { @html = '

OmniAuth

' } expect(f.instance_variable_get(:@html)).to eq('

OmniAuth

') end end describe '#initialize' do it 'sets the form action to the passed :url option' do expect(OmniAuth::Form.new(:url => '/awesome').to_html).to be_include("action='/awesome'") end it 'sets an H1 tag from the passed :title option' do expect(OmniAuth::Form.new(:title => 'Something Cool').to_html).to be_include('

Something Cool

') end end describe '#password_field' do it 'adds a labeled input field' do form = OmniAuth::Form.new.password_field('pass', 'password') form_html = form.to_html expect(form_html).to include('') expect(form_html).to include('') end end describe '#html' do it 'appends to the html body' do form = OmniAuth::Form.build { @html = +'

' } form.html('

') expect(form.instance_variable_get(:@html)).to eq '

' end end describe 'fieldset' do it 'creates a fieldset with options' do form = OmniAuth::Form.new options = {:style => 'color: red', :id => 'fieldSetId'} expected = "
\n legendary\n\n
" form.fieldset('legendary', options) {} expect(form.to_html).to include expected end end end omniauth-2.1.1/spec/omniauth/key_store_spec.rb0000644000175000017500000000400114362554334021012 0ustar nileshnileshrequire 'helper' RSpec.describe OmniAuth::KeyStore do let(:logger) { double('Logger') } around(:each) do |example| patched = monkey_patch_logger example.run remove_logger(patched) end context 'on Hashie < 3.5.0' do let(:version) { '3.4.0' } it 'does not log anything to the console' do stub_const('Hashie::VERSION', version) OmniAuth::KeyStore.override_logging expect(logger).not_to receive(:info) OmniAuth::KeyStore.new(:id => 1234) end end context 'on Hashie 3.5.0 and 3.5.1' do let(:version) { '3.5.0' } it 'does not log anything to the console' do stub_const('Hashie::VERSION', version) allow(OmniAuth::KeyStore).to receive(:respond_to?).with(:disable_warnings).and_return(false) OmniAuth::KeyStore.override_logging expect(logger).not_to receive(:info) OmniAuth::KeyStore.new(:id => 1234) end end context 'on Hashie 3.5.2+' do let(:version) { '3.5.2' } around(:each) do |example| patching = monkey_patch_unreleased_interface example.run remove_monkey_patch(patching) end it 'does not log anything to the console' do stub_const('Hashie::VERSION', version) OmniAuth::KeyStore.override_logging expect(logger).not_to receive(:info) OmniAuth::KeyStore.new(:id => 1234) end end def monkey_patch_unreleased_interface return false if OmniAuth::KeyStore.class.respond_to?(:disable_warnings, true) OmniAuth::KeyStore.define_singleton_method(:disable_warnings) {} OmniAuth::KeyStore.define_singleton_method(:log_built_in_message) { |*| } true end def monkey_patch_logger return unless Hashie.respond_to?(:logger) original_logger = Hashie.logger Hashie.logger = logger original_logger end def remove_logger(logger) return unless logger Hashie.logger = logger end def remove_monkey_patch(perform) return unless perform OmniAuth::KeyStore.singleton_class.__send__(:remove_method, :disable_warnings) end end omniauth-2.1.1/spec/omniauth_spec.rb0000644000175000017500000001320514362554334017014 0ustar nileshnileshrequire 'helper' describe OmniAuth do describe '.strategies' do it 'increases when a new strategy is made' do expect do class ExampleStrategy include OmniAuth::Strategy end end.to change(OmniAuth.strategies, :size).by(1) expect(OmniAuth.strategies.last).to eq(ExampleStrategy) end end context 'configuration' do describe '.defaults' do it 'is a hash of default configuration' do expect(OmniAuth::Configuration.defaults).to be_kind_of(Hash) end end it 'is callable from .configure' do OmniAuth.configure do |c| expect(c).to be_kind_of(OmniAuth::Configuration) end end before do @old_path_prefix = OmniAuth.config.path_prefix @old_on_failure = OmniAuth.config.on_failure @old_before_callback_phase = OmniAuth.config.before_callback_phase @old_before_options_phase = OmniAuth.config.before_options_phase @old_before_request_phase = OmniAuth.config.before_request_phase @old_request_validation_phase = OmniAuth.config.request_validation_phase end after do OmniAuth.configure do |config| config.path_prefix = @old_path_prefix config.on_failure = @old_on_failure config.before_callback_phase = @old_before_callback_phase config.before_options_phase = @old_before_options_phase config.before_request_phase = @old_before_request_phase config.request_validation_phase = @old_request_validation_phase end end it 'is able to set the path' do OmniAuth.configure do |config| config.path_prefix = '/awesome' end expect(OmniAuth.config.path_prefix).to eq('/awesome') end it 'is able to set the on_failure rack app' do OmniAuth.configure do |config| config.on_failure do 'yoyo' end end expect(OmniAuth.config.on_failure.call).to eq('yoyo') end it 'is able to set hook on option_call' do OmniAuth.configure do |config| config.before_options_phase do 'yoyo' end end expect(OmniAuth.config.before_options_phase.call).to eq('yoyo') end it 'is able to set hook on request_call' do OmniAuth.configure do |config| config.before_request_phase do 'heyhey' end end expect(OmniAuth.config.before_request_phase.call).to eq('heyhey') end it 'is able to set hook on callback_call' do OmniAuth.configure do |config| config.before_callback_phase do 'heyhey' end end expect(OmniAuth.config.before_callback_phase.call).to eq('heyhey') end it 'is able to set request_validation_phase' do OmniAuth.configure do |config| config.request_validation_phase do 'validated' end end expect(OmniAuth.config.request_validation_phase.call).to eq('validated') end describe 'mock auth' do before do @auth_hash = {:uid => '12345', :info => {:name => 'Joe', :email => 'joe@example.com'}} @original_auth_hash = @auth_hash.dup OmniAuth.config.add_mock(:facebook, @auth_hash) end it 'default is AuthHash' do OmniAuth.configure do |config| expect(config.mock_auth[:default]).to be_kind_of(OmniAuth::AuthHash) end end it 'facebook is AuthHash' do OmniAuth.configure do |config| expect(config.mock_auth[:facebook]).to be_kind_of(OmniAuth::AuthHash) end end it 'sets facebook attributes' do OmniAuth.configure do |config| expect(config.mock_auth[:facebook].uid).to eq('12345') expect(config.mock_auth[:facebook].info.name).to eq('Joe') expect(config.mock_auth[:facebook].info.email).to eq('joe@example.com') end end it 'does not mutate given auth hash' do OmniAuth.configure do expect(@auth_hash).to eq @original_auth_hash end end end end describe '.logger' do it 'calls through to the configured logger' do allow(OmniAuth).to receive(:config).and_return(double(:logger => 'foo')) expect(OmniAuth.logger).to eq('foo') end end describe '::Utils' do describe 'form_css' do it 'returns a style tag with the configured form_css' do allow(OmniAuth).to receive(:config).and_return(double(:form_css => 'css.css')) expect(OmniAuth::Utils.form_css).to eq "" end end describe '.deep_merge' do it 'combines hashes' do expect(OmniAuth::Utils.deep_merge({'abc' => {'def' => 123}}, 'abc' => {'foo' => 'bar'})).to eq('abc' => {'def' => 123, 'foo' => 'bar'}) end end describe '.camelize' do it 'works on normal cases' do { 'some_word' => 'SomeWord', 'AnotherWord' => 'AnotherWord', 'one' => 'One', 'three_words_now' => 'ThreeWordsNow' }.each_pair { |k, v| expect(OmniAuth::Utils.camelize(k)).to eq(v) } end it 'works in special cases that have been added' do OmniAuth.config.add_camelization('oauth', 'OAuth') expect(OmniAuth::Utils.camelize(:oauth)).to eq('OAuth') end it 'doesn\'t uppercase the first letter when passed false' do expect(OmniAuth::Utils.camelize('apple_jack', false)).to eq('appleJack') end it 'replaces / with ::' do expect(OmniAuth::Utils.camelize('apple_jack/cereal')).to eq('AppleJack::Cereal') expect(OmniAuth::Utils.camelize('apple_jack/cereal', false)).to eq('appleJack::Cereal') end end end end omniauth-2.1.1/README.md0000644000175000017500000002610314362554334014157 0ustar nileshnilesh# OmniAuth: Standardized Multi-Provider Authentication [![Gem Version](http://img.shields.io/gem/v/omniauth.svg)][gem] [![Ruby](https://github.com/omniauth/omniauth/actions/workflows/main.yml/badge.svg)][githubactions] [![TruffleRuby](https://github.com/omniauth/omniauth/actions/workflows/truffle_ruby.yml/badge.svg)][githubactionstruffle] [![JRuby](https://github.com/omniauth/omniauth/actions/workflows/jruby.yml/badge.svg)][githubactionsjruby] [![Code Climate](https://api.codeclimate.com/v1/badges/ffd33970723587806744/maintainability)][codeclimate] [![Coverage Status](http://img.shields.io/coveralls/omniauth/omniauth.svg)][coveralls] [gem]: https://rubygems.org/gems/omniauth [githubactions]: https://github.com/omniauth/omniauth/actions/workflows/main.yml [githubactionstruffle]: https://github.com/omniauth/omniauth/actions/workflows/truffle_ruby.yml [githubactionsjruby]: https://github.com/omniauth/omniauth/actions/workflows/jruby.yml [codeclimate]: https://codeclimate.com/github/omniauth/omniauth [coveralls]: https://coveralls.io/r/omniauth/omniauth This is the documentation for the in-development branch of OmniAuth. You can find the documentation for the latest stable release [here](https://github.com/omniauth/omniauth/tree/v2.1.1) ## An Introduction OmniAuth is a library that standardizes multi-provider authentication for web applications. It was created to be powerful, flexible, and do as little as possible. Any developer can create **strategies** for OmniAuth that can authenticate users via disparate systems. OmniAuth strategies have been created for everything from Facebook to LDAP. In order to use OmniAuth in your applications, you will need to leverage one or more strategies. These strategies are generally released individually as RubyGems, and you can see a [community maintained list](https://github.com/omniauth/omniauth/wiki/List-of-Strategies) on the wiki for this project. One strategy, called `Developer`, is included with OmniAuth and provides a completely insecure, non-production-usable strategy that directly prompts a user for authentication information and then passes it straight through. You can use it as a placeholder when you start development and easily swap in other strategies later. ## Getting Started Each OmniAuth strategy is a Rack Middleware. That means that you can use it the same way that you use any other Rack middleware. For example, to use the built-in Developer strategy in a Sinatra application you might do this: ```ruby require 'sinatra' require 'omniauth' class MyApplication < Sinatra::Base use Rack::Session::Cookie use OmniAuth::Strategies::Developer end ``` Because OmniAuth is built for *multi-provider* authentication, you may want to leave room to run multiple strategies. For this, the built-in `OmniAuth::Builder` class gives you an easy way to specify multiple strategies. Note that there is **no difference** between the following code and using each strategy individually as middleware. This is an example that you might put into a Rails initializer at `config/initializers/omniauth.rb`: ```ruby Rails.application.config.middleware.use OmniAuth::Builder do provider :developer unless Rails.env.production? provider :twitter, ENV['TWITTER_KEY'], ENV['TWITTER_SECRET'] end ``` You should look to the documentation for each provider you use for specific initialization requirements. ## Integrating OmniAuth Into Your Application OmniAuth is an extremely low-touch library. It is designed to be a black box that you can send your application's users into when you need authentication and then get information back. OmniAuth was intentionally built not to automatically associate with a User model or make assumptions about how many authentication methods you might want to use or what you might want to do with the data once a user has authenticated. This makes OmniAuth incredibly flexible. To use OmniAuth, you need only to redirect users to `/auth/:provider`, where `:provider` is the name of the strategy (for example, `developer` or `twitter`). From there, OmniAuth will take over and take the user through the necessary steps to authenticate them with the chosen strategy. Once the user has authenticated, what do you do next? OmniAuth simply sets a special hash called the Authentication Hash on the Rack environment of a request to `/auth/:provider/callback`. This hash contains as much information about the user as OmniAuth was able to glean from the utilized strategy. You should set up an endpoint in your application that matches to the callback URL and then performs whatever steps are necessary for your application. The `omniauth.auth` key in the environment hash provides an Authentication Hash which will contain information about the just authenticated user including a unique id, the strategy they just used for authentication, and personal details such as name and email address as available. For an in-depth description of what the authentication hash might contain, see the [Auth Hash Schema wiki page](https://github.com/omniauth/omniauth/wiki/Auth-Hash-Schema). Note that OmniAuth does not perform any actions beyond setting some environment information on the callback request. It is entirely up to you how you want to implement the particulars of your application's authentication flow. ## rack_csrf `omniauth` is not OOTB-compatible with [rack_csrf](https://github.com/baldowl/rack_csrf). In order to do so, the following code needs to be added to the application bootstrapping code: ```ruby OmniAuth::AuthenticityTokenProtection.default_options(key: "csrf.token", authenticity_param: "_csrf") ``` ## Rails (without Devise) To get started, add the following gems **Gemfile**: ```ruby gem 'omniauth' gem "omniauth-rails_csrf_protection" ``` Then insert OmniAuth as a middleware **config/initializers/omniauth.rb**: ```ruby Rails.application.config.middleware.use OmniAuth::Builder do provider :developer if Rails.env.development? end ``` Additional providers can be added here in the future. Next we wire it all up using routes, a controller and a login view. **config/routes.rb**: ```ruby get 'auth/:provider/callback', to: 'sessions#create' get '/login', to: 'sessions#new' ``` **app/controllers/sessions_controller.rb**: ```ruby class SessionsController < ApplicationController def new render :new end def create user_info = request.env['omniauth.auth'] raise user_info # Your own session management should be placed here. end end ``` **app/views/sessions/new.html.erb**: ```erb <%= form_tag('/auth/developer', method: 'post', data: {turbo: false}) do %> <% end %> ``` Now if you visit `/login` and click the Login button, you should see the OmniAuth developer login screen. After submitting it, you are returned to your application at `Sessions#create`. The raise should now display all the Omniauth details you have available to integrate it into your own user management. If you want out of the box usermanagement, you should consider using Omniauth through Devise. Please visit the [Devise Github page](https://github.com/heartcombo/devise#omniauth) for more information. ## Rails API The following middleware are (by default) included for session management in Rails applications. When using OmniAuth with a Rails API, you'll need to add one of these required middleware back in: - `ActionDispatch::Session::CacheStore` - `ActionDispatch::Session::CookieStore` - `ActionDispatch::Session::MemCacheStore` The trick to adding these back in is that, by default, they are passed `session_options` when added (including the session key), so you can't just add a `session_store.rb` initializer, add `use ActionDispatch::Session::CookieStore` and have sessions functioning as normal. To be clear: sessions may work, but your session options will be ignored (i.e. the session key will default to `_session_id`). Instead of the initializer, you'll have to set the relevant options somewhere before your middleware is built (like `application.rb`) and pass them to your preferred middleware, like this: **application.rb:** ```ruby config.session_store :cookie_store, key: '_interslice_session' config.middleware.use ActionDispatch::Cookies # Required for all session management config.middleware.use ActionDispatch::Session::CookieStore, config.session_options ``` (Thanks @mltsy) ## Logging OmniAuth supports a configurable logger. By default, OmniAuth will log to `STDOUT` but you can configure this using `OmniAuth.config.logger`: ```ruby # Rails application example OmniAuth.config.logger = Rails.logger ``` ## Origin Param The `origin` url parameter is typically used to inform where a user came from and where, should you choose to use it, they'd want to return to. Omniauth supports the following settings which can be configured on a provider level: **Default**: ```ruby provider :twitter, ENV['KEY'], ENV['SECRET'] POST /auth/twitter/?origin=[URL] # If the `origin` parameter is blank, `omniauth.origin` is set to HTTP_REFERER ``` **Using a differently named origin parameter**: ```ruby provider :twitter, ENV['KEY'], ENV['SECRET'], origin_param: 'return_to' POST /auth/twitter/?return_to=[URL] # If the `return_to` parameter is blank, `omniauth.origin` is set to HTTP_REFERER ``` **Disabled**: ```ruby provider :twitter, ENV['KEY'], ENV['SECRET'], origin_param: false POST /auth/twitter # This means the origin should be handled by your own application. # Note that `omniauth.origin` will always be blank. ``` ## Resources The [OmniAuth Wiki](https://github.com/omniauth/omniauth/wiki) has actively maintained in-depth documentation for OmniAuth. It should be your first stop if you are wondering about a more in-depth look at OmniAuth, how it works, and how to use it. ## OmniAuth for Enterprise Available as part of the Tidelift Subscription. The maintainers of OmniAuth and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source packages you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact packages you use. [Learn more.](https://tidelift.com/subscription/pkg/rubygems-omniauth?utm_source=undefined&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) ## Supported Ruby Versions OmniAuth is tested under 2.5, 2.6, 2.7, truffleruby, and JRuby. ## Versioning This library aims to adhere to [Semantic Versioning 2.0.0][semver]. Violations of this scheme should be reported as bugs. Specifically, if a minor or patch version is released that breaks backward compatibility, that version should be immediately yanked and/or a new version should be immediately released that restores compatibility. Breaking changes to the public API will only be introduced with new major versions. As a result of this policy, you can (and should) specify a dependency on this gem using the [Pessimistic Version Constraint][pvc] with two digits of precision. For example: spec.add_dependency 'omniauth', '~> 1.0' [semver]: http://semver.org/ [pvc]: http://guides.rubygems.org/patterns/#pessimistic-version-constraint ## License Copyright (c) 2010-2017 Michael Bleigh and Intridea, Inc. See [LICENSE][] for details. [license]: LICENSE.md omniauth-2.1.1/SECURITY.md0000644000175000017500000000102114362554334014461 0ustar nileshnilesh# Security Policy ## Supported Versions Use this section to tell people about which versions of your project are currently being supported with security updates. | Version | Supported | | ------- | ------------------ | | 2.1.x | :white_check_mark: | | 2.0.x | :white_check_mark: | | <= 1.9.1 | :x: | ## Security contact information To report a security vulnerability, please use the [Tidelift security contact](https://tidelift.com/security). Tidelift will coordinate the fix and disclosure. omniauth-2.1.1/LICENSE.md0000644000175000017500000000207214362554334014303 0ustar nileshnileshCopyright (c) 2010-2017 Michael Bleigh and Intridea, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. omniauth-2.1.1/Gemfile0000644000175000017500000000144114362554334014171 0ustar nileshnileshsource 'https://rubygems.org' gem 'jruby-openssl', '~> 0.10.5', platforms: :jruby gem 'rake', '>= 12.0' gem 'yard', '>= 0.9.11' group :development do gem 'benchmark-ips' gem 'kramdown' gem 'memory_profiler' gem 'pry' end group :test do gem 'coveralls_reborn', '~> 0.19.0', require: false gem 'hashie', '>= 3.4.6', '~> 4.0.0', platforms: [:jruby_18] gem 'json', '~> 2.3.0', platforms: %i[jruby_18 jruby_19 ruby_19] gem 'mime-types', '~> 3.1', platforms: [:jruby_18] gem 'rack-test' gem 'rest-client', '~> 2.0.0', platforms: [:jruby_18] gem 'rspec', '~> 3.5' gem 'rack-freeze' gem 'rubocop', '>= 0.58.2', '< 0.69.0', platforms: %i[ruby_20 ruby_21 ruby_22 ruby_23 ruby_24] gem 'simplecov-lcov' gem 'tins', '~> 1.13', platforms: %i[jruby_18 jruby_19 ruby_19] end gemspec