omniauth 2.1.4 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.md +1 -1
- data/README.md +170 -29
- data/SECURITY.md +5 -3
- data/lib/omniauth/auth_hash.rb +32 -6
- data/lib/omniauth/authenticity_token_protection.rb +6 -4
- data/lib/omniauth/builder.rb +9 -6
- data/lib/omniauth/failure_endpoint.rb +4 -4
- data/lib/omniauth/form.rb +5 -7
- data/lib/omniauth/key_store.rb +2 -10
- data/lib/omniauth/strategies/developer.rb +3 -5
- data/lib/omniauth/strategy/class_methods.rb +118 -0
- data/lib/omniauth/strategy/fetchers.rb +57 -0
- data/lib/omniauth/strategy/hosts.rb +48 -0
- data/lib/omniauth/strategy/paths.rb +140 -0
- data/lib/omniauth/strategy/sign_ins.rb +57 -0
- data/lib/omniauth/strategy/test_mode.rb +53 -0
- data/lib/omniauth/strategy.rb +149 -361
- data/lib/omniauth/test/phony_session.rb +1 -1
- data/lib/omniauth/test/strategy_test_case.rb +8 -9
- data/lib/omniauth/version.rb +1 -1
- data/lib/omniauth.rb +28 -25
- data/sig/manifest.yaml +5 -0
- data/sig/omniauth.rbs +662 -0
- metadata +30 -59
- data/.github/FUNDING.yml +0 -2
- data/.github/ISSUE_TEMPLATE.md +0 -20
- data/.github/dependabot.yml +0 -18
- data/.github/workflows/jruby.yml +0 -28
- data/.github/workflows/main.yml +0 -64
- data/.github/workflows/truffle_ruby.yml +0 -24
- data/.gitignore +0 -14
- data/.rspec +0 -2
- data/.rubocop.yml +0 -69
- data/.yardopts +0 -4
- data/Gemfile +0 -24
- data/Rakefile +0 -53
- data/omniauth.gemspec +0 -26
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
module OmniAuth
|
|
2
|
+
module Strategy
|
|
3
|
+
module ClassMethods
|
|
4
|
+
DISPATCH_METHODS = %i[call! phase_call options_call? request_call? on_auth_path?].freeze
|
|
5
|
+
private_constant :DISPATCH_METHODS
|
|
6
|
+
|
|
7
|
+
# True when requests are dispatched by OmniAuth's own #call! and its
|
|
8
|
+
# phase checks, so #call can tell which ones would go to the app.
|
|
9
|
+
# They may live in Strategy or in a module it includes, like Paths.
|
|
10
|
+
# Methods patched directly onto Strategy count as its own.
|
|
11
|
+
#
|
|
12
|
+
# @api private
|
|
13
|
+
def default_dispatch?
|
|
14
|
+
return @default_dispatch if instance_variable_defined?(:@default_dispatch)
|
|
15
|
+
|
|
16
|
+
@default_dispatch = DISPATCH_METHODS.all? { |m| Strategy.ancestors.include?(instance_method(m).owner) }
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# Returns an inherited set of default options set at the class-level
|
|
20
|
+
# for each strategy.
|
|
21
|
+
def default_options
|
|
22
|
+
@default_options ||= begin
|
|
23
|
+
parent = superclass
|
|
24
|
+
Options.new((parent.default_options if parent.is_a?(ClassMethods)))
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# This allows for more declarative subclassing of strategies by allowing
|
|
29
|
+
# default options to be set using a simple configure call.
|
|
30
|
+
#
|
|
31
|
+
# @param options [Hash] If supplied, these will be the default options (deep-merged into the superclass's default options).
|
|
32
|
+
# @yield [Options] The options Mash that allows you to set your defaults as you'd like.
|
|
33
|
+
#
|
|
34
|
+
# @example Using a yield to configure the default options.
|
|
35
|
+
#
|
|
36
|
+
# class MyStrategy
|
|
37
|
+
# include OmniAuth::Strategy
|
|
38
|
+
#
|
|
39
|
+
# configure do |c|
|
|
40
|
+
# c.foo = 'bar'
|
|
41
|
+
# end
|
|
42
|
+
# end
|
|
43
|
+
#
|
|
44
|
+
# @example Using a hash to configure the default options.
|
|
45
|
+
#
|
|
46
|
+
# class MyStrategy
|
|
47
|
+
# include OmniAuth::Strategy
|
|
48
|
+
# configure foo: 'bar'
|
|
49
|
+
# end
|
|
50
|
+
def configure(options = nil)
|
|
51
|
+
if block_given?
|
|
52
|
+
yield default_options
|
|
53
|
+
else
|
|
54
|
+
default_options.deep_merge!(options || {})
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Directly declare a default option for your class. This is a useful from
|
|
59
|
+
# a documentation perspective as it provides a simple line-by-line analysis
|
|
60
|
+
# of the kinds of options your strategy provides by default.
|
|
61
|
+
#
|
|
62
|
+
# @param name [Symbol] The key of the default option in your configuration hash.
|
|
63
|
+
# @param value [Object] The value your object defaults to. Nil if not provided.
|
|
64
|
+
#
|
|
65
|
+
# @example
|
|
66
|
+
#
|
|
67
|
+
# class MyStrategy
|
|
68
|
+
# include OmniAuth::Strategy
|
|
69
|
+
#
|
|
70
|
+
# option :foo, 'bar'
|
|
71
|
+
# option
|
|
72
|
+
# end
|
|
73
|
+
def option(name, value = nil)
|
|
74
|
+
default_options[name] = value
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Sets (and retrieves) option key names for initializer arguments to be
|
|
78
|
+
# recorded as. This takes care of 90% of the use cases for overriding
|
|
79
|
+
# the initializer in OmniAuth Strategies.
|
|
80
|
+
def args(args = nil)
|
|
81
|
+
if args
|
|
82
|
+
@args = args.is_a?(Array) ? args : [args]
|
|
83
|
+
return
|
|
84
|
+
end
|
|
85
|
+
return @args if instance_variable_defined?(:@args)
|
|
86
|
+
|
|
87
|
+
parent = superclass
|
|
88
|
+
parent.is_a?(ClassMethods) ? parent.args : []
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
%w[uid info extra credentials].each do |fetcher|
|
|
92
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
|
93
|
+
attr_reader :#{fetcher}_proc # attr_reader :uid_proc
|
|
94
|
+
private :#{fetcher}_proc # private :uid_proc
|
|
95
|
+
|
|
96
|
+
def #{fetcher}(&block) # def uid(&block)
|
|
97
|
+
return #{fetcher}_proc unless block_given? # return uid_proc unless block_given?
|
|
98
|
+
@#{fetcher}_proc = block # @uid_proc = block
|
|
99
|
+
end # end
|
|
100
|
+
|
|
101
|
+
def #{fetcher}_stack(context) # def uid_stack(context)
|
|
102
|
+
compile_stack(self.ancestors, :#{fetcher}, context) # compile_stack(self.ancestors, :uid, context)
|
|
103
|
+
end # end
|
|
104
|
+
RUBY
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def compile_stack(ancestors, method, context)
|
|
108
|
+
stack = ancestors.inject([]) do |a, ancestor|
|
|
109
|
+
# Only strategy classes define these blocks. Other ancestors may
|
|
110
|
+
# respond to the same names (e.g. a monkeypatched Object#info).
|
|
111
|
+
a << context.instance_eval(&ancestor.public_send(method)) if ancestor.is_a?(ClassMethods) && ancestor.public_send(method)
|
|
112
|
+
a
|
|
113
|
+
end
|
|
114
|
+
stack.reverse
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module OmniAuth
|
|
2
|
+
module Strategy
|
|
3
|
+
# Builds the auth hash from the uid, info, credentials, and extra
|
|
4
|
+
# blocks a strategy declares with the class-level fetcher DSL.
|
|
5
|
+
module Fetchers
|
|
6
|
+
def uid
|
|
7
|
+
self.class.uid_stack(self).last
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def info
|
|
11
|
+
merge_stack(self.class.info_stack(self))
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def credentials
|
|
15
|
+
merge_stack(self.class.credentials_stack(self))
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def extra
|
|
19
|
+
merge_stack(self.class.extra_stack(self))
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def auth_hash
|
|
23
|
+
credentials_data = credentials
|
|
24
|
+
extra_data = extra
|
|
25
|
+
AuthHash.new(:provider => name, :uid => uid).tap do |auth|
|
|
26
|
+
auth.info = info unless skip_info?
|
|
27
|
+
auth.credentials = credentials_data if credentials_data
|
|
28
|
+
auth.extra = extra_data if extra_data
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# Determines whether or not user info should be retrieved. This
|
|
33
|
+
# allows some strategies to save a call to an external API service
|
|
34
|
+
# for existing users. You can use it either by setting the `:skip_info`
|
|
35
|
+
# to true or by setting `:skip_info` to a Proc that takes a uid and
|
|
36
|
+
# evaluates to true when you would like to skip info.
|
|
37
|
+
#
|
|
38
|
+
# @example
|
|
39
|
+
#
|
|
40
|
+
# use MyStrategy, :skip_info => lambda{|uid| User.find_by_uid(uid)}
|
|
41
|
+
def skip_info?
|
|
42
|
+
return false unless options.skip_info?
|
|
43
|
+
return true unless options.skip_info.respond_to?(:call)
|
|
44
|
+
|
|
45
|
+
options.skip_info.call(uid)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
protected
|
|
49
|
+
|
|
50
|
+
def merge_stack(stack)
|
|
51
|
+
merged = {} #: Hash[untyped, untyped]
|
|
52
|
+
stack.each { |hash| merged.merge!(hash) }
|
|
53
|
+
merged
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module OmniAuth
|
|
2
|
+
module Strategy
|
|
3
|
+
# Guards against forged hosts. Unless a full_host is set, callback URLs
|
|
4
|
+
# use the request's host, which comes from the Host or X-Forwarded-Host
|
|
5
|
+
# header, so a forged one would send the provider a redirect_uri on
|
|
6
|
+
# another host.
|
|
7
|
+
module Hosts
|
|
8
|
+
protected
|
|
9
|
+
|
|
10
|
+
# Whether callback URLs may use this request's host. They always may
|
|
11
|
+
# when a full_host is set, since then the request's host isn't used.
|
|
12
|
+
# Otherwise, if OmniAuth.config.allowed_hosts is set, the host must
|
|
13
|
+
# match one of its entries: a string matches the whole host, ignoring
|
|
14
|
+
# case, and a regexp must match the whole host.
|
|
15
|
+
def allowed_host?
|
|
16
|
+
return true if full_host_set?
|
|
17
|
+
|
|
18
|
+
allowed_hosts = OmniAuth.config.allowed_hosts
|
|
19
|
+
return true unless allowed_hosts
|
|
20
|
+
|
|
21
|
+
host = request.host
|
|
22
|
+
allowed_hosts.any? do |allowed|
|
|
23
|
+
allowed.instance_of?(Regexp) ? /\A(?:#{allowed})\z/ === host : allowed.casecmp?(host)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def full_host_set?
|
|
28
|
+
!(options[:full_host] || OmniAuth.config.full_host).nil?
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def warn_if_using_request_host
|
|
32
|
+
return if full_host_set? || OmniAuth.config.allowed_hosts
|
|
33
|
+
|
|
34
|
+
log :warn, <<-WARN
|
|
35
|
+
OmniAuth is building callback URLs from the request's host, which comes
|
|
36
|
+
from the Host or X-Forwarded-Host header and can be forged unless your
|
|
37
|
+
app or a proxy in front of it checks it. To fix this, set either:
|
|
38
|
+
OmniAuth.config.full_host = 'https://example.com'
|
|
39
|
+
OmniAuth.config.allowed_hosts = ['example.com']
|
|
40
|
+
WARN
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def invalid_host!
|
|
44
|
+
fail!(:invalid_host, Error.new('The request host is not in OmniAuth.config.allowed_hosts'))
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
module OmniAuth
|
|
2
|
+
module Strategy
|
|
3
|
+
# Works out the request, callback, and setup paths for a strategy and
|
|
4
|
+
# whether the current request is on one of them, plus the full URLs
|
|
5
|
+
# built from them.
|
|
6
|
+
module Paths
|
|
7
|
+
# Returns true if the environment recognizes either the
|
|
8
|
+
# request or callback path.
|
|
9
|
+
def on_auth_path?
|
|
10
|
+
on_request_path? || on_callback_path?
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def on_request_path?
|
|
14
|
+
if options[:request_path].respond_to?(:call)
|
|
15
|
+
options.fetch(:request_path).call(env)
|
|
16
|
+
else
|
|
17
|
+
on_path?(request_path)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def on_callback_path?
|
|
22
|
+
on_path?(callback_path) || current_path.sub(FORMAT_EXTENSION_REGEX, EMPTY_STRING).casecmp(callback_path).zero?
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def on_path?(path)
|
|
26
|
+
current_path.casecmp(path).zero?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def path_prefix
|
|
30
|
+
options[:path_prefix] || OmniAuth.config.path_prefix
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def custom_path(kind)
|
|
34
|
+
if options[kind].respond_to?(:call)
|
|
35
|
+
result = options.fetch(kind).call(env)
|
|
36
|
+
return nil unless result.is_a?(String)
|
|
37
|
+
|
|
38
|
+
result
|
|
39
|
+
else
|
|
40
|
+
options[kind]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def request_path
|
|
45
|
+
@request_path ||=
|
|
46
|
+
if options[:request_path].is_a?(String)
|
|
47
|
+
options.fetch(:request_path)
|
|
48
|
+
else
|
|
49
|
+
"#{script_name}#{path_prefix}/#{name}"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def callback_path
|
|
54
|
+
@callback_path ||= callback_path_option || custom_path(:request_path) || "#{script_name}#{path_prefix}/#{name}/callback"
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def setup_path
|
|
58
|
+
options[:setup_path] || "#{path_prefix}/#{name}/setup"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
CURRENT_PATH_REGEX = %r{/$}.freeze
|
|
62
|
+
FORMAT_EXTENSION_REGEX = /\.\w+\z/.freeze
|
|
63
|
+
EMPTY_STRING = ''.freeze
|
|
64
|
+
# Repeated slashes are collapsed, as Rails routing does, so a proxy
|
|
65
|
+
# that sends //auth/:provider still reaches the strategy.
|
|
66
|
+
def current_path
|
|
67
|
+
@current_path ||= request.path.downcase.squeeze('/').sub(CURRENT_PATH_REGEX, EMPTY_STRING)
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def query_string
|
|
71
|
+
request.query_string.empty? ? '' : "?#{request.query_string}"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# The scheme and host for URLs such as callback_url: the strategy's
|
|
75
|
+
# :full_host option, else OmniAuth.config.full_host, else the
|
|
76
|
+
# request's. Either setting can be a string or a proc taking the env.
|
|
77
|
+
def full_host
|
|
78
|
+
host = options[:full_host] || OmniAuth.config.full_host
|
|
79
|
+
case host
|
|
80
|
+
when String then host
|
|
81
|
+
when Proc then host.call(env)
|
|
82
|
+
else full_host_from_request
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def callback_url
|
|
87
|
+
full_host + callback_path + query_string
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def script_name
|
|
91
|
+
current_env = @env
|
|
92
|
+
return '' if current_env.nil?
|
|
93
|
+
|
|
94
|
+
current_env['SCRIPT_NAME'] || ''
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
protected
|
|
98
|
+
|
|
99
|
+
# The :callback_path option: a string, or a lambda that returns true
|
|
100
|
+
# when the current path is the callback path.
|
|
101
|
+
def callback_path_option
|
|
102
|
+
option = options[:callback_path]
|
|
103
|
+
return option if option.is_a?(String)
|
|
104
|
+
|
|
105
|
+
current_path if option.respond_to?(:call) && option.call(env)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
# The scheme, host, and port of the current request, or an empty
|
|
109
|
+
# string if the request URL isn't absolute.
|
|
110
|
+
def full_host_from_request
|
|
111
|
+
# in Rack 1.3.x, request.url explodes if scheme is nil
|
|
112
|
+
return '' unless request.scheme && URI.parse(request.url).absolute?
|
|
113
|
+
|
|
114
|
+
uri = URI.parse(request.url.sub(/\?.*/, ''))
|
|
115
|
+
uri.path = ''
|
|
116
|
+
# sometimes the url is actually showing http inside rails because the
|
|
117
|
+
# other layers (like nginx) have handled the ssl termination.
|
|
118
|
+
uri.scheme = 'https' if ssl?
|
|
119
|
+
String(uri)
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Rack env values that mean the request came in over HTTPS.
|
|
123
|
+
SSL_ENV_VALUES = {
|
|
124
|
+
'HTTPS' => 'on',
|
|
125
|
+
'HTTP_X_FORWARDED_SSL' => 'on',
|
|
126
|
+
'HTTP_X_FORWARDED_SCHEME' => 'https',
|
|
127
|
+
'rack.url_scheme' => 'https'
|
|
128
|
+
}.freeze
|
|
129
|
+
|
|
130
|
+
# Reads request.env rather than env, so full_host and callback_url also
|
|
131
|
+
# work outside a Rack call, as when a strategy's tests stub #request.
|
|
132
|
+
def ssl?
|
|
133
|
+
request_env = request.env
|
|
134
|
+
# A proxy chain can list several protocols; the first is the client's.
|
|
135
|
+
forwarded_proto = request_env['HTTP_X_FORWARDED_PROTO'].to_s.split(',').first
|
|
136
|
+
forwarded_proto.eql?('https') || SSL_ENV_VALUES.any? { |key, value| request_env[key].eql?(value) }
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module OmniAuth
|
|
2
|
+
module Strategy
|
|
3
|
+
# Keeps the origin and params of several sign-ins in progress at once,
|
|
4
|
+
# for example in several tabs, so each callback gets its own. Without
|
|
5
|
+
# this, the session holds a single omniauth.origin and omniauth.params,
|
|
6
|
+
# and starting a sign-in replaces the last one's.
|
|
7
|
+
#
|
|
8
|
+
# A strategy opts in when its provider sends a value from the request
|
|
9
|
+
# phase back to the callback, such as OAuth 2.0's state. Its request
|
|
10
|
+
# phase calls remember_sign_in with that value, and it overrides
|
|
11
|
+
# callback_sign_in_key to return the value from the callback.
|
|
12
|
+
module SignIns
|
|
13
|
+
# How many sign-ins are remembered. Remembering another forgets the
|
|
14
|
+
# oldest.
|
|
15
|
+
MAX_REMEMBERED_SIGN_INS = 5
|
|
16
|
+
|
|
17
|
+
# Remembers the origin and params stored for the current request phase
|
|
18
|
+
# under key, which the provider sends back to the callback.
|
|
19
|
+
def remember_sign_in(key)
|
|
20
|
+
return if key.empty?
|
|
21
|
+
|
|
22
|
+
sign_ins = remembered_sign_ins
|
|
23
|
+
sign_ins.delete(key)
|
|
24
|
+
sign_ins[key] = {'origin' => session['omniauth.origin'], 'params' => session.fetch('omniauth.params')}
|
|
25
|
+
session['omniauth.sign_ins'] = sign_ins.to_a.last(MAX_REMEMBERED_SIGN_INS).to_h
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# The key the callback sends back, which a strategy that calls
|
|
29
|
+
# remember_sign_in returns. Nil for a strategy that doesn't.
|
|
30
|
+
def callback_sign_in_key; end
|
|
31
|
+
|
|
32
|
+
protected
|
|
33
|
+
|
|
34
|
+
# The origin and params for this callback, removed from the session:
|
|
35
|
+
# the ones remembered under its key, or else omniauth.origin and
|
|
36
|
+
# omniauth.params, which hold the latest sign-in's.
|
|
37
|
+
def recall_sign_in
|
|
38
|
+
fallback = {'origin' => session.delete('omniauth.origin'), 'params' => session.delete('omniauth.params')}
|
|
39
|
+
key = callback_sign_in_key
|
|
40
|
+
sign_ins = remembered_sign_ins
|
|
41
|
+
remembered = sign_ins.keys.detect { |stored| Rack::Utils.secure_compare(stored, key) } if key.instance_of?(String)
|
|
42
|
+
sign_in = sign_ins.delete(remembered)
|
|
43
|
+
return fallback unless sign_in
|
|
44
|
+
|
|
45
|
+
session['omniauth.sign_ins'] = sign_ins
|
|
46
|
+
sign_in
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# A copy of the remembered sign-ins, which are changed by assigning the
|
|
50
|
+
# session key, not in place.
|
|
51
|
+
def remembered_sign_ins
|
|
52
|
+
sign_ins = session['omniauth.sign_ins']
|
|
53
|
+
sign_ins.is_a?(Hash) ? sign_ins.dup : {}
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
module OmniAuth
|
|
2
|
+
module Strategy
|
|
3
|
+
# Runs the request and callback phases against OmniAuth.config.mock_auth
|
|
4
|
+
# instead of the provider when OmniAuth.config.test_mode is enabled.
|
|
5
|
+
module TestMode
|
|
6
|
+
# This is called in lieu of the normal request process
|
|
7
|
+
# in the event that OmniAuth has been configured to be
|
|
8
|
+
# in test mode.
|
|
9
|
+
def mock_call!(*)
|
|
10
|
+
if request_call?
|
|
11
|
+
mock_request_call
|
|
12
|
+
elsif on_callback_path?
|
|
13
|
+
mock_callback_call
|
|
14
|
+
else
|
|
15
|
+
call_app!
|
|
16
|
+
end
|
|
17
|
+
rescue StandardError => e
|
|
18
|
+
handle_phase_error(e)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def mock_request_call
|
|
22
|
+
setup_phase
|
|
23
|
+
|
|
24
|
+
run_hook(:request_validation_phase)
|
|
25
|
+
|
|
26
|
+
session['omniauth.params'] = omniauth_params
|
|
27
|
+
|
|
28
|
+
run_hook(:before_request_phase)
|
|
29
|
+
|
|
30
|
+
store_origin if options.origin_param
|
|
31
|
+
|
|
32
|
+
result = redirect(callback_url)
|
|
33
|
+
|
|
34
|
+
run_hook(:after_request_phase)
|
|
35
|
+
result
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def mock_callback_call
|
|
39
|
+
setup_phase
|
|
40
|
+
|
|
41
|
+
origin = session.delete('omniauth.origin')
|
|
42
|
+
env['omniauth.origin'] ||= origin
|
|
43
|
+
env['omniauth.origin'] = nil if env.fetch('omniauth.origin').eql?('')
|
|
44
|
+
env['omniauth.params'] = session.delete('omniauth.params') || {}
|
|
45
|
+
|
|
46
|
+
mocked_auth = OmniAuth.mock_auth_for(name)
|
|
47
|
+
env['omniauth.auth'] = mocked_auth unless mocked_auth.instance_of?(Symbol)
|
|
48
|
+
run_hook(:before_callback_phase)
|
|
49
|
+
mocked_auth.instance_of?(Symbol) ? fail!(mocked_auth) : call_app!
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|