omniauth 0.3.0.rc3 → 1.0.0.pr1
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.
- data/.gemtest +0 -0
- data/.gitignore +56 -0
- data/.rspec +2 -0
- data/.travis.yml +7 -0
- data/.yardopts +4 -0
- data/Gemfile +11 -0
- data/Guardfile +10 -0
- data/{LICENSE.md → LICENSE} +1 -1
- data/README.md +130 -152
- data/Rakefile +6 -0
- data/lib/omniauth/auth_hash.rb +47 -0
- data/lib/omniauth/builder.rb +33 -0
- data/lib/omniauth/form.rb +191 -0
- data/lib/omniauth/strategy.rb +429 -0
- data/lib/omniauth/test/phony_session.rb +8 -0
- data/lib/omniauth/test/strategy_macros.rb +34 -0
- data/lib/omniauth/test/strategy_test_case.rb +49 -0
- data/lib/omniauth/test.rb +12 -0
- data/lib/omniauth/version.rb +1 -17
- data/lib/omniauth.rb +135 -6
- data/omniauth.gemspec +28 -0
- data/spec/omniauth/auth_hash_spec.rb +103 -0
- data/spec/omniauth/builder_spec.rb +20 -0
- data/spec/omniauth/strategy_spec.rb +601 -0
- data/spec/omniauth_spec.rb +82 -0
- data/spec/spec_helper.rb +12 -0
- metadata +138 -143
|
@@ -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
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe OmniAuth do
|
|
4
|
+
describe '.strategies' do
|
|
5
|
+
it 'should increase when a new strategy is made' do
|
|
6
|
+
lambda{ class ExampleStrategy
|
|
7
|
+
include OmniAuth::Strategy
|
|
8
|
+
end }.should change(OmniAuth.strategies, :size).by(1)
|
|
9
|
+
OmniAuth.strategies.last.should == ExampleStrategy
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
context 'configuration' do
|
|
14
|
+
describe '.defaults' do
|
|
15
|
+
it 'should be a hash of default configuration' do
|
|
16
|
+
OmniAuth::Configuration.defaults.should be_kind_of(Hash)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should be callable from .configure' do
|
|
21
|
+
OmniAuth.configure do |c|
|
|
22
|
+
c.should be_kind_of(OmniAuth::Configuration)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
before do
|
|
27
|
+
@old_path_prefix = OmniAuth.config.path_prefix
|
|
28
|
+
@old_on_failure = OmniAuth.config.on_failure
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
after do
|
|
32
|
+
OmniAuth.configure do |config|
|
|
33
|
+
config.path_prefix = @old_path_prefix
|
|
34
|
+
config.on_failure = @old_on_failure
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'should be able to set the path' do
|
|
39
|
+
OmniAuth.configure do |config|
|
|
40
|
+
config.path_prefix = '/awesome'
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
OmniAuth.config.path_prefix.should == '/awesome'
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'should be able to set the on_failure rack app' do
|
|
47
|
+
OmniAuth.configure do |config|
|
|
48
|
+
config.on_failure do
|
|
49
|
+
'yoyo'
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
OmniAuth.config.on_failure.call.should == 'yoyo'
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
describe '::Utils' do
|
|
58
|
+
describe '.deep_merge' do
|
|
59
|
+
it 'should combine hashes' do
|
|
60
|
+
OmniAuth::Utils.deep_merge({'abc' => {'def' => 123}}, {'abc' => {'foo' => 'bar'}}).should == {
|
|
61
|
+
'abc' => {'def' => 123, 'foo' => 'bar'}
|
|
62
|
+
}
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
describe '.camelize' do
|
|
67
|
+
it 'should work on normal cases' do
|
|
68
|
+
{
|
|
69
|
+
'some_word' => 'SomeWord',
|
|
70
|
+
'AnotherWord' => 'AnotherWord',
|
|
71
|
+
'one' => 'One',
|
|
72
|
+
'three_words_now' => 'ThreeWordsNow'
|
|
73
|
+
}.each_pair{ |k,v| OmniAuth::Utils.camelize(k).should == v }
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'should work in special cases that have been added' do
|
|
77
|
+
OmniAuth.config.add_camelization('oauth', 'OAuth')
|
|
78
|
+
OmniAuth::Utils.camelize(:oauth).should == 'OAuth'
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
require 'simplecov'
|
|
2
|
+
SimpleCov.start
|
|
3
|
+
require 'rspec'
|
|
4
|
+
require 'rack/test'
|
|
5
|
+
require 'omniauth'
|
|
6
|
+
require 'omniauth/test'
|
|
7
|
+
|
|
8
|
+
RSpec.configure do |config|
|
|
9
|
+
config.include Rack::Test::Methods
|
|
10
|
+
config.extend OmniAuth::Test::StrategyMacros, :type => :strategy
|
|
11
|
+
end
|
|
12
|
+
|