pax_global_header00006660000000000000000000000064130521323400014503gustar00rootroot0000000000000052 comment=b1d2ab04250d55abed1625eb6c67805a15cd4ca9 omniauth-1.6.1/000077500000000000000000000000001305213234000133345ustar00rootroot00000000000000omniauth-1.6.1/.github/000077500000000000000000000000001305213234000146745ustar00rootroot00000000000000omniauth-1.6.1/.github/ISSUE_TEMPLATE.md000066400000000000000000000004601305213234000174010ustar00rootroot00000000000000Please complete all sections. ### Configuration - Provider Gem: `omniauth-*` - Ruby Version: `` - Framework: `` - Platform: `` ### Expected Behavior Tell us what should happen. ### Actual Behavior Tell us what happens instead. ### Steps to Reproduce Please list all steps to reproduce the issue. omniauth-1.6.1/.gitignore000066400000000000000000000001471305213234000153260ustar00rootroot00000000000000*.gem *~ .bundle .rvmrc .yardoc Gemfile.lock Gemfile.*.lock coverage/* doc/* log/* measurement/* pkg/* omniauth-1.6.1/.rspec000066400000000000000000000000271305213234000144500ustar00rootroot00000000000000--color --order random omniauth-1.6.1/.rubocop.yml000066400000000000000000000016041305213234000156070ustar00rootroot00000000000000Lint/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/AccessModifierIndentation: EnforcedStyle: outdent Style/CollectionMethods: PreferredMethods: map: 'collect' reduce: 'inject' find: 'detect' find_all: 'select' Style/Documentation: Enabled: false Style/DotPosition: EnforcedStyle: trailing Style/DoubleNegation: Enabled: false Style/EachWithObject: Enabled: false Style/Encoding: Enabled: false Style/HashSyntax: EnforcedStyle: hash_rockets Style/Lambda: Enabled: false Style/RaiseArgs: EnforcedStyle: compact Style/SpaceInsideHashLiteralBraces: EnforcedStyle: no_space omniauth-1.6.1/.travis.yml000066400000000000000000000005451305213234000154510ustar00rootroot00000000000000bundler_args: --without development before_install: gem update bundler cache: bundler env: global: - JRUBY_OPTS="$JRUBY_OPTS --debug" language: ruby rvm: - jruby-9000 - 2.1.10 # EOL Soon - 2.2.6 - 2.3.3 - 2.4.0 - jruby-head - ruby-head matrix: allow_failures: - rvm: jruby-head - rvm: ruby-head fast_finish: true sudo: false omniauth-1.6.1/.yardopts000066400000000000000000000000701305213234000151770ustar00rootroot00000000000000--markup markdown --markup-provider maruku - LICENSE.md omniauth-1.6.1/Gemfile000066400000000000000000000015261305213234000146330ustar00rootroot00000000000000source 'https://rubygems.org' gem 'jruby-openssl', '~> 0.9.19', :platforms => :jruby gem 'rake', '>= 12.0' gem 'yard', '>= 0.9' group :development do gem 'benchmark-ips' gem 'kramdown' gem 'memory_profiler' gem 'pry' end group :test do gem 'coveralls', :require => false gem 'hashie', '>= 3.4.6', '< 3.6.0', :platforms => [:jruby_18] gem 'json', '~> 2.0.3', :platforms => [:jruby_18, :jruby_19, :ruby_19] gem 'mime-types', '~> 3.1', :platforms => [:jruby_18] gem 'rack', '>= 1.6.2', :platforms => [:jruby_18, :jruby_19, :ruby_19, :ruby_20, :ruby_21] gem 'rack-test' gem 'rest-client', '~> 2.0.0', :platforms => [:jruby_18] gem 'rspec', '~> 3.5.0' gem 'rubocop', '>= 0.47', :platforms => [:ruby_20, :ruby_21, :ruby_22, :ruby_23, :ruby_24] gem 'tins', '~> 1.13.0', :platforms => [:jruby_18, :jruby_19, :ruby_19] end gemspec omniauth-1.6.1/LICENSE.md000066400000000000000000000020721305213234000147410ustar00rootroot00000000000000Copyright (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-1.6.1/README.md000066400000000000000000000153361305213234000146230ustar00rootroot00000000000000# OmniAuth: Standardized Multi-Provider Authentication [![Gem Version](http://img.shields.io/gem/v/omniauth.svg)][gem] [![Build Status](http://img.shields.io/travis/omniauth/omniauth.svg)][travis] [![Dependency Status](http://img.shields.io/gemnasium/omniauth/omniauth.svg)][gemnasium] [![Code Climate](http://img.shields.io/codeclimate/github/omniauth/omniauth.svg)][codeclimate] [![Coverage Status](http://img.shields.io/coveralls/omniauth/omniauth.svg)][coveralls] [![Security](https://hakiri.io/github/omniauth/omniauth/master.svg)](https://hakiri.io/github/omniauth/omniauth/master) [gem]: https://rubygems.org/gems/omniauth [travis]: http://travis-ci.org/omniauth/omniauth [gemnasium]: https://gemnasium.com/omniauth/omniauth [codeclimate]: https://codeclimate.com/github/omniauth/omniauth [coveralls]: https://coveralls.io/r/omniauth/omniauth ## 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 I 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, I 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. For example, in a Rails app I would add a line in my `routes.rb` file like this: ```ruby get '/auth/:provider/callback', to: 'sessions#create' ``` And I might then have a `SessionsController` with code that looks something like this: ```ruby class SessionsController < ApplicationController def create @user = User.find_or_create_from_auth_hash(auth_hash) self.current_user = @user redirect_to '/' end protected def auth_hash request.env['omniauth.auth'] end end ``` The `omniauth.auth` key in the environment hash gives me my 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. ## 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 ``` ## 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. ## Supported Ruby Versions OmniAuth is tested under 2.1.10, 2.2.6, 2.3.3, 2.4.0, 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-1.6.1/Rakefile000066400000000000000000000021771305213234000150100ustar00rootroot00000000000000require '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 $stderr.puts 'RuboCop is disabled' end end task :default => [: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-1.6.1/lib/000077500000000000000000000000001305213234000141025ustar00rootroot00000000000000omniauth-1.6.1/lib/omniauth.rb000066400000000000000000000104601305213234000162540ustar00rootroot00000000000000require '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' 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 @defaults ||= { :camelizations => {}, :path_prefix => '/auth', :on_failure => OmniAuth::FailureEndpoint, :failure_raise_out_environments => ['development'], :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 => [:get, :post], :mock_auth => {:default => AuthHash.new('provider' => 'default', 'uid' => '1234', 'info' => {'name' => 'Example User'})} } 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 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 attr_accessor :failure_raise_out_environments, :path_prefix, :allowed_request_methods, :form_css, :test_mode, :mock_auth, :full_host, :camelizations, :logger 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 def form_css "" end def deep_merge(hash, other_hash) target = hash.dup other_hash.keys.each 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 word.first + camelize(word)[1..-1] end end end end omniauth-1.6.1/lib/omniauth/000077500000000000000000000000001305213234000157265ustar00rootroot00000000000000omniauth-1.6.1/lib/omniauth/auth_hash.rb000066400000000000000000000024561305213234000202260ustar00rootroot00000000000000require '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) if key.to_s == 'info' && value.is_a?(::Hash) && !value.is_a?(InfoHash) value = InfoHash.new(value) end 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-1.6.1/lib/omniauth/builder.rb000066400000000000000000000030371305213234000177040ustar00rootroot00000000000000module OmniAuth class Builder < ::Rack::Builder def initialize(app, &block) @options = nil if rack14? || rack2? super else @app = app super(&block) @ins << @app end end def rack14? Rack.release.start_with?('1.') && (Rack.release.split('.')[1].to_i >= 4) end def rack2? Rack.release.start_with? '2.' end 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, &block) if klass.is_a?(Class) middleware = klass else begin middleware = OmniAuth::Strategies.const_get(OmniAuth::Utils.camelize(klass.to_s).to_s) 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 args.last.is_a?(Hash) ? args.push(options.merge(args.pop)) : args.push(options) use middleware, *args, &block end def call(env) to_app.call(env) end end end omniauth-1.6.1/lib/omniauth/failure_endpoint.rb000066400000000000000000000025251305213234000216060ustar00rootroot00000000000000module 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']}#{OmniAuth.config.path_prefix}/failure?message=#{message_key}#{origin_query_param}#{strategy_name_query_param}" Rack::Response.new(['302 Moved'], 302, 'Location' => new_path).finish 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-1.6.1/lib/omniauth/form.css000066400000000000000000000030671305213234000174110ustar00rootroot00000000000000body { 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-1.6.1/lib/omniauth/form.rb000066400000000000000000000047051305213234000172240ustar00rootroot00000000000000module 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 = '' @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-1.6.1/lib/omniauth/key_store.rb000066400000000000000000000011401305213234000202530ustar00rootroot00000000000000require '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-1.6.1/lib/omniauth/strategies/000077500000000000000000000000001305213234000201005ustar00rootroot00000000000000omniauth-1.6.1/lib/omniauth/strategies/developer.rb000066400000000000000000000032421305213234000224130ustar00rootroot00000000000000module 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, [: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-1.6.1/lib/omniauth/strategy.rb000066400000000000000000000376341305213234000201320ustar00rootroot00000000000000require '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 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 @env['omniauth.strategy'] = self if on_auth_path? return mock_call!(env) if OmniAuth.config.test_mode return options_call if on_auth_path? && options_request? return request_call if on_request_path? && OmniAuth.config.allowed_request_methods.include?(request.request_method.downcase.to_sym) return callback_call if on_callback_path? return other_phase if respond_to?(:other_phase) @app.call(env) end # 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 :info, 'Request phase initiated.' # store query params from the request url, extracted in the callback_phase session['omniauth.params'] = request.GET OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase if options.form.respond_to?(:call) log :info, 'Rendering form from supplied Rack endpoint.' options.form.call(env) elsif options.form log :info, 'Rendering form from underlying application.' call_app! else if request.params['origin'] env['rack.session']['omniauth.origin'] = request.params['origin'] elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/) env['rack.session']['omniauth.origin'] = env['HTTP_REFERER'] end request_phase end end # Performs the steps necessary to run the callback phase of a strategy. def callback_call setup_phase log :info, 'Callback phase initiated.' @env['omniauth.origin'] = session.delete('omniauth.origin') @env['omniauth.origin'] = nil if env['omniauth.origin'] == '' @env['omniauth.params'] = session.delete('omniauth.params') || {} OmniAuth.config.before_callback_phase.call(@env) if OmniAuth.config.before_callback_phase callback_phase end # 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!(*) 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? call_app! end def mock_request_call setup_phase session['omniauth.params'] = request.GET OmniAuth.config.before_request_phase.call(env) if OmniAuth.config.before_request_phase if request.params['origin'] @env['rack.session']['omniauth.origin'] = request.params['origin'] elsif env['HTTP_REFERER'] && !env['HTTP_REFERER'].match(/#{request_path}$/) @env['rack.session']['omniauth.origin'] = env['HTTP_REFERER'] end redirect(callback_url) end 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 :info, 'Setup endpoint detected, running now.' options[:setup].call(env) elsif options[:setup] log :info, 'Calling through to underlying application for setup.' setup_env = env.merge('PATH_INFO' => setup_path, 'REQUEST_METHOD' => 'GET') call_app!(setup_env) end end # @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 hash = AuthHash.new(:provider => name, :uid => uid) hash.info = info unless skip_info? hash.credentials = credentials if credentials hash.extra = extra if extra hash end # 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 ||= options[:request_path].is_a?(String) ? options[:request_path] : "#{path_prefix}/#{name}" 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 ||= "#{path_prefix}/#{name}/callback" path end end def setup_path options[:setup_path] || "#{path_prefix}/#{name}/setup" end CURRENT_PATH_REGEX = %r{/$} EMPTY_STRING = ''.freeze def current_path @current_path ||= request.path_info.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) 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 + script_name + callback_path + query_string end def script_name @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 def dup super.tap do @options = @options.dup end end class Options < OmniAuth::KeyStore; end protected 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-1.6.1/lib/omniauth/test.rb000066400000000000000000000004261305213234000172340ustar00rootroot00000000000000module 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-1.6.1/lib/omniauth/test/000077500000000000000000000000001305213234000167055ustar00rootroot00000000000000omniauth-1.6.1/lib/omniauth/test/phony_session.rb000066400000000000000000000004141305213234000221310ustar00rootroot00000000000000module 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-1.6.1/lib/omniauth/test/strategy_macros.rb000066400000000000000000000014321305213234000224400ustar00rootroot00000000000000module 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-1.6.1/lib/omniauth/test/strategy_test_case.rb000066400000000000000000000022011305213234000231210ustar00rootroot00000000000000require '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-1.6.1/lib/omniauth/version.rb000066400000000000000000000000571305213234000177420ustar00rootroot00000000000000module OmniAuth VERSION = '1.6.1'.freeze end omniauth-1.6.1/omniauth.gemspec000066400000000000000000000020631305213234000165260ustar00rootroot00000000000000# 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', '< 3.6.0'] spec.add_dependency 'rack', ['>= 1.6.2', '< 3'] spec.add_development_dependency 'bundler', '~> 1.14' 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.1.9' spec.summary = spec.description spec.version = OmniAuth::VERSION end omniauth-1.6.1/spec/000077500000000000000000000000001305213234000142665ustar00rootroot00000000000000omniauth-1.6.1/spec/helper.rb000066400000000000000000000024521305213234000160750ustar00rootroot00000000000000if RUBY_VERSION >= '1.9' require 'simplecov' require 'coveralls' SimpleCov.formatters = [ SimpleCov::Formatter::HTMLFormatter, Coveralls::SimpleCov::Formatter ] SimpleCov.start do add_filter '/spec/' add_filter '/vendor/' minimum_coverage(92.5) end end require 'rspec' require 'rack/test' require 'omniauth' require 'omniauth/test' OmniAuth.config.logger = Logger.new('/dev/null') 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]) 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]) if options[:failure] @last_env = env return @fail if @fail raise('Callback Phase') end end omniauth-1.6.1/spec/omniauth/000077500000000000000000000000001305213234000161125ustar00rootroot00000000000000omniauth-1.6.1/spec/omniauth/auth_hash_spec.rb000066400000000000000000000100571305213234000214200ustar00rootroot00000000000000require '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 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 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-1.6.1/spec/omniauth/builder_spec.rb000066400000000000000000000024711305213234000211030ustar00rootroot00000000000000require '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').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 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 end omniauth-1.6.1/spec/omniauth/failure_endpoint_spec.rb000066400000000000000000000034371305213234000230070ustar00rootroot00000000000000require '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 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 '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 end end omniauth-1.6.1/spec/omniauth/form_spec.rb000066400000000000000000000013761305213234000204230ustar00rootroot00000000000000require '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 OmniAuth::Form.build { |f| expect(f.class).to eq(OmniAuth::Form) } 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 end omniauth-1.6.1/spec/omniauth/key_store_spec.rb000066400000000000000000000036361305213234000214650ustar00rootroot00000000000000require '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) 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-1.6.1/spec/omniauth/strategies/000077500000000000000000000000001305213234000202645ustar00rootroot00000000000000omniauth-1.6.1/spec/omniauth/strategies/developer_spec.rb000066400000000000000000000041301305213234000236060ustar00rootroot00000000000000require '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) { get '/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 => [: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 => [: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-1.6.1/spec/omniauth/strategy_spec.rb000066400000000000000000000702541305213234000213230ustar00rootroot00000000000000require 'helper' def make_env(path = '/auth/test', props = {}) { 'REQUEST_METHOD' => 'GET', '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 '.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 '#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 [:abc, :def] expect(subject.args).to eq([:abc, :def]) end it 'is inheritable' do subject.args [:abc, :def] c = Class.new(subject) expect(c.args).to eq([:abc, :def]) end it 'accepts corresponding options as default arg values' do subject.args [: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 and info' do expect(instance).to receive(:uid) expect(instance).to receive(:info) 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') 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') 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 [: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 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') expect(response.last.body.first).to be_include('top.location.href') 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 it 'is set on the request phase' do expect { strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin')) }.to raise_error('Request Phase') 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.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'})) }.to raise_error('Callback Phase') expect(strategy.last_env['omniauth.origin']).to eq('http://example.com/origin') end it 'sets from the params if provided' do expect { strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo')) }.to raise_error('Request Phase') 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.call(make_env('/auth/test', env)) }.to raise_error('Request Phase') 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.call(make_env('/auth/test/callback', env)) }.to raise_error('Callback Phase') expect(strategy.last_env['omniauth.origin']).to eq('http://example.com/sub_uri/origin') end end end context 'default paths' do it 'uses the default request path' do expect { strategy.call(make_env) }.to raise_error('Request Phase') end it 'is case insensitive on request path' do expect { strategy.call(make_env('/AUTH/Test')) }.to raise_error('Request Phase') end it 'is case insensitive on callback path' do expect { strategy.call(make_env('/AUTH/TeSt/CaLlBAck')) }.to raise_error('Callback Phase') end it 'uses the default callback path' do expect { strategy.call(make_env('/auth/test/callback')) }.to raise_error('Callback Phase') end it 'strips trailing spaces on request' do expect { strategy.call(make_env('/auth/test/')) }.to raise_error('Request Phase') end it 'strips trailing spaces on callback' do expect { strategy.call(make_env('/auth/test/callback/')) }.to raise_error('Callback Phase') 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.call(make_env) }.to raise_error('Request Phase') 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.call(make_env('/asoufibasfi')) }.to raise_error('Request Phase') end it 'runs the callback phase if the custom callback path evaluator is truthy' do @options = {:callback_path => lambda { |_env| true }} expect { strategy.call(make_env('/asoufiasod')) }.to raise_error('Callback Phase') 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.call(make_env('/auth/bish/bosh/callback')) }.to raise_error('Callback Phase') 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.call(make_env('/awesome')) }.to raise_error('Request Phase') end it 'uses a custom callback_path if one is provided' do @options = {:callback_path => '/radical'} expect { strategy.call(make_env('/radical')) }.to raise_error('Callback Phase') 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.call(make_env('/radical')) }.to raise_error('Callback Phase') 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.call(make_env('/wowzers/test')) }.to raise_error('Request Phase') end it 'uses a custom prefix for callback' do expect { strategy.call(make_env('/wowzers/test/callback')) }.to raise_error('Callback Phase') end context 'callback_url' do it 'uses a custom prefix' do expect(strategy).to receive(:full_host).and_return('http://example.com') expect { strategy.call(make_env('/wowzers/test')) }.to raise_error('Request Phase') 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 'request method restriction' do before do OmniAuth.config.allowed_request_methods = [:post] end it 'does not allow a request method of the wrong type' do expect { strategy.call(make_env) }.not_to raise_error end it 'allows a request method of the correct type' do expect { strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'POST')) }.to raise_error('Request Phase') end after do OmniAuth.config.allowed_request_methods = [:get, :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('GET, 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) } expect { strategy.call(make_env) }.to raise_error('Request Phase') 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) } expect { strategy.call(make_env) }.to raise_error('Request Phase') 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) } expect { strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'POST')) }.to raise_error('Callback Phase') 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) } expect { strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'POST')) }.to raise_error('Callback Phase') 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', 'HTTP_HOST' => 'example.org', 'SERVER_PORT' => 3000)) expect(response[1]['Location']).to eq('http://example.org:3000/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 it 'sets omniauth.origin on the request phase' 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 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 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 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-1.6.1/spec/omniauth_spec.rb000066400000000000000000000110471305213234000174540ustar00rootroot00000000000000require '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 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 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 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 '.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 end end end