omniauth 0.3.2 → 1.0.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of omniauth might be problematic. Click here for more details.

@@ -0,0 +1,12 @@
1
+ module OmniAuth
2
+
3
+ # Support for testing OmniAuth strategies.
4
+ module Test
5
+
6
+ autoload :PhonySession, 'omniauth/test/phony_session'
7
+ autoload :StrategyMacros, 'omniauth/test/strategy_macros'
8
+ autoload :StrategyTestCase, 'omniauth/test/strategy_test_case'
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,8 @@
1
+ class OmniAuth::Test::PhonySession
2
+ def initialize(app); @app = app end
3
+ def call(env)
4
+ @session ||= (env['rack.session'] || {})
5
+ env['rack.session'] = @session
6
+ @app.call(env)
7
+ end
8
+ end
@@ -0,0 +1,34 @@
1
+ module OmniAuth
2
+
3
+ module Test
4
+
5
+ module StrategyMacros
6
+
7
+ def sets_an_auth_hash
8
+ it 'should set an auth hash' do
9
+ last_request.env['omniauth.auth'].should be_kind_of(Hash)
10
+ end
11
+ end
12
+
13
+ def sets_provider_to(provider)
14
+ it "should set the provider to #{provider}" do
15
+ (last_request.env['omniauth.auth'] || {})['provider'].should == provider
16
+ end
17
+ end
18
+
19
+ def sets_uid_to(uid)
20
+ it "should set the UID to #{uid}" do
21
+ (last_request.env['omniauth.auth'] || {})['uid'].should == uid
22
+ end
23
+ end
24
+
25
+ def sets_user_info_to(user_info)
26
+ it "should set the user_info to #{user_info}" do
27
+ (last_request.env['omniauth.auth'] || {})['user_info'].should == user_info
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+
34
+ end
@@ -0,0 +1,49 @@
1
+ require 'rack'
2
+ require 'omniauth/test'
3
+
4
+ module OmniAuth
5
+
6
+ module Test
7
+
8
+ # Support for testing OmniAuth strategies.
9
+ #
10
+ # @example Usage
11
+ # class MyStrategyTest < Test::Unit::TestCase
12
+ # include OmniAuth::Test::StrategyTestCase
13
+ # def strategy
14
+ # # return the parameters to a Rack::Builder map call:
15
+ # [MyStrategy.new, :some, :configuration, :options => 'here']
16
+ # end
17
+ # setup do
18
+ # post '/auth/my_strategy/callback', :user => { 'name' => 'Dylan', 'id' => '445' }
19
+ # end
20
+ # end
21
+ module StrategyTestCase
22
+
23
+ def app
24
+ strat = self.strategy
25
+ resp = self.app_response
26
+ Rack::Builder.new {
27
+ use OmniAuth::Test::PhonySession
28
+ use *strat
29
+ run lambda {|env| [404, {'Content-Type' => 'text/plain'}, [resp || env.key?('omniauth.auth').to_s]] }
30
+ }.to_app
31
+ end
32
+
33
+ def app_response
34
+ nil
35
+ end
36
+
37
+ def session
38
+ last_request.env['rack.session']
39
+ end
40
+
41
+ def strategy
42
+ raise NotImplementedError.new('Including specs must define #strategy')
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -1,19 +1,3 @@
1
1
  module OmniAuth
2
- module Version
3
- unless defined?(::OmniAuth::Version::MAJOR)
4
- MAJOR = 0
5
- end
6
- unless defined?(::OmniAuth::Version::MINOR)
7
- MINOR = 3
8
- end
9
- unless defined?(::OmniAuth::Version::PATCH)
10
- PATCH = 2
11
- end
12
- unless defined?(::OmniAuth::Version::PRE)
13
- PRE = nil
14
- end
15
- unless defined?(::OmniAuth::Version::STRING)
16
- STRING = [MAJOR, MINOR, PATCH, PRE].compact.join('.')
17
- end
18
- end
2
+ VERSION = "1.0.0.beta1"
19
3
  end
