omniauth-rightsignature 0.0.1 → 0.0.2

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.
@@ -0,0 +1,23 @@
1
+ require 'helper'
2
+
3
+ describe OmniAuth::Form do
4
+ describe '.build' do
5
+ it 'yields the instance when called with a block and argument' do
6
+ OmniAuth::Form.build { |f| expect(f).to be_kind_of(OmniAuth::Form) }
7
+ end
8
+
9
+ it 'evaluates in the instance when called with a block and no argument' do
10
+ OmniAuth::Form.build { |f| expect(f.class).to eq(OmniAuth::Form) }
11
+ end
12
+ end
13
+
14
+ describe '#initialize' do
15
+ it 'sets the form action to the passed :url option' do
16
+ expect(OmniAuth::Form.new(:url => '/awesome').to_html).to be_include("action='/awesome'")
17
+ end
18
+
19
+ it 'sets an H1 tag from the passed :title option' do
20
+ expect(OmniAuth::Form.new(:title => 'Something Cool').to_html).to be_include('<h1>Something Cool</h1>')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,73 @@
1
+ require 'helper'
2
+
3
+ describe OmniAuth::Strategies::Developer do
4
+ let(:app) do
5
+ Rack::Builder.new do |b|
6
+ b.use Rack::Session::Cookie, :secret => 'abc123'
7
+ b.use OmniAuth::Strategies::Developer
8
+ b.run lambda { |_env| [200, {}, ['Not Found']] }
9
+ end.to_app
10
+ end
11
+
12
+ context 'request phase' do
13
+ before(:each) { get '/auth/developer' }
14
+
15
+ it 'displays a form' do
16
+ expect(last_response.status).to eq(200)
17
+ expect(last_response.body).to be_include('<form')
18
+ end
19
+
20
+ it 'has the callback as the action for the form' do
21
+ expect(last_response.body).to be_include("action='/auth/developer/callback'")
22
+ end
23
+
24
+ it 'has a text field for each of the fields' do
25
+ expect(last_response.body.scan('<input').size).to eq(2)
26
+ end
27
+ end
28
+
29
+ context 'callback phase' do
30
+ let(:auth_hash) { last_request.env['omniauth.auth'] }
31
+
32
+ context 'with default options' do
33
+ before do
34
+ post '/auth/developer/callback', :name => 'Example User', :email => 'user@example.com'
35
+ end
36
+
37
+ it 'sets the name in the auth hash' do
38
+ expect(auth_hash.info.name).to eq('Example User')
39
+ end
40
+
41
+ it 'sets the email in the auth hash' do
42
+ expect(auth_hash.info.email).to eq('user@example.com')
43
+ end
44
+
45
+ it 'sets the uid to the email' do
46
+ expect(auth_hash.uid).to eq('user@example.com')
47
+ end
48
+ end
49
+
50
+ context 'with custom options' do
51
+ let(:app) do
52
+ Rack::Builder.new do |b|
53
+ b.use Rack::Session::Cookie, :secret => 'abc123'
54
+ b.use OmniAuth::Strategies::Developer, :fields => [:first_name, :last_name], :uid_field => :last_name
55
+ b.run lambda { |_env| [200, {}, ['Not Found']] }
56
+ end.to_app
57
+ end
58
+
59
+ before do
60
+ @options = {:uid_field => :last_name, :fields => [:first_name, :last_name]}
61
+ post '/auth/developer/callback', :first_name => 'Example', :last_name => 'User'
62
+ end
63
+
64
+ it 'sets info fields properly' do
65
+ expect(auth_hash.info.name).to eq('Example User')
66
+ end
67
+
68
+ it 'sets the uid properly' do
69
+ expect(auth_hash.uid).to eq('User')
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,765 @@
1
+ require 'helper'
2
+
3
+ def make_env(path = '/auth/test', props = {})
4
+ {
5
+ 'REQUEST_METHOD' => 'GET',
6
+ 'PATH_INFO' => path,
7
+ 'rack.session' => {},
8
+ 'rack.input' => StringIO.new('test=true'),
9
+ }.merge(props)
10
+ end
11
+
12
+ describe OmniAuth::Strategy do
13
+ let(:app) do
14
+ lambda { |_env| [404, {}, ['Awesome']] }
15
+ end
16
+
17
+ let(:fresh_strategy) do
18
+ c = Class.new
19
+ c.send(:include, OmniAuth::Strategy)
20
+ end
21
+
22
+ describe '.default_options' do
23
+ it 'is inherited from a parent class' do
24
+ superklass = Class.new
25
+ superklass.send :include, OmniAuth::Strategy
26
+ superklass.configure do |c|
27
+ c.foo = 'bar'
28
+ end
29
+
30
+ klass = Class.new(superklass)
31
+ expect(klass.default_options.foo).to eq('bar')
32
+ end
33
+ end
34
+
35
+ describe '.configure' do
36
+ subject do
37
+ c = Class.new
38
+ c.send(:include, OmniAuth::Strategy)
39
+ end
40
+
41
+ context 'when block is passed' do
42
+ it 'allows for default options setting' do
43
+ subject.configure do |c|
44
+ c.wakka = 'doo'
45
+ end
46
+ expect(subject.default_options['wakka']).to eq('doo')
47
+ end
48
+
49
+ it "works when block doesn't evaluate to true" do
50
+ environment_variable = nil
51
+ subject.configure do |c|
52
+ c.abc = '123'
53
+ c.hgi = environment_variable
54
+ end
55
+ expect(subject.default_options['abc']).to eq('123')
56
+ end
57
+ end
58
+
59
+ it 'takes a hash and deep merge it' do
60
+ subject.configure :abc => {:def => 123}
61
+ subject.configure :abc => {:hgi => 456}
62
+ expect(subject.default_options['abc']).to eq('def' => 123, 'hgi' => 456)
63
+ end
64
+ end
65
+
66
+ describe '#skip_info?' do
67
+ it 'is true if options.skip_info is true' do
68
+ expect(ExampleStrategy.new(app, :skip_info => true)).to be_skip_info
69
+ end
70
+
71
+ it 'is false if options.skip_info is false' do
72
+ expect(ExampleStrategy.new(app, :skip_info => false)).not_to be_skip_info
73
+ end
74
+
75
+ it 'is false by default' do
76
+ expect(ExampleStrategy.new(app)).not_to be_skip_info
77
+ end
78
+
79
+ it 'is true if options.skip_info is a callable that evaluates to truthy' do
80
+ instance = ExampleStrategy.new(app, :skip_info => lambda { |uid| uid })
81
+ expect(instance).to receive(:uid).and_return(true)
82
+ expect(instance).to be_skip_info
83
+ end
84
+ end
85
+
86
+ describe '.option' do
87
+ subject do
88
+ c = Class.new
89
+ c.send(:include, OmniAuth::Strategy)
90
+ end
91
+ it 'sets a default value' do
92
+ subject.option :abc, 123
93
+ expect(subject.default_options.abc).to eq(123)
94
+ end
95
+
96
+ it 'sets the default value to nil if none is provided' do
97
+ subject.option :abc
98
+ expect(subject.default_options.abc).to be_nil
99
+ end
100
+ end
101
+
102
+ describe '.args' do
103
+ subject do
104
+ c = Class.new
105
+ c.send(:include, OmniAuth::Strategy)
106
+ end
107
+
108
+ it 'sets args to the specified argument if there is one' do
109
+ subject.args [:abc, :def]
110
+ expect(subject.args).to eq([:abc, :def])
111
+ end
112
+
113
+ it 'is inheritable' do
114
+ subject.args [:abc, :def]
115
+ c = Class.new(subject)
116
+ expect(c.args).to eq([:abc, :def])
117
+ end
118
+
119
+ it 'accepts corresponding options as default arg values' do
120
+ subject.args [:a, :b]
121
+ subject.option :a, '1'
122
+ subject.option :b, '2'
123
+
124
+ expect(subject.new(nil).options.a).to eq '1'
125
+ expect(subject.new(nil).options.b).to eq '2'
126
+ expect(subject.new(nil, '3', '4').options.b).to eq '4'
127
+ expect(subject.new(nil, nil, '4').options.a).to eq nil
128
+ end
129
+ end
130
+
131
+ context 'fetcher procs' do
132
+ subject { fresh_strategy }
133
+ %w(uid info credentials extra).each do |fetcher|
134
+ describe ".#{fetcher}" do
135
+ it 'sets and retrieve a proc' do
136
+ proc = lambda { 'Hello' }
137
+ subject.send(fetcher, &proc)
138
+ expect(subject.send(fetcher)).to eq(proc)
139
+ end
140
+ end
141
+ end
142
+ end
143
+
144
+ context 'fetcher stacks' do
145
+ subject { fresh_strategy }
146
+ %w(uid info credentials extra).each do |fetcher|
147
+ describe ".#{fetcher}_stack" do
148
+ it 'is an array of called ancestral procs' do
149
+ fetchy = proc { 'Hello' }
150
+ subject.send(fetcher, &fetchy)
151
+ expect(subject.send("#{fetcher}_stack", subject.new(app))).to eq(['Hello'])
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ %w(request_phase).each do |abstract_method|
158
+ context "#{abstract_method}" do
159
+ it 'raises a NotImplementedError' do
160
+ strat = Class.new
161
+ strat.send :include, OmniAuth::Strategy
162
+ expect { strat.new(app).send(abstract_method) }.to raise_error(NotImplementedError)
163
+ end
164
+ end
165
+ end
166
+
167
+ describe '#auth_hash' do
168
+ subject do
169
+ klass = Class.new
170
+ klass.send :include, OmniAuth::Strategy
171
+ klass.option :name, 'auth_hasher'
172
+ klass
173
+ end
174
+ let(:instance) { subject.new(app) }
175
+
176
+ it 'calls through to uid and info' do
177
+ expect(instance).to receive(:uid)
178
+ expect(instance).to receive(:info)
179
+ instance.auth_hash
180
+ end
181
+
182
+ it 'returns an AuthHash' do
183
+ allow(instance).to receive(:uid).and_return('123')
184
+ allow(instance).to receive(:info).and_return(:name => 'Hal Awesome')
185
+ hash = instance.auth_hash
186
+ expect(hash).to be_kind_of(OmniAuth::AuthHash)
187
+ expect(hash.uid).to eq('123')
188
+ expect(hash.info.name).to eq('Hal Awesome')
189
+ end
190
+ end
191
+
192
+ describe '#initialize' do
193
+ context 'options extraction' do
194
+ it 'is the last argument if the last argument is a Hash' do
195
+ expect(ExampleStrategy.new(app, :abc => 123).options[:abc]).to eq(123)
196
+ end
197
+
198
+ it 'is the default options if any are provided' do
199
+ allow(ExampleStrategy).to receive(:default_options).and_return(OmniAuth::Strategy::Options.new(:abc => 123))
200
+ expect(ExampleStrategy.new(app).options.abc).to eq(123)
201
+ end
202
+ end
203
+
204
+ context 'custom args' do
205
+ subject do
206
+ c = Class.new
207
+ c.send(:include, OmniAuth::Strategy)
208
+ end
209
+
210
+ it 'sets options based on the arguments if they are supplied' do
211
+ subject.args [:abc, :def]
212
+ s = subject.new app, 123, 456
213
+ expect(s.options[:abc]).to eq(123)
214
+ expect(s.options[:def]).to eq(456)
215
+ end
216
+ end
217
+ end
218
+
219
+ describe '#call' do
220
+ it 'duplicates and calls' do
221
+ klass = Class.new
222
+ klass.send :include, OmniAuth::Strategy
223
+ instance = klass.new(app)
224
+ expect(instance).to receive(:dup).and_return(instance)
225
+ instance.call('rack.session' => {})
226
+ end
227
+ end
228
+
229
+ describe '#inspect' do
230
+ it 'returns the class name' do
231
+ expect(ExampleStrategy.new(app).inspect).to eq('#<ExampleStrategy>')
232
+ end
233
+ end
234
+
235
+ describe '#redirect' do
236
+ it 'uses javascript if :iframe is true' do
237
+ response = ExampleStrategy.new(app, :iframe => true).redirect('http://abc.com')
238
+ expect(response.last.body.first).to be_include('top.location.href')
239
+ end
240
+ end
241
+
242
+ describe '#callback_phase' do
243
+ subject do
244
+ c = Class.new
245
+ c.send(:include, OmniAuth::Strategy)
246
+ c.new(app)
247
+ end
248
+
249
+ it 'sets the auth hash' do
250
+ env = make_env
251
+ allow(subject).to receive(:env).and_return(env)
252
+ allow(subject).to receive(:auth_hash).and_return('AUTH HASH')
253
+ subject.callback_phase
254
+ expect(env['omniauth.auth']).to eq('AUTH HASH')
255
+ end
256
+ end
257
+
258
+ describe '#full_host' do
259
+ let(:strategy) { ExampleStrategy.new(app, {}) }
260
+ it 'remains calm when there is a pipe in the URL' do
261
+ strategy.call!(make_env('/whatever', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'facebook.lame', 'QUERY_STRING' => 'code=asofibasf|asoidnasd', 'SCRIPT_NAME' => '', 'SERVER_PORT' => 80))
262
+ expect { strategy.full_host }.not_to raise_error
263
+ end
264
+ end
265
+
266
+ describe '#uid' do
267
+ subject { fresh_strategy }
268
+ it "is the current class's uid if one exists" do
269
+ subject.uid { 'Hi' }
270
+ expect(subject.new(app).uid).to eq('Hi')
271
+ end
272
+
273
+ it 'inherits if it can' do
274
+ subject.uid { 'Hi' }
275
+ c = Class.new(subject)
276
+ expect(c.new(app).uid).to eq('Hi')
277
+ end
278
+ end
279
+
280
+ %w(info credentials extra).each do |fetcher|
281
+ subject { fresh_strategy }
282
+ it "is the current class's proc call if one exists" do
283
+ subject.send(fetcher) { {:abc => 123} }
284
+ expect(subject.new(app).send(fetcher)).to eq(:abc => 123)
285
+ end
286
+
287
+ it 'inherits by merging with preference for the latest class' do
288
+ subject.send(fetcher) { {:abc => 123, :def => 456} }
289
+ c = Class.new(subject)
290
+ c.send(fetcher) { {:abc => 789} }
291
+ expect(c.new(app).send(fetcher)).to eq(:abc => 789, :def => 456)
292
+ end
293
+ end
294
+
295
+ describe '#call' do
296
+ before(:all) do
297
+ @options = nil
298
+ end
299
+
300
+ let(:strategy) { ExampleStrategy.new(app, @options || {}) }
301
+
302
+ context 'omniauth.origin' do
303
+ it 'is set on the request phase' do
304
+ expect { strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin')) }.to raise_error('Request Phase')
305
+ expect(strategy.last_env['rack.session']['omniauth.origin']).to eq('http://example.com/origin')
306
+ end
307
+
308
+ it 'is turned into an env variable on the callback phase' do
309
+ expect { strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'})) }.to raise_error('Callback Phase')
310
+ expect(strategy.last_env['omniauth.origin']).to eq('http://example.com/origin')
311
+ end
312
+
313
+ it 'sets from the params if provided' do
314
+ expect { strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo')) }.to raise_error('Request Phase')
315
+ expect(strategy.last_env['rack.session']['omniauth.origin']).to eq('/foo')
316
+ end
317
+
318
+ it 'is set on the failure env' do
319
+ expect(OmniAuth.config).to receive(:on_failure).and_return(lambda { |env| env })
320
+ @options = {:failure => :forced_fail}
321
+ strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => '/awesome'}))
322
+ end
323
+
324
+ context 'with script_name' do
325
+ it 'is set on the request phase, containing full path' do
326
+ env = {'HTTP_REFERER' => 'http://example.com/sub_uri/origin', 'SCRIPT_NAME' => '/sub_uri'}
327
+ expect { strategy.call(make_env('/auth/test', env)) }.to raise_error('Request Phase')
328
+ expect(strategy.last_env['rack.session']['omniauth.origin']).to eq('http://example.com/sub_uri/origin')
329
+ end
330
+
331
+ it 'is turned into an env variable on the callback phase, containing full path' do
332
+ env = {
333
+ 'rack.session' => {'omniauth.origin' => 'http://example.com/sub_uri/origin'},
334
+ 'SCRIPT_NAME' => '/sub_uri',
335
+ }
336
+
337
+ expect { strategy.call(make_env('/auth/test/callback', env)) }.to raise_error('Callback Phase')
338
+ expect(strategy.last_env['omniauth.origin']).to eq('http://example.com/sub_uri/origin')
339
+ end
340
+ end
341
+ end
342
+
343
+ context 'default paths' do
344
+ it 'uses the default request path' do
345
+ expect { strategy.call(make_env) }.to raise_error('Request Phase')
346
+ end
347
+
348
+ it 'is case insensitive on request path' do
349
+ expect { strategy.call(make_env('/AUTH/Test')) }.to raise_error('Request Phase')
350
+ end
351
+
352
+ it 'is case insensitive on callback path' do
353
+ expect { strategy.call(make_env('/AUTH/TeSt/CaLlBAck')) }.to raise_error('Callback Phase')
354
+ end
355
+
356
+ it 'uses the default callback path' do
357
+ expect { strategy.call(make_env('/auth/test/callback')) }.to raise_error('Callback Phase')
358
+ end
359
+
360
+ it 'strips trailing spaces on request' do
361
+ expect { strategy.call(make_env('/auth/test/')) }.to raise_error('Request Phase')
362
+ end
363
+
364
+ it 'strips trailing spaces on callback' do
365
+ expect { strategy.call(make_env('/auth/test/callback/')) }.to raise_error('Callback Phase')
366
+ end
367
+
368
+ context 'callback_url' do
369
+ it 'uses the default callback_path' do
370
+ expect(strategy).to receive(:full_host).and_return('http://example.com')
371
+
372
+ expect { strategy.call(make_env) }.to raise_error('Request Phase')
373
+
374
+ expect(strategy.callback_url).to eq('http://example.com/auth/test/callback')
375
+ end
376
+
377
+ it 'preserves the query parameters' do
378
+ allow(strategy).to receive(:full_host).and_return('http://example.com')
379
+ begin
380
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
381
+ rescue RuntimeError
382
+ end
383
+ expect(strategy.callback_url).to eq('http://example.com/auth/test/callback?id=5')
384
+ end
385
+
386
+ it 'consider script name' do
387
+ allow(strategy).to receive(:full_host).and_return('http://example.com')
388
+ begin
389
+ strategy.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri'))
390
+ rescue RuntimeError
391
+ end
392
+ expect(strategy.callback_url).to eq('http://example.com/sub_uri/auth/test/callback')
393
+ end
394
+ end
395
+ end
396
+
397
+ context ':form option' do
398
+ it 'calls through to the supplied form option if one exists' do
399
+ strategy.options.form = lambda { |_env| 'Called me!' }
400
+ expect(strategy.call(make_env('/auth/test'))).to eq('Called me!')
401
+ end
402
+
403
+ it 'calls through to the app if :form => true is set as an option' do
404
+ strategy.options.form = true
405
+ expect(strategy.call(make_env('/auth/test'))).to eq(app.call(make_env('/auth/test')))
406
+ end
407
+ end
408
+
409
+ context 'dynamic paths' do
410
+ it 'runs the request phase if the custom request path evaluator is truthy' do
411
+ @options = {:request_path => lambda { |_env| true }}
412
+ expect { strategy.call(make_env('/asoufibasfi')) }.to raise_error('Request Phase')
413
+ end
414
+
415
+ it 'runs the callback phase if the custom callback path evaluator is truthy' do
416
+ @options = {:callback_path => lambda { |_env| true }}
417
+ expect { strategy.call(make_env('/asoufiasod')) }.to raise_error('Callback Phase')
418
+ end
419
+
420
+ it 'provides a custom callback path if request_path evals to a string' do
421
+ strategy_instance = fresh_strategy.new(nil, :request_path => lambda { |_env| '/auth/boo/callback/22' })
422
+ expect(strategy_instance.callback_path).to eq('/auth/boo/callback/22')
423
+ end
424
+
425
+ it 'correctly reports the callback path when the custom callback path evaluator is truthy' do
426
+ strategy_instance = ExampleStrategy.new(app, :callback_path => lambda { |env| env['PATH_INFO'] == '/auth/bish/bosh/callback' })
427
+
428
+ expect { strategy_instance.call(make_env('/auth/bish/bosh/callback')) }.to raise_error('Callback Phase')
429
+ expect(strategy_instance.callback_path).to eq('/auth/bish/bosh/callback')
430
+ end
431
+ end
432
+
433
+ context 'custom paths' do
434
+ it 'uses a custom request_path if one is provided' do
435
+ @options = {:request_path => '/awesome'}
436
+ expect { strategy.call(make_env('/awesome')) }.to raise_error('Request Phase')
437
+ end
438
+
439
+ it 'uses a custom callback_path if one is provided' do
440
+ @options = {:callback_path => '/radical'}
441
+ expect { strategy.call(make_env('/radical')) }.to raise_error('Callback Phase')
442
+ end
443
+
444
+ context 'callback_url' do
445
+ it 'uses a custom callback_path if one is provided' do
446
+ @options = {:callback_path => '/radical'}
447
+ expect(strategy).to receive(:full_host).and_return('http://example.com')
448
+
449
+ expect { strategy.call(make_env('/radical')) }.to raise_error('Callback Phase')
450
+
451
+ expect(strategy.callback_url).to eq('http://example.com/radical')
452
+ end
453
+
454
+ it 'preserves the query parameters' do
455
+ @options = {:callback_path => '/radical'}
456
+ allow(strategy).to receive(:full_host).and_return('http://example.com')
457
+ begin
458
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
459
+ rescue RuntimeError
460
+ end
461
+ expect(strategy.callback_url).to eq('http://example.com/radical?id=5')
462
+ end
463
+ end
464
+ end
465
+
466
+ context 'custom prefix' do
467
+ before do
468
+ @options = {:path_prefix => '/wowzers'}
469
+ end
470
+
471
+ it 'uses a custom prefix for request' do
472
+ expect { strategy.call(make_env('/wowzers/test')) }.to raise_error('Request Phase')
473
+ end
474
+
475
+ it 'uses a custom prefix for callback' do
476
+ expect { strategy.call(make_env('/wowzers/test/callback')) }.to raise_error('Callback Phase')
477
+ end
478
+
479
+ context 'callback_url' do
480
+ it 'uses a custom prefix' do
481
+ expect(strategy).to receive(:full_host).and_return('http://example.com')
482
+
483
+ expect { strategy.call(make_env('/wowzers/test')) }.to raise_error('Request Phase')
484
+
485
+ expect(strategy.callback_url).to eq('http://example.com/wowzers/test/callback')
486
+ end
487
+
488
+ it 'preserves the query parameters' do
489
+ allow(strategy).to receive(:full_host).and_return('http://example.com')
490
+ begin
491
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'id=5'))
492
+ rescue RuntimeError
493
+ end
494
+ expect(strategy.callback_url).to eq('http://example.com/wowzers/test/callback?id=5')
495
+ end
496
+ end
497
+ end
498
+
499
+ context 'request method restriction' do
500
+ before do
501
+ OmniAuth.config.allowed_request_methods = [:post]
502
+ end
503
+
504
+ it 'does not allow a request method of the wrong type' do
505
+ expect { strategy.call(make_env) }.not_to raise_error
506
+ end
507
+
508
+ it 'allows a request method of the correct type' do
509
+ expect { strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'POST')) }.to raise_error('Request Phase')
510
+ end
511
+
512
+ after do
513
+ OmniAuth.config.allowed_request_methods = [:get, :post]
514
+ end
515
+ end
516
+
517
+ context 'receiving an OPTIONS request' do
518
+ shared_examples_for 'an OPTIONS request' do
519
+ it 'responds with 200' do
520
+ expect(response[0]).to eq(200)
521
+ end
522
+
523
+ it 'sets the Allow header properly' do
524
+ expect(response[1]['Allow']).to eq('GET, POST')
525
+ end
526
+ end
527
+
528
+ context 'to the request path' do
529
+ let(:response) { strategy.call(make_env('/auth/test', 'REQUEST_METHOD' => 'OPTIONS')) }
530
+ it_behaves_like 'an OPTIONS request'
531
+ end
532
+
533
+ context 'to the request path' do
534
+ let(:response) { strategy.call(make_env('/auth/test/callback', 'REQUEST_METHOD' => 'OPTIONS')) }
535
+ it_behaves_like 'an OPTIONS request'
536
+ end
537
+
538
+ context 'to some other path' do
539
+ it 'does not short-circuit the request' do
540
+ env = make_env('/other', 'REQUEST_METHOD' => 'OPTIONS')
541
+ expect(strategy.call(env)).to eq(app.call(env))
542
+ end
543
+ end
544
+ end
545
+
546
+ context 'test mode' do
547
+ let(:app) do
548
+ # In test mode, the underlying app shouldn't be called on request phase.
549
+ lambda { |_env| [404, {'Content-Type' => 'text/html'}, []] }
550
+ end
551
+
552
+ before do
553
+ OmniAuth.config.test_mode = true
554
+ end
555
+
556
+ it 'short circuits the request phase entirely' do
557
+ response = strategy.call(make_env)
558
+ expect(response[0]).to eq(302)
559
+ expect(response[1]['Location']).to eq('/auth/test/callback')
560
+ end
561
+
562
+ it 'is case insensitive on request path' do
563
+ expect(strategy.call(make_env('/AUTH/Test'))[0]).to eq(302)
564
+ end
565
+
566
+ it 'respects SCRIPT_NAME (a.k.a. BaseURI)' do
567
+ response = strategy.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri'))
568
+ expect(response[1]['Location']).to eq('/sub_uri/auth/test/callback')
569
+ end
570
+
571
+ it 'redirects on failure' do
572
+ response = OmniAuth.config.on_failure.call(make_env('/auth/test', 'omniauth.error.type' => 'error'))
573
+ expect(response[0]).to eq(302)
574
+ expect(response[1]['Location']).to eq('/auth/failure?message=error')
575
+ end
576
+
577
+ it 'respects SCRIPT_NAME (a.k.a. BaseURI) on failure' do
578
+ response = OmniAuth.config.on_failure.call(make_env('/auth/test', 'SCRIPT_NAME' => '/sub_uri', 'omniauth.error.type' => 'error'))
579
+ expect(response[0]).to eq(302)
580
+ expect(response[1]['Location']).to eq('/sub_uri/auth/failure?message=error')
581
+ end
582
+
583
+ it 'is case insensitive on callback path' do
584
+ expect(strategy.call(make_env('/AUTH/TeSt/CaLlBAck')).first).to eq(strategy.call(make_env('/auth/test/callback')).first)
585
+ end
586
+
587
+ it 'maintains host and port' do
588
+ response = strategy.call(make_env('/auth/test', 'rack.url_scheme' => 'http', 'HTTP_HOST' => 'example.org', 'SERVER_PORT' => 3000))
589
+ expect(response[1]['Location']).to eq('http://example.org:3000/auth/test/callback')
590
+ end
591
+
592
+ it 'maintains query string parameters' do
593
+ response = strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'cheese=stilton'))
594
+ expect(response[1]['Location']).to eq('/auth/test/callback?cheese=stilton')
595
+ end
596
+
597
+ it 'does not short circuit requests outside of authentication' do
598
+ expect(strategy.call(make_env('/'))).to eq(app.call(make_env('/')))
599
+ end
600
+
601
+ it 'responds with the default hash if none is set' do
602
+ OmniAuth.config.mock_auth[:test] = nil
603
+
604
+ strategy.call make_env('/auth/test/callback')
605
+ expect(strategy.env['omniauth.auth']['uid']).to eq('1234')
606
+ end
607
+
608
+ it 'responds with a provider-specific hash if one is set' do
609
+ OmniAuth.config.mock_auth[:test] = {
610
+ 'uid' => 'abc',
611
+ }
612
+
613
+ strategy.call make_env('/auth/test/callback')
614
+ expect(strategy.env['omniauth.auth']['uid']).to eq('abc')
615
+ end
616
+
617
+ it 'simulates login failure if mocked data is set as a symbol' do
618
+ OmniAuth.config.mock_auth[:test] = :invalid_credentials
619
+
620
+ strategy.call make_env('/auth/test/callback')
621
+ expect(strategy.env['omniauth.error.type']).to eq(:invalid_credentials)
622
+ end
623
+
624
+ it 'sets omniauth.origin on the request phase' do
625
+ strategy.call(make_env('/auth/test', 'HTTP_REFERER' => 'http://example.com/origin'))
626
+ expect(strategy.env['rack.session']['omniauth.origin']).to eq('http://example.com/origin')
627
+ end
628
+
629
+ it 'sets omniauth.origin from the params if provided' do
630
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'origin=/foo'))
631
+ expect(strategy.env['rack.session']['omniauth.origin']).to eq('/foo')
632
+ end
633
+
634
+ it 'turns omniauth.origin into an env variable on the callback phase' do
635
+ OmniAuth.config.mock_auth[:test] = {}
636
+
637
+ strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'}))
638
+ expect(strategy.env['omniauth.origin']).to eq('http://example.com/origin')
639
+ end
640
+
641
+ it 'executes callback hook on the callback phase' do
642
+ OmniAuth.config.mock_auth[:test] = {}
643
+ OmniAuth.config.before_callback_phase do |env|
644
+ env['foobar'] = 'baz'
645
+ end
646
+ strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.origin' => 'http://example.com/origin'}))
647
+ expect(strategy.env['foobar']).to eq('baz')
648
+ end
649
+
650
+ it 'sets omniauth.params on the request phase' do
651
+ OmniAuth.config.mock_auth[:test] = {}
652
+
653
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'foo=bar'))
654
+ expect(strategy.env['rack.session']['omniauth.params']).to eq('foo' => 'bar')
655
+ end
656
+
657
+ it 'executes request hook on the request phase' do
658
+ OmniAuth.config.mock_auth[:test] = {}
659
+ OmniAuth.config.before_request_phase do |env|
660
+ env['foobar'] = 'baz'
661
+ end
662
+ strategy.call(make_env('/auth/test', 'QUERY_STRING' => 'foo=bar'))
663
+ expect(strategy.env['foobar']).to eq('baz')
664
+ end
665
+
666
+ it 'turns omniauth.params into an env variable on the callback phase' do
667
+ OmniAuth.config.mock_auth[:test] = {}
668
+
669
+ strategy.call(make_env('/auth/test/callback', 'rack.session' => {'omniauth.params' => {'foo' => 'bar'}}))
670
+ expect(strategy.env['omniauth.params']).to eq('foo' => 'bar')
671
+ end
672
+
673
+ after do
674
+ OmniAuth.config.test_mode = false
675
+ end
676
+ end
677
+
678
+ context 'custom full_host' do
679
+ before do
680
+ OmniAuth.config.test_mode = true
681
+ end
682
+
683
+ it 'is the string when a string is there' do
684
+ OmniAuth.config.full_host = 'my.host.com'
685
+ expect(strategy.full_host).to eq('my.host.com')
686
+ end
687
+
688
+ it 'runs the proc with the env when it is a proc' do
689
+ OmniAuth.config.full_host = proc { |env| env['HOST'] }
690
+ strategy.call(make_env('/auth/test', 'HOST' => 'my.host.net'))
691
+ expect(strategy.full_host).to eq('my.host.net')
692
+ end
693
+
694
+ it "is based on the request if it's not a string nor a proc" do
695
+ OmniAuth.config.full_host = nil
696
+ strategy.call(make_env('/whatever', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'my.host.net', 'SERVER_PORT' => 80))
697
+ expect(strategy.full_host).to eq('http://my.host.net')
698
+ end
699
+
700
+ it 'honors HTTP_X_FORWARDED_PROTO if present' do
701
+ OmniAuth.config.full_host = nil
702
+ strategy.call(make_env('/whatever', 'HTTP_X_FORWARDED_PROTO' => 'https', 'rack.url_scheme' => 'http', 'SERVER_NAME' => 'my.host.net', 'SERVER_PORT' => 443))
703
+ expect(strategy.full_host).to eq('https://my.host.net')
704
+ end
705
+
706
+ after do
707
+ OmniAuth.config.full_host = nil
708
+ OmniAuth.config.test_mode = false
709
+ end
710
+ end
711
+ end
712
+
713
+ context 'setup phase' do
714
+ before do
715
+ OmniAuth.config.test_mode = true
716
+ end
717
+
718
+ context 'when options[:setup] = true' do
719
+ let(:strategy) do
720
+ ExampleStrategy.new(app, :setup => true)
721
+ end
722
+
723
+ let(:app) do
724
+ lambda do |env|
725
+ env['omniauth.strategy'].options[:awesome] = 'sauce' if env['PATH_INFO'] == '/auth/test/setup'
726
+ [404, {}, 'Awesome']
727
+ end
728
+ end
729
+
730
+ it 'calls through to /auth/:provider/setup' do
731
+ strategy.call(make_env('/auth/test'))
732
+ expect(strategy.options[:awesome]).to eq('sauce')
733
+ end
734
+
735
+ it 'does not call through on a non-omniauth endpoint' do
736
+ strategy.call(make_env('/somewhere/else'))
737
+ expect(strategy.options[:awesome]).not_to eq('sauce')
738
+ end
739
+ end
740
+
741
+ context 'when options[:setup] is an app' do
742
+ let(:setup_proc) do
743
+ proc do |env|
744
+ env['omniauth.strategy'].options[:awesome] = 'sauce'
745
+ end
746
+ end
747
+
748
+ let(:strategy) { ExampleStrategy.new(app, :setup => setup_proc) }
749
+
750
+ it 'does not call the app on a non-omniauth endpoint' do
751
+ strategy.call(make_env('/somehwere/else'))
752
+ expect(strategy.options[:awesome]).not_to eq('sauce')
753
+ end
754
+
755
+ it 'calls the rack app' do
756
+ strategy.call(make_env('/auth/test'))
757
+ expect(strategy.options[:awesome]).to eq('sauce')
758
+ end
759
+ end
760
+
761
+ after do
762
+ OmniAuth.config.test_mode = false
763
+ end
764
+ end
765
+ end