mirror of
https://github.com/omniauth/omniauth.git
synced 2022-11-09 12:31:49 -05:00
Merge branch '2_0-indev' into fix-path-prefix-when-redirecting-on-failure
This commit is contained in:
commit
43a396f181
21 changed files with 468 additions and 121 deletions
74
.github/workflows/main.yml
vendored
Normal file
74
.github/workflows/main.yml
vendored
Normal file
|
@ -0,0 +1,74 @@
|
|||
# This workflow uses actions that are not certified by GitHub.
|
||||
# They are provided by a third-party and are governed by
|
||||
# separate terms of service, privacy policy, and support
|
||||
# documentation.
|
||||
# This workflow will download a prebuilt Ruby version, install dependencies and run tests with Rake
|
||||
# For more information see: https://github.com/marketplace/actions/setup-ruby-jruby-and-truffleruby
|
||||
|
||||
name: Ruby
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-18.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu, macos]
|
||||
ruby: [2.5, 2.6, 2.7, head, debug, truffleruby, truffleruby-head]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ matrix.ruby }}
|
||||
bundler-cache: true
|
||||
- name: Install dependencies
|
||||
run: bundle install
|
||||
- name: Run tests
|
||||
run: bundle exec rake
|
||||
test-jruby:
|
||||
runs-on: ubuntu-18.04
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [ubuntu, macos]
|
||||
jruby: [jruby, jruby-head]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: ${{ matrix.jruby }}
|
||||
bundler-cache: true
|
||||
- name: Install dependencies
|
||||
env:
|
||||
JRUBY_OPTS: --debug
|
||||
run: bundle install
|
||||
- name: Run tests
|
||||
env:
|
||||
JRUBY_OPTS: --debug
|
||||
run: bundle exec rake
|
||||
coveralls:
|
||||
runs-on: ubuntu-18.04
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up Ruby
|
||||
uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: 2.5
|
||||
bundler-cache: true
|
||||
- name: Install dependencies
|
||||
run: bundle install
|
||||
- name: Run tests
|
||||
run: bundle exec rake
|
||||
- name: Coveralls GitHub Action
|
||||
uses: coverallsapp/github-action@v1.1.2
|
||||
with:
|
||||
github-token: ${{ secrets.github_token }}
|
||||
path-to-lcov: './coverage/lcov/omniauth.lcov'
|
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -10,3 +10,4 @@ doc/*
|
|||
log/*
|
||||
measurement/*
|
||||
pkg/*
|
||||
.DS_Store
|
||||
|
|
25
.travis.yml
25
.travis.yml
|
@ -1,25 +0,0 @@
|
|||
bundler_args: --without development
|
||||
before_install:
|
||||
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
||||
- gem install bundler -v '1.17.3'
|
||||
install:
|
||||
- bundle _1.17.3_ install --jobs=3 --retry=3
|
||||
cache: bundler
|
||||
env:
|
||||
global:
|
||||
- JRUBY_OPTS="$JRUBY_OPTS --debug"
|
||||
language: ruby
|
||||
rvm:
|
||||
- jruby-9000
|
||||
- 2.2.9
|
||||
- 2.3.5
|
||||
- 2.4.4
|
||||
- 2.5.3
|
||||
- jruby-head
|
||||
- ruby-head
|
||||
matrix:
|
||||
allow_failures:
|
||||
- rvm: jruby-head
|
||||
- rvm: ruby-head
|
||||
fast_finish: true
|
||||
sudo: false
|
9
Gemfile
9
Gemfile
|
@ -1,6 +1,6 @@
|
|||
source 'https://rubygems.org'
|
||||
|
||||
gem 'jruby-openssl', '~> 0.9.19', :platforms => :jruby
|
||||
gem 'jruby-openssl', '~> 0.10.5', :platforms => :jruby
|
||||
gem 'rake', '>= 12.0'
|
||||
gem 'yard', '>= 0.9.11'
|
||||
|
||||
|
@ -12,16 +12,17 @@ group :development do
|
|||
end
|
||||
|
||||
group :test do
|
||||
gem 'coveralls', :require => false
|
||||
gem 'coveralls_reborn', '~> 0.19.0', require: false
|
||||
gem 'hashie', '>= 3.4.6', '~> 4.0.0', :platforms => [:jruby_18]
|
||||
gem 'json', '~> 2.0.3', :platforms => %i[jruby_18 jruby_19 ruby_19]
|
||||
gem 'json', '~> 2.3.0', :platforms => %i[jruby_18 jruby_19 ruby_19]
|
||||
gem 'mime-types', '~> 3.1', :platforms => [:jruby_18]
|
||||
gem 'rack', '>= 2.0.6', :platforms => %i[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.58.2', '< 0.69.0', :platforms => %i[ruby_20 ruby_21 ruby_22 ruby_23 ruby_24]
|
||||
gem 'tins', '~> 1.13.0', :platforms => %i[jruby_18 jruby_19 ruby_19]
|
||||
gem 'simplecov-lcov'
|
||||
gem 'tins', '~> 1.13', :platforms => %i[jruby_18 jruby_19 ruby_19]
|
||||
end
|
||||
|
||||
gemspec
|
||||
|
|
24
README.md
24
README.md
|
@ -2,9 +2,8 @@
|
|||
|
||||
[![Gem Version](http://img.shields.io/gem/v/omniauth.svg)][gem]
|
||||
[![Build Status](http://img.shields.io/travis/omniauth/omniauth.svg)][travis]
|
||||
[![Code Climate](http://img.shields.io/codeclimate/github/omniauth/omniauth.svg)][codeclimate]
|
||||
[![Code Climate](https://api.codeclimate.com/v1/badges/ffd33970723587806744/maintainability)][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
|
||||
|
@ -32,8 +31,8 @@ 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:
|
||||
use the built-in Developer strategy in a Sinatra application you might
|
||||
do this:
|
||||
|
||||
```ruby
|
||||
require 'sinatra'
|
||||
|
@ -45,7 +44,7 @@ class MyApplication < Sinatra::Base
|
|||
end
|
||||
```
|
||||
|
||||
Because OmniAuth is built for *multi-provider* authentication, I may
|
||||
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
|
||||
|
@ -82,18 +81,21 @@ 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:
|
||||
steps are necessary for your application. For example, in a Rails app
|
||||
you would add a line in your `routes.rb` file like this:
|
||||
|
||||
```ruby
|
||||
get '/auth/:provider/callback', to: 'sessions#create'
|
||||
post '/auth/:provider/callback', to: 'sessions#create'
|
||||
```
|
||||
|
||||
And I might then have a `SessionsController` with code that looks
|
||||
And you might then have a `SessionsController` with code that looks
|
||||
something like this:
|
||||
|
||||
```ruby
|
||||
class SessionsController < ApplicationController
|
||||
# If you're using a strategy that POSTs during callback, you'll need to skip the authenticity token check for the callback action only.
|
||||
skip_before_action :verify_authenticity_token, only: :create
|
||||
|
||||
def create
|
||||
@user = User.find_or_create_from_auth_hash(auth_hash)
|
||||
self.current_user = @user
|
||||
|
@ -108,7 +110,7 @@ class SessionsController < ApplicationController
|
|||
end
|
||||
```
|
||||
|
||||
The `omniauth.auth` key in the environment hash gives me my
|
||||
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
|
||||
|
@ -163,7 +165,7 @@ 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
|
||||
(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:
|
||||
|
|
|
@ -15,6 +15,7 @@ module OmniAuth
|
|||
autoload :Form, 'omniauth/form'
|
||||
autoload :AuthHash, 'omniauth/auth_hash'
|
||||
autoload :FailureEndpoint, 'omniauth/failure_endpoint'
|
||||
autoload :AuthenticityTokenProtection, 'omniauth/authenticity_token_protection'
|
||||
|
||||
def self.strategies
|
||||
@strategies ||= []
|
||||
|
@ -29,20 +30,22 @@ module OmniAuth
|
|||
logger
|
||||
end
|
||||
|
||||
def self.defaults
|
||||
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[get post],
|
||||
:mock_auth => {:default => AuthHash.new('provider' => 'default', 'uid' => '1234', 'info' => {'name' => 'Example User'})}
|
||||
:allowed_request_methods => %i[post],
|
||||
:mock_auth => {:default => AuthHash.new('provider' => 'default', 'uid' => '1234', 'info' => {'name' => 'Example User'})},
|
||||
:silence_get_warning => false
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -74,6 +77,14 @@ module OmniAuth
|
|||
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
|
||||
|
@ -111,8 +122,9 @@ module OmniAuth
|
|||
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
|
||||
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
|
||||
|
@ -159,7 +171,7 @@ module OmniAuth
|
|||
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]
|
||||
camelize(word).tap { |w| w[0] = w[0].downcase }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
30
lib/omniauth/authenticity_token_protection.rb
Normal file
30
lib/omniauth/authenticity_token_protection.rb
Normal file
|
@ -0,0 +1,30 @@
|
|||
require '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
|
||||
|
||||
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
|
|
@ -31,7 +31,7 @@ module OmniAuth
|
|||
middleware = klass
|
||||
else
|
||||
begin
|
||||
middleware = OmniAuth::Strategies.const_get(OmniAuth::Utils.camelize(klass.to_s).to_s)
|
||||
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
|
||||
|
|
|
@ -27,7 +27,8 @@ module OmniAuth
|
|||
|
||||
def redirect_to_failure
|
||||
message_key = env['omniauth.error.type']
|
||||
new_path = "#{env['SCRIPT_NAME']}#{strategy_path_prefix}/failure?message=#{message_key}#{origin_query_param}#{strategy_name_query_param}"
|
||||
|
||||
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
|
||||
|
||||
|
|
|
@ -180,18 +180,44 @@ module OmniAuth
|
|||
raise(error)
|
||||
end
|
||||
|
||||
warn_if_using_get
|
||||
|
||||
@env = env
|
||||
@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
|
||||
return fail!(e.message, e)
|
||||
end
|
||||
|
||||
@app.call(env)
|
||||
end
|
||||
|
||||
def warn_if_using_get
|
||||
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
|
||||
|
@ -202,17 +228,19 @@ module OmniAuth
|
|||
# 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.'
|
||||
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 :info, 'Rendering form from supplied Rack endpoint.'
|
||||
log :debug, 'Rendering form from supplied Rack endpoint.'
|
||||
options.form.call(env)
|
||||
elsif options.form
|
||||
log :info, 'Rendering form from underlying application.'
|
||||
log :debug, 'Rendering form from underlying application.'
|
||||
call_app!
|
||||
elsif !options.origin_param
|
||||
request_phase
|
||||
|
@ -225,12 +253,14 @@ module OmniAuth
|
|||
|
||||
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 :info, 'Callback phase initiated.'
|
||||
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') || {}
|
||||
|
@ -312,10 +342,10 @@ module OmniAuth
|
|||
# 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.'
|
||||
log :debug, 'Setup endpoint detected, running now.'
|
||||
options[:setup].call(env)
|
||||
elsif options[:setup]
|
||||
log :info, 'Calling through to underlying application for 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
|
||||
|
@ -345,11 +375,13 @@ module OmniAuth
|
|||
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
|
||||
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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
module OmniAuth
|
||||
VERSION = '1.9.0'.freeze
|
||||
VERSION = '1.9.1'.freeze
|
||||
end
|
||||
|
|
|
@ -7,7 +7,8 @@ require 'omniauth/version'
|
|||
Gem::Specification.new do |spec|
|
||||
spec.add_dependency 'hashie', ['>= 3.4.6']
|
||||
spec.add_dependency 'rack', ['>= 1.6.2', '< 3']
|
||||
spec.add_development_dependency 'bundler', '~> 1.14'
|
||||
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.'
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
if 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.01)
|
||||
maximum_coverage_drop(0.05)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -20,6 +24,7 @@ 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
|
||||
|
@ -45,7 +50,7 @@ class ExampleStrategy
|
|||
|
||||
def request_phase
|
||||
options[:mutate_on_request].call(options) if options[:mutate_on_request]
|
||||
@fail = fail!(options[:failure]) if options[:failure]
|
||||
@fail = fail!(options[:failure], options[:failure_exception]) if options[:failure]
|
||||
@last_env = env
|
||||
return @fail if @fail
|
||||
|
||||
|
@ -54,7 +59,7 @@ class ExampleStrategy
|
|||
|
||||
def callback_phase
|
||||
options[:mutate_on_callback].call(options) if options[:mutate_on_callback]
|
||||
@fail = fail!(options[:failure]) if options[:failure]
|
||||
@fail = fail!(options[:failure], options[:failure_exception]) if options[:failure]
|
||||
@last_env = env
|
||||
return @fail if @fail
|
||||
|
||||
|
|
|
@ -13,6 +13,10 @@ describe OmniAuth::AuthHash do
|
|||
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'}) }
|
||||
|
||||
|
@ -111,6 +115,10 @@ describe OmniAuth::AuthHash do
|
|||
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
|
||||
|
|
|
@ -3,7 +3,7 @@ require '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)
|
||||
expect(OmniAuth::Strategies).to receive(:const_get).with('MyStrategy', false).and_return(Class.new)
|
||||
OmniAuth::Builder.new(nil) do
|
||||
provider :my_strategy
|
||||
end
|
||||
|
@ -26,6 +26,16 @@ describe OmniAuth::Builder do
|
|||
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
|
||||
|
|
|
@ -60,5 +60,10 @@ describe OmniAuth::FailureEndpoint do
|
|||
_, 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
|
||||
|
|
|
@ -7,7 +7,8 @@ describe OmniAuth::Form do
|
|||
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) }
|
||||
f = OmniAuth::Form.build { @html = '<h1>OmniAuth</h1>' }
|
||||
expect(f.instance_variable_get(:@html)).to eq('<h1>OmniAuth</h1>')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -20,4 +21,34 @@ describe OmniAuth::Form do
|
|||
expect(OmniAuth::Form.new(:title => 'Something Cool').to_html).to be_include('<h1>Something Cool</h1>')
|
||||
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('<label for=\'password\'>pass:</label>')
|
||||
expect(form_html).to include('<input type=\'password\' id=\'password\' name=\'password\'/>')
|
||||
end
|
||||
end
|
||||
|
||||
describe '#html' do
|
||||
it 'appends to the html body' do
|
||||
form = OmniAuth::Form.build { @html = '<p></p>' }
|
||||
form.html('<h1></h1>')
|
||||
|
||||
expect(form.instance_variable_get(:@html)).to eq '<p></p><h1></h1>'
|
||||
end
|
||||
end
|
||||
|
||||
describe 'fieldset' do
|
||||
it 'creates a fieldset with options' do
|
||||
form = OmniAuth::Form.new
|
||||
options = {:style => 'color: red', :id => 'fieldSetId'}
|
||||
expected = "<fieldset style='color: red' id='fieldSetId'>\n <legend>legendary</legend>\n\n</fieldset>"
|
||||
|
||||
form.fieldset('legendary', options) {}
|
||||
|
||||
expect(form.to_html).to include expected
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -25,6 +25,7 @@ RSpec.describe OmniAuth::KeyStore do
|
|||
|
||||
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)
|
||||
|
|
|
@ -10,7 +10,7 @@ describe OmniAuth::Strategies::Developer do
|
|||
end
|
||||
|
||||
context 'request phase' do
|
||||
before(:each) { get '/auth/developer' }
|
||||
before(:each) { post '/auth/developer' }
|
||||
|
||||
it 'displays a form' do
|
||||
expect(last_response.status).to eq(200)
|
||||
|
|
|
@ -2,7 +2,7 @@ require 'helper'
|
|||
|
||||
def make_env(path = '/auth/test', props = {})
|
||||
{
|
||||
'REQUEST_METHOD' => 'GET',
|
||||
'REQUEST_METHOD' => 'POST',
|
||||
'PATH_INFO' => path,
|
||||
'rack.session' => {},
|
||||
'rack.input' => StringIO.new('test=true')
|
||||
|
@ -32,6 +32,12 @@ describe OmniAuth::Strategy do
|
|||
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
|
||||
|
@ -63,6 +69,29 @@ describe OmniAuth::Strategy do
|
|||
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
|
||||
|
@ -173,19 +202,25 @@ describe OmniAuth::Strategy do
|
|||
end
|
||||
let(:instance) { subject.new(app) }
|
||||
|
||||
it 'calls through to uid and info' do
|
||||
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
|
||||
|
||||
|
@ -242,7 +277,9 @@ describe OmniAuth::Strategy do
|
|||
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')
|
||||
expected_body = "<script type='text/javascript' charset='utf-8'>top.location.href = 'http://abc.com';</script>"
|
||||
|
||||
expect(response.last).to include(expected_body)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -310,7 +347,9 @@ describe OmniAuth::Strategy do
|
|||
context 'disabled' do
|
||||
it 'does not set omniauth.origin' do
|
||||
@options = {:origin_param => false}
|
||||
expect { strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'return=/foo')) }.to raise_error('Request Phase')
|
||||
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
|
||||
|
@ -318,24 +357,31 @@ describe OmniAuth::Strategy do
|
|||
context 'custom' do
|
||||
it 'sets from a custom param' do
|
||||
@options = {:origin_param => 'return'}
|
||||
expect { strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'return=/foo')) }.to raise_error('Request Phase')
|
||||
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.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin')) }.to raise_error('Request Phase')
|
||||
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.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'})) }.to raise_error('Callback Phase')
|
||||
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.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo')) }.to raise_error('Request Phase')
|
||||
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
|
||||
|
||||
|
@ -348,7 +394,9 @@ describe OmniAuth::Strategy do
|
|||
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).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
|
||||
|
||||
|
@ -357,8 +405,9 @@ describe OmniAuth::Strategy do
|
|||
'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))
|
||||
|
||||
expect { strategy.call(make_env('/auth/test/callback', env)) }.to raise_error('Callback Phase')
|
||||
strategy.call(make_env('/auth/test/callback', env))
|
||||
expect(strategy.last_env['omniauth.origin']).to eq('http://example.com/sub_uri/origin')
|
||||
end
|
||||
end
|
||||
|
@ -367,34 +416,41 @@ describe OmniAuth::Strategy do
|
|||
|
||||
context 'default paths' do
|
||||
it 'uses the default request path' do
|
||||
expect { strategy.call(make_env) }.to raise_error('Request Phase')
|
||||
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.call(make_env('/AUTH/Test')) }.to raise_error('Request Phase')
|
||||
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.call(make_env('/AUTH/TeSt/CaLlBAck')) }.to raise_error('Callback Phase')
|
||||
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.call(make_env('/auth/test/callback')) }.to raise_error('Callback Phase')
|
||||
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.call(make_env('/auth/test/')) }.to raise_error('Request Phase')
|
||||
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.call(make_env('/auth/test/callback/')) }.to raise_error('Callback Phase')
|
||||
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))
|
||||
|
||||
expect { strategy.call(make_env) }.to raise_error('Request Phase')
|
||||
strategy.call(make_env)
|
||||
|
||||
expect(strategy.callback_url).to eq('http://example.com/auth/test/callback')
|
||||
end
|
||||
|
@ -434,12 +490,15 @@ describe OmniAuth::Strategy do
|
|||
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')
|
||||
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.call(make_env('/asoufiasod')) }.to raise_error('Callback Phase')
|
||||
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
|
||||
|
@ -449,8 +508,9 @@ describe OmniAuth::Strategy do
|
|||
|
||||
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' })
|
||||
strategy_instance.should_receive(:fail!).with('Callback Phase', kind_of(StandardError))
|
||||
|
||||
expect { strategy_instance.call(make_env('/auth/bish/bosh/callback')) }.to raise_error('Callback Phase')
|
||||
strategy_instance.call(make_env('/auth/bish/bosh/callback'))
|
||||
expect(strategy_instance.callback_path).to eq('/auth/bish/bosh/callback')
|
||||
end
|
||||
end
|
||||
|
@ -458,20 +518,25 @@ describe OmniAuth::Strategy do
|
|||
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')
|
||||
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.call(make_env('/radical')) }.to raise_error('Callback Phase')
|
||||
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))
|
||||
|
||||
expect { strategy.call(make_env('/radical')) }.to raise_error('Callback Phase')
|
||||
strategy.call(make_env('/radical'))
|
||||
|
||||
expect(strategy.callback_url).to eq('http://example.com/radical')
|
||||
end
|
||||
|
@ -494,18 +559,20 @@ describe OmniAuth::Strategy do
|
|||
end
|
||||
|
||||
it 'uses a custom prefix for request' do
|
||||
expect { strategy.call(make_env('/wowzers/test')) }.to raise_error('Request Phase')
|
||||
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.call(make_env('/wowzers/test/callback')) }.to raise_error('Callback Phase')
|
||||
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.call(make_env('/wowzers/test')) }.to raise_error('Request Phase')
|
||||
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
|
||||
|
@ -522,20 +589,21 @@ describe OmniAuth::Strategy do
|
|||
end
|
||||
|
||||
context 'request method restriction' do
|
||||
before do
|
||||
OmniAuth.config.allowed_request_methods = [:post]
|
||||
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) }.not_to raise_error
|
||||
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.call(make_env('/auth/test', 'REQUEST_METHOD' => 'POST')) }.to raise_error('Request Phase')
|
||||
expect(strategy).to receive(:fail!).with('Request Phase', kind_of(StandardError))
|
||||
strategy.call(make_env('/auth/test'))
|
||||
end
|
||||
|
||||
after do
|
||||
OmniAuth.config.allowed_request_methods = %i[get post]
|
||||
after(:context) do
|
||||
OmniAuth.config.allowed_request_methods = %i[post]
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -546,7 +614,7 @@ describe OmniAuth::Strategy do
|
|||
end
|
||||
|
||||
it 'sets the Allow header properly' do
|
||||
expect(response[1]['Allow']).to eq('GET, POST')
|
||||
expect(response[1]['Allow']).to eq('POST')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -577,14 +645,16 @@ describe OmniAuth::Strategy 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')
|
||||
|
||||
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) }
|
||||
expect { strategy.call(make_env) }.to raise_error('Request Phase')
|
||||
|
||||
strategy.call(make_env)
|
||||
expect(strategy.options[:deep_option]).to have_key(:test_option)
|
||||
end
|
||||
end
|
||||
|
@ -593,14 +663,16 @@ describe OmniAuth::Strategy 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')
|
||||
|
||||
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) }
|
||||
expect { strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'POST')) }.to raise_error('Callback Phase')
|
||||
|
||||
strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'POST'))
|
||||
expect(strategy.options[:deep_option]).to have_key(:test_option)
|
||||
end
|
||||
end
|
||||
|
@ -653,8 +725,8 @@ describe OmniAuth::Strategy do
|
|||
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')
|
||||
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
|
||||
|
@ -807,6 +879,65 @@ describe OmniAuth::Strategy do
|
|||
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
|
||||
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))
|
||||
|
||||
get_env = make_env('/auth/test', 'REQUEST_METHOD' => 'GET')
|
||||
strategy.call(get_env)
|
||||
end
|
||||
|
||||
after(:context) do
|
||||
OmniAuth.config.allowed_request_methods = @old_allowed_request_methods
|
||||
end
|
||||
end
|
||||
|
||||
after do
|
||||
OmniAuth.config.request_validation_phase = nil
|
||||
end
|
||||
end
|
||||
|
||||
it 'calls fail! when encountering an unhandled exception' do
|
||||
strategy.stub(: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
|
||||
end
|
||||
|
||||
context 'setup phase' do
|
||||
|
|
|
@ -31,6 +31,7 @@ describe OmniAuth do
|
|||
@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
|
||||
|
@ -40,6 +41,7 @@ describe OmniAuth do
|
|||
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
|
||||
|
||||
|
@ -88,6 +90,15 @@ describe OmniAuth do
|
|||
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'}}
|
||||
|
@ -128,6 +139,13 @@ describe OmniAuth do
|
|||
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 "<style type='text/css'>css.css</style>"
|
||||
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'})
|
||||
|
@ -148,6 +166,15 @@ describe OmniAuth 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
|
||||
|
|
Loading…
Reference in a new issue