data/omniauth.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # encoding: utf-8
2
+ require File.expand_path('../lib/omniauth/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = 'omniauth'
6
+ gem.description = %q{A generalized Rack framework for multiple-provider authentication.}
7
+ gem.authors = ['Michael Bleigh', 'Erik Michaels-Ober']
8
+ gem.email = ['michael@intridea.com', 'sferik@gmail.com']
9
+
10
+ gem.add_runtime_dependency 'rack'
11
+ gem.add_runtime_dependency 'hashie', '~> 1.2'
12
+
13
+ gem.add_development_dependency 'maruku', '~> 0.6'
14
+ gem.add_development_dependency 'simplecov', '~> 0.4'
15
+ gem.add_development_dependency 'rack-test', '~> 0.5'
16
+ gem.add_development_dependency 'rake', '~> 0.8'
17
+ gem.add_development_dependency 'rdiscount', '~> 1.6'
18
+ gem.add_development_dependency 'rspec', '~> 2.5'
19
+ gem.add_development_dependency 'yard', '~> 0.7'
20
+
21
+ gem.version = OmniAuth::VERSION
22
+ gem.files = `git ls-files`.split("\n")
23
+ gem.homepage = 'http://github.com/intridea/omniauth'
24
+ gem.require_paths = ['lib']
25
+ gem.required_rubygems_version = Gem::Requirement.new('>= 1.3.6') if gem.respond_to? :required_rubygems_version=
26
+ gem.summary = gem.description
27
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
28
+ end
@@ -0,0 +1,108 @@
1
+ require 'spec_helper'
2
+
3
+ describe OmniAuth::AuthHash do
4
+ subject{ OmniAuth::AuthHash.new }
5
+ it 'should convert a supplied info key into an InfoHash object' do
6
+ subject.info = {:first_name => 'Awesome'}
7
+ subject.info.should be_kind_of(OmniAuth::AuthHash::InfoHash)
8
+ subject.info.first_name.should == 'Awesome'
9
+ end
10
+
11
+ describe '#valid?' do
12
+ subject{ OmniAuth::AuthHash.new(:uid => '123', :provider => 'example', :info => {:name => 'Steven'}) }
13
+
14
+ it 'should be valid with the right parameters' do
15
+ subject.should be_valid
16
+ end
17
+
18
+ it 'should require a uid' do
19
+ subject.uid = nil
20
+ subject.should_not be_valid
21
+ end
22
+
23
+ it 'should require a provider' do
24
+ subject.provider = nil
25
+ subject.should_not be_valid
26
+ end
27
+
28
+ it 'should require a name in the user info hash' do
29
+ subject.info.name = nil
30
+ subject.should_not be_valid?
31
+ end
32
+ end
33
+
34
+ describe '#name' do
35
+ subject{ OmniAuth::AuthHash.new(
36
+ :info => {
37
+ :name => 'Phillip J. Fry',
38
+ :first_name => 'Phillip',
39
+ :last_name => 'Fry',
40
+ :nickname => 'meatbag',
41
+ :email => 'fry@planetexpress.com'
42
+ })}
43
+
44
+ it 'should default to the name key' do
45
+ subject.info.name.should == 'Phillip J. Fry'
46
+ end
47
+
48
+ it 'should fall back to go to first_name last_name concatenation' do
49
+ subject.info.name = nil
50
+ subject.info.name.should == 'Phillip Fry'
51
+ end
52
+
53
+ it 'should display only a first or last name if only that is available' do
54
+ subject.info.name = nil
55
+ subject.info.first_name = nil
56
+ subject.info.name.should == 'Fry'
57
+ end
58
+
59
+ it 'should display the nickname if no name, first, or last is available' do
60
+ subject.info.name = nil
61
+ %w(first_name last_name).each{|k| subject.info[k] = nil}
62
+ subject.info.name.should == 'meatbag'
63
+ end
64
+
65
+ it 'should display the email if no name, first, last, or nick is available' do
66
+ subject.info.name = nil
67
+ %w(first_name last_name nickname).each{|k| subject.info[k] = nil}
68
+ subject.info.name.should == 'fry@planetexpress.com'
69
+ end
70
+ end
71
+
72
+ describe '#to_hash' do
73
+ subject{ OmniAuth::AuthHash.new(:uid => '123', :provider => 'test', :name => 'Bob Example')}
74
+ let(:hash){ subject.to_hash }
75
+
76
+ it 'should be a plain old hash' do
77
+ hash.class.should == ::Hash
78
+ end
79
+
80
+ it 'should have string keys' do
81
+ hash.keys.should be_include('uid')
82
+ end
83
+
84
+ it 'should convert an info hash as well' do
85
+ subject.info = {:first_name => 'Bob', :last_name => 'Example'}
86
+ subject.info.class.should == OmniAuth::AuthHash::InfoHash
87
+ subject.to_hash['info'].class.should == ::Hash
88
+ end
89
+
90
+ it 'should supply the calculated name in the converted hash' do
91
+ subject.info = {:first_name => 'Bob', :last_name => 'Examplar'}
92
+ hash['info']['name'].should == 'Bob Examplar'
93
+ end
94
+
95
+ it 'should not pollute the URL hash with "name" etc' do
96
+ subject.info = {'urls' => {'Homepage' => "http://homepage.com"}}
97
+ subject.to_hash['info']['urls'].should == {'Homepage' => "http://homepage.com"}
98
+ end
99
+ end
100
+
101
+ describe OmniAuth::AuthHash::InfoHash do
102
+ describe '#valid?' do
103
+ it 'should be valid if there is a name' do
104
+ OmniAuth::AuthHash::InfoHash.new(:name => 'Awesome').should be_valid
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,20 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ describe OmniAuth::Builder do
4
+ describe '#provider' do
5
+ it 'should translate a symbol to a constant' do
6
+ OmniAuth::Strategies.should_receive(:const_get).with('MyStrategy').and_return(Class.new)
7
+ OmniAuth::Builder.new(nil) do
8
+ provider :my_strategy
9
+ end
10
+ end
11
+
12
+ it 'should also just accept a class' do
13
+ class ::ExampleClass; end
14
+
15
+ lambda{ OmniAuth::Builder.new(nil) do
16
+ provider ::ExampleClass
17
+ end }.should_not raise_error
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe OmniAuth::Strategies::Developer do
4
+ let(:app){ Rack::Builder.new do |b|
5
+ b.use Rack::Session::Cookie
6
+ b.use OmniAuth::Strategies::Developer
7
+ b.run lambda{|env| [200, {}, ['Not Found']]}
8
+ end.to_app }
9
+
10
+ context 'request phase' do
11
+ before(:each){ get '/auth/developer' }
12
+
13
+ it 'should display a form' do
14
+ last_response.status.should == 200
15
+ last_response.body.should be_include("<form")
16
+ end
17
+
18
+ it 'should have the callback as the action for the form' do
19
+ last_response.body.should be_include("action='/auth/developer/callback'")
20
+ end
21
+
22
+ it 'should have a text field for each of the fields' do
23
+ last_response.body.scan('<input').size.should == 2
24
+ end
25
+ end
26
+
27
+ context 'callback phase' do
28
+ let(:auth_hash){ last_request.env['omniauth.auth'] }
29
+
30
+ context 'with default options' do
31
+ before do
32
+ post '/auth/developer/callback', :name => 'Example User', :email => 'user@example.com'
33
+ end
34
+
35
+ it 'should set the name in the auth hash' do
36
+ auth_hash.info.name.should == 'Example User'
37
+ end
38
+
39
+ it 'should set the email in the auth hash' do
40
+ auth_hash.info.email.should == 'user@example.com'
41
+ end
42
+
43
+ it 'should set the uid to the email' do
44
+ auth_hash.uid.should == 'user@example.com'
45
+ end
46
+ end
47
+
48
+ context 'with custom options' do
49
+ let(:app){ Rack::Builder.new do |b|
50
+ b.use Rack::Session::Cookie
51
+ b.use OmniAuth::Strategies::Developer, :fields => [:first_name, :last_name], :uid_field => :last_name
52
+ b.run lambda{|env| [200, {}, ['Not Found']]}
53
+ end.to_app }
54
+
55
+ before do
56
+ @options = {:uid_field => :last_name, :fields => [:first_name, :last_name]}
57
+ post '/auth/developer/callback', :first_name => 'Example', :last_name => 'User'
58
+ end
59
+
60
+ it 'should set info fields properly' do
61
+ auth_hash.info.name.should == 'Example User'
62
+ end
63
+
64
+ it 'should set the uid properly' do
65
+ auth_hash.uid.should == 'User'
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,601 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+
3
+ class ExampleStrategy
4
+ include OmniAuth::Strategy
5
+ option :name, 'test'
6
+ def call(env); self.call!(env) end
7
+ attr_reader :last_env
8
+ def request_phase
9
+ @fail = fail!(options[:failure]) if options[:failure]
10
+ @last_env = env
11
+ return @fail if @fail
12
+ raise "Request Phase"
13
+ end
14
+ def callback_phase
15
+ @fail = fail!(options[:failure]) if options[:failure]
16
+ @last_env = env
17
+ return @fail if @fail
18
+ raise "Callback Phase"
19
+ end
20
+ end
21
+
22
+ def make_env(path = '/auth/test', props = {})
23
+ {
24
+ 'REQUEST_METHOD' => 'GET',
25
+ 'PATH_INFO' => path,
26
+ 'rack.session' => {},
27
+ 'rack.input' => StringIO.new('test=true')
28
+ }.merge(props)
29
+ end
30
+
31
+ describe OmniAuth::Strategy do
32
+ let(:app){ lambda{|env| [404, {}, ['Awesome']]}}
33
+ let(:fresh_strategy){ c = Class.new; c.send :include, OmniAuth::Strategy; c}
34
+
35
+ describe '.default_options' do
36
+ it 'should be inherited from a parent class' do
37
+ superklass = Class.new
38
+ superklass.send :include, OmniAuth::Strategy
39
+ superklass.configure do |c|
40
+ c.foo = 'bar'
41
+ end
42
+
43
+ klass = Class.new(superklass)
44
+ klass.default_options.foo.should == 'bar'
45
+ end
46
+ end
47
+
48
+ describe '.configure' do
49
+ subject { klass = Class.new; klass.send :include, OmniAuth::Strategy; klass }
50
+ it 'should take a block and allow for default options setting' do
51
+ subject.configure do |c|
52
+ c.wakka = 'doo'
53
+ end
54
+ subject.default_options["wakka"].should == "doo"
55
+ end
56
+
57
+ it 'should take a hash and deep merge it' do
58
+ subject.configure :abc => {:def => 123}
59
+ subject.configure :abc => {:hgi => 456}
60
+ subject.default_options['abc'].should == {'def' => 123, 'hgi' => 456}
61
+ end
62
+ end
63
+
64
+ describe '#skip_info?' do
65
+ it 'should be true if options.skip_info is true' do
66
+ ExampleStrategy.new(app, :skip_info => true).should be_skip_info
67
+ end
68
+
69
+ it 'should be false if options.skip_info is false' do
70
+ ExampleStrategy.new(app, :skip_info => false).should_not be_skip_info
71
+ end
72
+
73
+ it 'should be false by default' do
74
+ ExampleStrategy.new(app).should_not be_skip_info
75
+ end
76
+
77
+ it 'should be true if options.skip_info is a callable that evaluates to truthy' do
78
+ instance = ExampleStrategy.new(app, :skip_info => lambda{|uid| uid})
79
+ instance.should_receive(:uid).and_return(true)
80
+ instance.should be_skip_info
81
+ end
82
+ end
83
+
84
+ describe '.option' do
85
+ subject { klass = Class.new; klass.send :include, OmniAuth::Strategy; klass }
86
+ it 'should set a default value' do
87
+ subject.option :abc, 123
88
+ subject.default_options.abc.should == 123
89
+ end
90
+
91
+ it 'should set the default value to nil if none is provided' do
92
+ subject.option :abc
93
+ subject.default_options.abc.should be_nil
94
+ end
95
+ end
96
+
97
+ describe '.args' do
98
+ subject{ c = Class.new; c.send :include, OmniAuth::Strategy; c }
99
+ it 'should set args to the specified argument if there is one' do
100
+ subject.args [:abc, :def]
101
+ subject.args.should == [:abc, :def]
102
+ end
103
+
104
+ it 'should be inheritable' do
105
+ subject.args [:abc, :def]
106
+ c = Class.new(subject)
107
+ c.args.should == [:abc, :def]
108
+ end
109
+ end
110
+
111
+ context 'fetcher procs' do
112
+ subject{ fresh_strategy }
113
+ %w(uid info credentials extra).each do |fetcher|
114
+ it ".#{fetcher} should be able to set and retrieve a proc" do
115
+ proc = lambda{ "Hello" }
116
+ subject.send(fetcher, &proc)
117
+ subject.send(fetcher).should == proc
118
+ end
119
+ end
120
+ end
121
+
122
+ context 'fetcher stacks' do
123
+ subject{ fresh_strategy }
124
+ %w(uid info credentials extra).each do |fetcher|
125
+ it ".#{fetcher}_stack should be an array of called ancestral procs" do
126
+ fetchy = Proc.new{ "Hello" }
127
+ subject.send(fetcher, &fetchy)
128
+ subject.send("#{fetcher}_stack", subject.new(app)).should == ["Hello"]
129
+ end
130
+ end
131
+ end
132
+
133
+ %w(request_phase).each do |abstract_method|
134
+ it "#{abstract_method} should raise a NotImplementedError" do
135
+ strat = Class.new
136
+ strat.send :include, OmniAuth::Strategy
137
+ lambda{ strat.new(app).send(abstract_method) }.should raise_error(NotImplementedError)
138
+ end
139
+ end
140
+
141
+ describe '#auth_hash' do
142
+ subject do
143
+ klass = Class.new
144
+ klass.send :include, OmniAuth::Strategy
145
+ klass.option :name, 'auth_hasher'
146
+ klass
147
+ end
148
+ let(:instance){ subject.new(app) }
149
+
150
+ it 'should call through to uid and info' do
151
+ instance.should_receive :uid
152
+ instance.should_receive :info
153
+ instance.auth_hash
154
+ end
155
+
156
+ it 'should return an AuthHash' do
157
+ instance.stub!(:uid).and_return('123')
158
+ instance.stub!(:info).and_return(:name => 'Hal Awesome')
159
+ hash = instance.auth_hash
160
+ hash.should be_kind_of(OmniAuth::AuthHash)
161
+ hash.uid.should == '123'
162
+ hash.info.name.should == 'Hal Awesome'
163
+ end
164
+ end
165
+
166
+ describe '#initialize' do
167
+ context 'options extraction' do
168
+ it 'should be the last argument if the last argument is a Hash' do
169
+ ExampleStrategy.new(app, :abc => 123).options[:abc].should == 123
170
+ end
171
+
172
+ it 'should be the default options if any are provided' do
173
+ ExampleStrategy.stub!(:default_options).and_return(OmniAuth::Strategy::Options.new(:abc => 123))
174
+ ExampleStrategy.new(app).options.abc.should == 123
175
+ end
176
+ end
177
+
178
+ context 'custom args' do
179
+ subject{ c = Class.new; c.send :include, OmniAuth::Strategy; c }
180
+ it 'should set options based on the arguments if they are supplied' do
181
+ subject.args [:abc, :def]
182
+ s = subject.new app, 123, 456
183
+ s.options[:abc].should == 123
184
+ s.options[:def].should == 456
185
+ end
186
+ end
187
+ end
188
+
189
+ it '#call should duplicate and call' do
190
+ klass = Class.new
191
+ klass.send :include, OmniAuth::Strategy
192
+ instance = klass.new(app)
193
+ instance.should_receive(:dup).and_return(instance)
194
+ instance.call({'rack.session' => {}})
195
+ end
196
+
197
+ describe '#inspect' do
198
+ it 'should just be the class name in Ruby inspect format' do
199
+ ExampleStrategy.new(app).inspect.should == '#<ExampleStrategy>'
200
+ end
201
+ end
202
+
203
+ describe '#redirect' do
204
+ it 'should use javascript if :iframe is true' do
205
+ response = ExampleStrategy.new(app, :iframe => true).redirect("http://abc.com")
206
+ response.last.body.first.should be_include("top.location.href")
207
+ end
208
+ end
209
+
210
+ describe '#callback_phase' do
211
+ subject{ k = Class.new; k.send :include, OmniAuth::Strategy; k.new(app) }
212
+
213
+ it 'should set the auth hash' do
214
+ env = make_env
215
+ subject.stub!(:env).and_return(env)
216
+ subject.stub!(:auth_hash).and_return("AUTH HASH")
217
+ subject.callback_phase
218
+ env['omniauth.auth'].should == "AUTH HASH"
219
+ end
220
+ end
221
+
222
+ describe '#full_host' do
223
+ let(:strategy){ ExampleStrategy.new(app, {}) }
224
+ it 'should not freak out if there is a pipe in the URL' do
225
+ strategy.call!(make_env('/whatever', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'facebook.lame', 'QUERY_STRING' => 'code=asofibasf|asoidnasd', 'SCRIPT_NAME' => '', 'SERVER_PORT' => 80))
226
+ lambda{ strategy.full_host }.should_not raise_error
227
+ end
228
+ end
229
+
230
+ describe '#uid' do
231
+ subject{ fresh_strategy }
232
+ it "should be the current class's uid if one exists" do
233
+ subject.uid{ "Hi" }
234
+ subject.new(app).uid.should == "Hi"
235
+ end
236
+
237
+ it "should inherit if it can" do
238
+ subject.uid{ "Hi" }
239
+ c = Class.new(subject)
240
+ c.new(app).uid.should == "Hi"
241
+ end
242
+ end
243
+
244
+ %w(info credentials extra).each do |fetcher|
245
+ subject{ fresh_strategy }
246
+ it "should be the current class's proc call if one exists" do
247
+ subject.send(fetcher){ {:abc => 123} }
248
+ subject.new(app).send(fetcher).should == {:abc => 123}
249
+ end
250
+
251
+ it 'should inherit by merging with preference for the latest class' do
252
+ subject.send(fetcher){ {:abc => 123, :def => 456} }
253
+ c = Class.new(subject)
254
+ c.send(fetcher){ {:abc => 789} }
255
+ c.new(app).send(fetcher).should == {:abc => 789, :def => 456}
256
+ end
257
+ end
258
+
259
+ describe '#call' do
260
+ let(:strategy){ ExampleStrategy.new(app, @options || {}) }
261
+
262
+ context 'omniauth.origin' do
263
+ it 'should be set on the request phase' do
264
+ lambda{ strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin')) }.should raise_error("Request Phase")
265
+ strategy.last_env['rack.session']['omniauth.origin'].should == 'http://example.com/origin'
266
+ end
267
+
268
+ it 'should be turned into an env variable on the callback phase' do
269
+ lambda{ strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'})) }.should raise_error("Callback Phase")
270
+ strategy.last_env['omniauth.origin'].should == 'http://example.com/origin'
271
+ end
272
+
273
+ it 'should set from the params if provided' do
274
+ lambda{ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo')) }.should raise_error('Request Phase')
275
+ strategy.last_env['rack.session']['omniauth.origin'].should == '/foo'
276
+ end
277
+
278
+ it 'should be set on the failure env' do
279
+ OmniAuth.config.should_receive(:on_failure).and_return(lambda{|env| env})
280
+ @options = {:failure => :forced_fail}
281
+ strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => '/awesome'}))
282
+ end
283
+
284
+ context "with script_name" do
285
+ it 'should be set on the request phase, containing full path' do
286
+ env = {'HTTP_REFERER' => 'http://example.com/sub_uri/origin', 'SCRIPT_NAME' => '/sub_uri' }
287
+ lambda{ strategy.call(make_env('/auth/test', env)) }.should raise_error("Request Phase")
288
+ strategy.last_env['rack.session']['omniauth.origin'].should == 'http://example.com/sub_uri/origin'
289
+ end
290
+
291
+ it 'should be turned into an env variable on the callback phase, containing full path' do
292
+ env = {
293
+ 'rack.session' => {'omniauth.origin' => 'http://example.com/sub_uri/origin'},
294
+ 'SCRIPT_NAME' => '/sub_uri'
295
+ }
296
+
297
+ lambda{ strategy.call(make_env('/auth/test/callback', env)) }.should raise_error("Callback Phase")
298
+ strategy.last_env['omniauth.origin'].should == 'http://example.com/sub_uri/origin'
299
+ end
300
+
301
+ end
302
+ end
303
+
304
+ context 'default paths' do
305
+ it 'should use the default request path' do
306
+ lambda{ strategy.call(make_env) }.should raise_error("Request Phase")
307
+ end
308
+
309
+ it 'should be case insensitive on request path' do
310
+ lambda{ strategy.call(make_env('/AUTH/Test'))}.should raise_error("Request Phase")
311
+ end
312
+
313
+ it 'should be case insensitive on callback path' do
314
+ lambda{ strategy.call(make_env('/AUTH/TeSt/CaLlBAck'))}.should raise_error("Callback Phase")
315
+ end
316
+
317
+ it 'should use the default callback path' do
318
+ lambda{ strategy.call(make_env('/auth/test/callback')) }.should raise_error("Callback Phase")
319
+ end
320
+
321
+ it 'should strip trailing spaces on request' do
322
+ lambda{ strategy.call(make_env('/auth/test/')) }.should raise_error("Request Phase")
323
+ end
324
+
325
+ it 'should strip trailing spaces on callback' do
326
+ lambda{ strategy.call(make_env('/auth/test/callback/')) }.should raise_error("Callback Phase")
327
+ end
328
+
329
+ context 'callback_url' do
330
+ it 'uses the default callback_path' do
331
+ strategy.should_receive(:full_host).and_return('http://example.com')
332
+
333
+ lambda{ strategy.call(make_env) }.should raise_error("Request Phase")
334
+
335
+ strategy.callback_url.should == 'http://example.com/auth/test/callback'
336
+ end
337
+
338
+ it 'preserves the query parameters' do
339
+ strategy.stub(:full_host).and_return('http://example.com')
340
+ begin
341
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
342
+ rescue RuntimeError; end
343
+ strategy.callback_url.should == 'http://example.com/auth/test/callback?id=5'
344
+ end
345
+
346
+ it 'consider script name' do
347
+ strategy.stub(:full_host).and_return('http://example.com')
348
+ begin
349
+ strategy.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri'))
350
+ rescue RuntimeError; end
351
+ strategy.callback_url.should == 'http://example.com/sub_uri/auth/test/callback'
352
+ end
353
+ end
354
+ end
355
+
356
+ context ':form option' do
357
+ it 'should call through to the supplied form option if one exists' do
358
+ strategy.options.form = lambda{|env| "Called me!"}
359
+ strategy.call(make_env('/auth/test')).should == "Called me!"
360
+ end
361
+
362
+ it 'should call through to the app if :form => true is set as an option' do
363
+ strategy.options.form = true
364
+ strategy.call(make_env('/auth/test')).should == app.call(make_env('/auth/test'))
365
+ end
366
+ end
367
+
368
+ context 'custom paths' do
369
+ it 'should use a custom request_path if one is provided' do
370
+ @options = {:request_path => '/awesome'}
371
+ lambda{ strategy.call(make_env('/awesome')) }.should raise_error("Request Phase")
372
+ end
373
+
374
+ it 'should use a custom callback_path if one is provided' do
375
+ @options = {:callback_path => '/radical'}
376
+ lambda{ strategy.call(make_env('/radical')) }.should raise_error("Callback Phase")
377
+ end
378
+
379
+ context 'callback_url' do
380
+ it 'uses a custom callback_path if one is provided' do
381
+ @options = {:callback_path => '/radical'}
382
+ strategy.should_receive(:full_host).and_return('http://example.com')
383
+
384
+ lambda{ strategy.call(make_env('/radical')) }.should raise_error("Callback Phase")
385
+
386
+ strategy.callback_url.should == 'http://example.com/radical'
387
+ end
388
+
389
+ it 'preserves the query parameters' do
390
+ @options = {:callback_path => '/radical'}
391
+ strategy.stub(:full_host).and_return('http://example.com')
392
+ begin
393
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
394
+ rescue RuntimeError; end
395
+ strategy.callback_url.should == 'http://example.com/radical?id=5'
396
+ end
397
+ end
398
+ end
399
+
400
+ context 'custom prefix' do
401
+ before do
402
+ @options = {:path_prefix => '/wowzers'}
403
+ end
404
+
405
+ it 'should use a custom prefix for request' do
406
+ lambda{ strategy.call(make_env('/wowzers/test')) }.should raise_error("Request Phase")
407
+ end
408
+
409
+ it 'should use a custom prefix for callback' do
410
+ lambda{ strategy.call(make_env('/wowzers/test/callback')) }.should raise_error("Callback Phase")
411
+ end
412
+
413
+ context 'callback_url' do
414
+ it 'uses a custom prefix' do
415
+ strategy.should_receive(:full_host).and_return('http://example.com')
416
+
417
+ lambda{ strategy.call(make_env('/wowzers/test')) }.should raise_error("Request Phase")
418
+
419
+ strategy.callback_url.should == 'http://example.com/wowzers/test/callback'
420
+ end
421
+
422
+ it 'preserves the query parameters' do
423
+ strategy.stub(:full_host).and_return('http://example.com')
424
+ begin
425
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
426
+ rescue RuntimeError; end
427
+ strategy.callback_url.should == 'http://example.com/wowzers/test/callback?id=5'
428
+ end
429
+ end
430
+ end
431
+
432
+ context 'request method restriction' do
433
+ before do
434
+ OmniAuth.config.allowed_request_methods = [:post]
435
+ end
436
+
437
+ it 'should not allow a request method of the wrong type' do
438
+ lambda{ strategy.call(make_env)}.should_not raise_error
439
+ end
440
+
441
+ it 'should allow a request method of the correct type' do
442
+ lambda{ strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'POST'))}.should raise_error("Request Phase")
443
+ end
444
+
445
+ after do
446
+ OmniAuth.config.allowed_request_methods = [:get, :post]
447
+ end
448
+ end
449
+
450
+ context 'receiving an OPTIONS request' do
451
+ shared_examples_for "an OPTIONS request" do
452
+ it 'should respond with 200' do
453
+ response[0].should == 200
454
+ end
455
+
456
+ it 'should set the Allow header properly' do
457
+ response[1]['Allow'].should == "GET, POST"
458
+ end
459
+ end
460
+
461
+ context 'to the request path' do
462
+ let(:response) { strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'OPTIONS')) }
463
+ it_should_behave_like 'an OPTIONS request'
464
+ end
465
+
466
+ context 'to the request path' do
467
+ let(:response) { strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'OPTIONS')) }
468
+ it_should_behave_like 'an OPTIONS request'
469
+ end
470
+
471
+ context 'to some other path' do
472
+ it 'should not short-circuit the request' do
473
+ env = make_env('/other', 'REQUEST_METHOD' => 'OPTIONS')
474
+ strategy.call(env).should == app.call(env)
475
+ end
476
+ end
477
+ end
478
+
479
+ context 'test mode' do
480
+ before do
481
+ OmniAuth.config.test_mode = true
482
+ end
483
+
484
+ it 'should short circuit the request phase entirely' do
485
+ response = strategy.call(make_env)
486
+ response[0].should == 302
487
+ response[1]['Location'].should == '/auth/test/callback'
488
+ end
489
+
490
+ it 'should be case insensitive on request path' do
491
+ strategy.call(make_env('/AUTH/Test'))[0].should == 302
492
+ end
493
+
494
+ it 'should respect SCRIPT_NAME (a.k.a. BaseURI)' do
495
+ response = strategy.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri'))
496
+ response[1]['Location'].should == '/sub_uri/auth/test/callback'
497
+ end
498
+
499
+ it 'should be case insensitive on callback path' do
500
+ strategy.call(make_env('/AUTH/TeSt/CaLlBAck')).should == strategy.call(make_env('/auth/test/callback'))
501
+ end
502
+
503
+ it 'should maintain query string parameters' do
504
+ response = strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'cheese=stilton'))
505
+ response[1]['Location'].should == '/auth/test/callback?cheese=stilton'
506
+ end
507
+
508
+ it 'should not short circuit requests outside of authentication' do
509
+ strategy.call(make_env('/')).should == app.call(make_env('/'))
510
+ end
511
+
512
+ it 'should respond with the default hash if none is set' do
513
+ strategy.call make_env('/auth/test/callback')
514
+ strategy.env['omniauth.auth']['uid'].should == '1234'
515
+ end
516
+
517
+ it 'should respond with a provider-specific hash if one is set' do
518
+ OmniAuth.config.mock_auth[:test] = {
519
+ 'uid' => 'abc'
520
+ }
521
+
522
+ strategy.call make_env('/auth/test/callback')
523
+ strategy.env['omniauth.auth']['uid'].should == 'abc'
524
+ end
525
+
526
+ it 'should simulate login failure if mocked data is set as a symbol' do
527
+ OmniAuth.config.mock_auth[:test] = :invalid_credentials
528
+
529
+ strategy.call make_env('/auth/test/callback')
530
+ strategy.env['omniauth.error.type'].should == :invalid_credentials
531
+ end
532
+
533
+ it 'should set omniauth.origin on the request phase' do
534
+ strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin'))
535
+ strategy.env['rack.session']['omniauth.origin'].should == 'http://example.com/origin'
536
+ end
537
+
538
+ it 'should set omniauth.origin from the params if provided' do
539
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo'))
540
+ strategy.env['rack.session']['omniauth.origin'].should == '/foo'
541
+ end
542
+
543
+ it 'should turn omniauth.origin into an env variable on the callback phase' do
544
+ OmniAuth.config.mock_auth[:test] = {}
545
+
546
+ strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'}))
547
+ strategy.env['omniauth.origin'].should == 'http://example.com/origin'
548
+ end
549
+ end
550
+
551
+ context 'custom full_host' do
552
+ it 'should be the string when a string is there' do
553
+ OmniAuth.config.full_host = 'my.host.com'
554
+ strategy.full_host.should == 'my.host.com'
555
+ end
556
+
557
+ it 'should run the proc with the env when it is a proc' do
558
+ OmniAuth.config.full_host = Proc.new{|env| env['HOST']}
559
+ strategy.call(make_env('/auth/test', 'HOST' => 'my.host.net'))
560
+ strategy.full_host.should == 'my.host.net'
561
+ end
562
+ end
563
+ end
564
+
565
+ context 'setup phase' do
566
+ context 'when options[:setup] = true' do
567
+ let(:strategy){ ExampleStrategy.new(app, :setup => true) }
568
+ let(:app){lambda{|env| env['omniauth.strategy'].options[:awesome] = 'sauce' if env['PATH_INFO'] == '/auth/test/setup'; [404, {}, 'Awesome'] }}
569
+
570
+ it 'should call through to /auth/:provider/setup' do
571
+ strategy.call(make_env('/auth/test'))
572
+ strategy.options[:awesome].should == 'sauce'
573
+ end
574
+
575
+ it 'should not call through on a non-omniauth endpoint' do
576
+ strategy.call(make_env('/somewhere/else'))
577
+ strategy.options[:awesome].should_not == 'sauce'
578
+ end
579
+ end
580
+
581
+ context 'when options[:setup] is an app' do
582
+ let(:setup_proc) do
583
+ Proc.new do |env|
584
+ env['omniauth.strategy'].options[:awesome] = 'sauce'
585
+ end
586
+ end
587
+
588
+ let(:strategy){ ExampleStrategy.new(app, :setup => setup_proc) }
589
+
590
+ it 'should not call the app on a non-omniauth endpoint' do
591
+ strategy.call(make_env('/somehwere/else'))
592
+ strategy.options[:awesome].should_not == 'sauce'
593
+ end
594
+
595
+ it 'should call the rack app' do
596
+ strategy.call(make_env('/auth/test'))
597
+ strategy.options[:awesome].should == 'sauce'
598
+ end
599
+ end
600
+ end
601
+ end