rockoauth 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. checksums.yaml +7 -0
  2. data/History.txt +5 -0
  3. data/README.rdoc +422 -0
  4. data/example/README.rdoc +11 -0
  5. data/example/application.rb +158 -0
  6. data/example/config.ru +3 -0
  7. data/example/environment.rb +11 -0
  8. data/example/models/connection.rb +9 -0
  9. data/example/models/note.rb +4 -0
  10. data/example/models/user.rb +5 -0
  11. data/example/public/style.css +78 -0
  12. data/example/schema.rb +22 -0
  13. data/example/views/authorize.erb +28 -0
  14. data/example/views/create_user.erb +3 -0
  15. data/example/views/error.erb +6 -0
  16. data/example/views/home.erb +24 -0
  17. data/example/views/layout.erb +24 -0
  18. data/example/views/login.erb +20 -0
  19. data/example/views/new_client.erb +25 -0
  20. data/example/views/new_user.erb +22 -0
  21. data/example/views/show_client.erb +15 -0
  22. data/lib/rockoauth/model/authorization.rb +132 -0
  23. data/lib/rockoauth/model/client.rb +54 -0
  24. data/lib/rockoauth/model/client_owner.rb +13 -0
  25. data/lib/rockoauth/model/hashing.rb +26 -0
  26. data/lib/rockoauth/model/helpers.rb +14 -0
  27. data/lib/rockoauth/model/resource_owner.rb +22 -0
  28. data/lib/rockoauth/model.rb +38 -0
  29. data/lib/rockoauth/provider/access_token.rb +70 -0
  30. data/lib/rockoauth/provider/authorization.rb +185 -0
  31. data/lib/rockoauth/provider/error.rb +19 -0
  32. data/lib/rockoauth/provider/exchange.rb +225 -0
  33. data/lib/rockoauth/provider.rb +133 -0
  34. data/lib/rockoauth/router.rb +75 -0
  35. data/lib/rockoauth/schema/20120828112156_rockoauth_schema_original_schema.rb +35 -0
  36. data/lib/rockoauth/schema/20121024180930_rockoauth_schema_add_authorization_index.rb +13 -0
  37. data/lib/rockoauth/schema/20121025180447_rockoauth_schema_add_unique_indexes.rb +31 -0
  38. data/lib/rockoauth/schema.rb +25 -0
  39. data/lib/rockoauth.rb +1 -0
  40. data/spec/factories.rb +20 -0
  41. data/spec/request_helpers.rb +62 -0
  42. data/spec/rockoauth/model/authorization_spec.rb +237 -0
  43. data/spec/rockoauth/model/client_spec.rb +44 -0
  44. data/spec/rockoauth/model/helpers_spec.rb +25 -0
  45. data/spec/rockoauth/model/resource_owner_spec.rb +87 -0
  46. data/spec/rockoauth/provider/access_token_spec.rb +138 -0
  47. data/spec/rockoauth/provider/authorization_spec.rb +356 -0
  48. data/spec/rockoauth/provider/exchange_spec.rb +361 -0
  49. data/spec/rockoauth/provider_spec.rb +560 -0
  50. data/spec/spec_helper.rb +80 -0
  51. data/spec/test_app/helper.rb +36 -0
  52. data/spec/test_app/provider/application.rb +67 -0
  53. data/spec/test_app/provider/views/authorize.erb +19 -0
  54. metadata +238 -0
@@ -0,0 +1,560 @@
1
+ require 'spec_helper'
2
+
3
+ describe RockOAuth::Provider do
4
+ include RequestHelpers
5
+
6
+ before(:all) { TestApp::Provider.start(RequestHelpers::SERVER_PORT) }
7
+ after(:all) { TestApp::Provider.stop }
8
+
9
+ let(:params) { { 'response_type' => 'code',
10
+ 'client_id' => @client.client_id,
11
+ 'redirect_uri' => @client.redirect_uri }
12
+ }
13
+
14
+ before do
15
+ @client = Factory(:client, :name => 'Test client')
16
+ @owner = TestApp::User['Bob']
17
+ end
18
+
19
+ describe "access grant request" do
20
+ shared_examples_for "asks for user permission" do
21
+ it "creates an authorization" do
22
+ auth = mock_request(RockOAuth::Provider::Authorization, :client => @client, :params => {}, :scopes => [], :valid? => true)
23
+ expect(RockOAuth::Provider::Authorization).to receive(:new).with(@owner, params, nil).and_return(auth)
24
+ get(params)
25
+ end
26
+
27
+ it "displays an authorization page" do
28
+ response = get(params)
29
+ expect(response.code.to_i).to eq(200)
30
+ expect(response.body).to match(/Do you want to allow Test client/)
31
+ expect(response['Content-Type']).to match(/text\/html/)
32
+ end
33
+ end
34
+
35
+ describe "with valid parameters" do
36
+ it_should_behave_like "asks for user permission"
37
+ end
38
+
39
+ describe "for token requests" do
40
+ before { params['response_type'] = 'token' }
41
+ it_should_behave_like "asks for user permission"
42
+ end
43
+
44
+ describe "for code_and_token requests" do
45
+ before { params['response_type'] = 'code_and_token' }
46
+ it_should_behave_like "asks for user permission"
47
+ end
48
+
49
+ describe "enforcing SSL" do
50
+ before { RockOAuth::Provider.enforce_ssl = true }
51
+
52
+ it "does not allow non-SSL requests" do
53
+ response = get(params)
54
+ validate_response(response, 400, 'WAT')
55
+ end
56
+ end
57
+
58
+ describe "when there is already a pending authorization from the user" do
59
+ before do
60
+ @authorization = create_authorization(
61
+ :owner => @owner,
62
+ :client => @client,
63
+ :code => 'pending_code',
64
+ :scope => 'offline_access')
65
+ end
66
+
67
+ it "immediately redirects with the code" do
68
+ response = get(params)
69
+ expect(response.code.to_i).to eq(302)
70
+ expect(response['location']).to eq('https://client.example.com/cb?code=pending_code')
71
+ end
72
+
73
+ describe "when the client is requesting scopes it already has access to" do
74
+ before { params['scope'] = 'offline_access' }
75
+
76
+ it "immediately redirects with the code" do
77
+ response = get(params)
78
+ expect(response.code.to_i).to eq(302)
79
+ expect(response['location']).to eq('https://client.example.com/cb?code=pending_code&scope=offline_access')
80
+ end
81
+ end
82
+
83
+ describe "when the client is requesting scopes it doesn't have yet" do
84
+ before { params['scope'] = 'wall_publish' }
85
+ it_should_behave_like "asks for user permission"
86
+ end
87
+
88
+ describe "and the authorization does not have a code" do
89
+ before { @authorization.update_attribute(:code, nil) }
90
+
91
+ it "generates a new code and redirects" do
92
+ expect(RockOAuth::Model::Authorization).not_to receive(:create)
93
+ expect(RockOAuth::Model::Authorization).not_to receive(:new)
94
+ expect(RockOAuth).to receive(:random_string).and_return('new_code')
95
+ response = get(params)
96
+ expect(response.code.to_i).to eq(302)
97
+ expect(response['location']).to eq('https://client.example.com/cb?code=new_code')
98
+ end
99
+ end
100
+
101
+ describe "and the authorization is expired" do
102
+ before { @authorization.update_attribute(:expires_at, 2.hours.ago) }
103
+ it_should_behave_like "asks for user permission"
104
+ end
105
+ end
106
+
107
+ describe "when there is already a completed authorization from the user" do
108
+ before do
109
+ @authorization = create_authorization(
110
+ :owner => @owner,
111
+ :client => @client,
112
+ :code => nil,
113
+ :access_token => RockOAuth.hashify('complete_token'))
114
+ end
115
+
116
+ it "immediately redirects with a new code" do
117
+ expect(RockOAuth).to receive(:random_string).and_return('new_code')
118
+ response = get(params)
119
+ expect(response.code.to_i).to eq(302)
120
+ expect(response['location']).to eq('https://client.example.com/cb?code=new_code')
121
+ end
122
+
123
+ describe "for token requests" do
124
+ before { params['response_type'] = 'token' }
125
+
126
+ it "immediately redirects with a new token" do
127
+ expect(RockOAuth).to receive(:random_string).and_return('new_access_token')
128
+ response = get(params)
129
+ expect(response.code.to_i).to eq(302)
130
+ expect(response['location']).to eq('https://client.example.com/cb#access_token=new_access_token')
131
+ end
132
+
133
+ describe "with an invalid client_id" do
134
+ before { params['client_id'] = 'unknown_id' }
135
+
136
+ it "does not generate any new tokens" do
137
+ expect(RockOAuth).not_to receive(:random_string)
138
+ get(params)
139
+ end
140
+ end
141
+ end
142
+
143
+ it "does not create a new Authorization" do
144
+ get(params)
145
+ expect(RockOAuth::Model::Authorization.count).to eq(1)
146
+ end
147
+
148
+ it "keeps the code and access token on the Authorization" do
149
+ get(params)
150
+ authorization = RockOAuth::Model::Authorization.first
151
+ expect(authorization.code).not_to be_nil
152
+ expect(authorization.access_token_hash).not_to be_nil
153
+ end
154
+ end
155
+
156
+ describe "with no parameters" do
157
+ let(:params) { {} }
158
+
159
+ it "renders an error page" do
160
+ response = get(params)
161
+ validate_response(response, 400, 'WAT')
162
+ end
163
+ end
164
+
165
+ describe "with a redirect_uri and no client_id" do
166
+ let(:params) { {'redirect_uri' => 'http://evilsite.com/callback'} }
167
+
168
+ it "renders an error page" do
169
+ response = get(params)
170
+ validate_response(response, 400, 'WAT')
171
+ end
172
+ end
173
+
174
+ describe "with a client_id and a bad redirect_uri" do
175
+ let(:params) { {'redirect_uri' => 'http://evilsite.com/callback',
176
+ 'client_id' => @client.client_id} }
177
+
178
+ it "redirects to the client's registered redirect_uri" do
179
+ response = get(params)
180
+ expect(response.code.to_i).to eq(302)
181
+ expect(response['location']).to eq('https://client.example.com/cb?error=invalid_request&error_description=Missing+required+parameter+response_type')
182
+ end
183
+ end
184
+
185
+ describe "with an invalid request" do
186
+ before { params.delete('response_type') }
187
+
188
+ it "redirects to the client's redirect_uri on error" do
189
+ response = get(params)
190
+ expect(response.code.to_i).to eq(302)
191
+ expect(response['location']).to eq('https://client.example.com/cb?error=invalid_request&error_description=Missing+required+parameter+response_type')
192
+ end
193
+
194
+ describe "with a state parameter" do
195
+ before { params['state'] = "Facebook\nmesses this\nup" }
196
+
197
+ it "redirects to the client, including the state param" do
198
+ response = get(params)
199
+ expect(response.code.to_i).to eq(302)
200
+ expect(response['location']).to eq("https://client.example.com/cb?error=invalid_request&error_description=Missing+required+parameter+response_type&state=Facebook%0Amesses+this%0Aup")
201
+ end
202
+ end
203
+ end
204
+ end
205
+
206
+ describe "authorization confirmation from the user" do
207
+ let(:mock_auth) do
208
+ mock = double RockOAuth::Provider::Authorization,
209
+ :redirect_uri => 'http://example.com/',
210
+ :response_status => 302
211
+
212
+ allow(RockOAuth::Provider::Authorization).to receive(:new).and_return(mock)
213
+ mock
214
+ end
215
+
216
+ describe "without the user's permission" do
217
+ before { params['allow'] = '' }
218
+
219
+ it "does not grant access" do
220
+ expect(mock_auth).to receive(:deny_access!)
221
+ allow_or_deny(params)
222
+ end
223
+
224
+ it "redirects to the client with an error" do
225
+ response = allow_or_deny(params)
226
+ expect(response.code.to_i).to eq(302)
227
+ expect(response['location']).to eq('https://client.example.com/cb?error=access_denied&error_description=The+user+denied+you+access')
228
+ end
229
+ end
230
+
231
+ describe "with valid parameters and user permission" do
232
+ before { allow(RockOAuth).to receive(:random_string).and_return('foo') }
233
+ before { params['allow'] = '1' }
234
+
235
+ describe "for code requests" do
236
+ it "grants access" do
237
+ expect(mock_auth).to receive(:grant_access!)
238
+ allow_or_deny(params)
239
+ end
240
+
241
+ it "redirects to the client with an authorization code" do
242
+ response = allow_or_deny(params)
243
+ expect(response.code.to_i).to eq(302)
244
+ expect(response['location']).to eq('https://client.example.com/cb?code=foo')
245
+ end
246
+
247
+ it "passes the state parameter through" do
248
+ params['state'] = 'illinois'
249
+ response = allow_or_deny(params)
250
+ expect(response.code.to_i).to eq(302)
251
+ expect(response['location']).to eq('https://client.example.com/cb?code=foo&state=illinois')
252
+ end
253
+
254
+ it "passes the scope parameter through" do
255
+ params['scope'] = 'foo bar'
256
+ response = allow_or_deny(params)
257
+ expect(response.code.to_i).to eq(302)
258
+ expect(response['location']).to eq('https://client.example.com/cb?code=foo&scope=foo+bar')
259
+ end
260
+ end
261
+
262
+ describe "for token requests" do
263
+ before { params['response_type'] = 'token' }
264
+
265
+ it "grants access" do
266
+ expect(mock_auth).to receive(:grant_access!)
267
+ allow_or_deny(params)
268
+ end
269
+
270
+ it "redirects to the client with an access token" do
271
+ response = allow_or_deny(params)
272
+ expect(response.code.to_i).to eq(302)
273
+ expect(response['location']).to eq('https://client.example.com/cb#access_token=foo&expires_in=10800')
274
+ end
275
+
276
+ it "passes the state parameter through" do
277
+ params['state'] = 'illinois'
278
+ response = allow_or_deny(params)
279
+ expect(response.code.to_i).to eq(302)
280
+ expect(response['location']).to eq('https://client.example.com/cb#access_token=foo&expires_in=10800&state=illinois')
281
+ end
282
+
283
+ it "passes the scope parameter through" do
284
+ params['scope'] = 'foo bar'
285
+ response = allow_or_deny(params)
286
+ expect(response.code.to_i).to eq(302)
287
+ expect(response['location']).to eq('https://client.example.com/cb#access_token=foo&expires_in=10800&scope=foo+bar')
288
+ end
289
+ end
290
+
291
+ describe "for code_and_token requests" do
292
+ before { params['response_type'] = 'code_and_token' }
293
+
294
+ it "grants access" do
295
+ expect(mock_auth).to receive(:grant_access!)
296
+ allow_or_deny(params)
297
+ end
298
+
299
+ it "redirects to the client with an access token" do
300
+ response = allow_or_deny(params)
301
+ expect(response.code.to_i).to eq(302)
302
+ expect(response['location']).to eq('https://client.example.com/cb?code=foo#access_token=foo&expires_in=10800')
303
+ end
304
+
305
+ it "passes the state parameter through" do
306
+ params['state'] = 'illinois'
307
+ response = allow_or_deny(params)
308
+ expect(response.code.to_i).to eq(302)
309
+ expect(response['location']).to eq('https://client.example.com/cb?code=foo&state=illinois#access_token=foo&expires_in=10800')
310
+ end
311
+
312
+ it "passes the scope parameter through" do
313
+ params['scope'] = 'foo bar'
314
+ response = allow_or_deny(params)
315
+ expect(response.code.to_i).to eq(302)
316
+ expect(response['location']).to eq('https://client.example.com/cb?code=foo#access_token=foo&expires_in=10800&scope=foo+bar')
317
+ end
318
+ end
319
+ end
320
+ end
321
+
322
+ describe "access token request" do
323
+ before do
324
+ @client = Factory(:client)
325
+ @authorization = create_authorization(
326
+ :owner => @owner,
327
+ :client => @client,
328
+ :code => 'a_fake_code',
329
+ :expires_at => 3.hours.from_now)
330
+ end
331
+
332
+ let(:auth_params) { { 'client_id' => @client.client_id,
333
+ 'client_secret' => @client.client_secret }
334
+ }
335
+
336
+ describe "using authorization_code request" do
337
+ let(:query_params) { { 'client_id' => @client.client_id,
338
+ 'grant_type' => 'authorization_code',
339
+ 'code' => @authorization.code,
340
+ 'redirect_uri' => @client.redirect_uri }
341
+ }
342
+
343
+ let(:params) { auth_params.merge(query_params) }
344
+
345
+ describe "with valid parameters" do
346
+ it "does not respond to GET" do
347
+ expect(RockOAuth::Provider::Authorization).not_to receive(:new)
348
+ params.delete('client_secret')
349
+ response = get(params)
350
+ validate_json_response(response, 400,
351
+ 'error' => 'invalid_request',
352
+ 'error_description' => 'Bad request: must be a POST request'
353
+ )
354
+ end
355
+
356
+ it "does not allow client credentials to be passed in the query string" do
357
+ expect(RockOAuth::Provider::Authorization).not_to receive(:new)
358
+ query_string = {'client_id' => params.delete('client_id'), 'client_secret' => params.delete('client_secret')}
359
+ response = post(params, query_string)
360
+ validate_json_response(response, 400,
361
+ 'error' => 'invalid_request',
362
+ 'error_description' => 'Bad request: must not send client credentials in the URI'
363
+ )
364
+ end
365
+
366
+ describe "enforcing SSL" do
367
+ before { RockOAuth::Provider.enforce_ssl = true }
368
+
369
+ it "does not allow non-SSL requests" do
370
+ response = get(params)
371
+ validate_json_response(response, 400,
372
+ 'error' => 'invalid_request',
373
+ 'error_description' => 'Bad request: must make requests using HTTPS'
374
+ )
375
+ end
376
+ end
377
+
378
+ it "creates a Token when using Basic Auth" do
379
+ token = mock_request(RockOAuth::Provider::Exchange, :response_body => 'Hello')
380
+ expect(RockOAuth::Provider::Exchange).to receive(:new).with(@owner, params, nil).and_return(token)
381
+ post_basic_auth(auth_params, query_params)
382
+ end
383
+
384
+ it "creates a Token when passing params in the POST body" do
385
+ token = mock_request(RockOAuth::Provider::Exchange, :response_body => 'Hello')
386
+ expect(RockOAuth::Provider::Exchange).to receive(:new).with(@owner, params, nil).and_return(token)
387
+ post(params)
388
+ end
389
+
390
+ it "returns a successful response" do
391
+ allow(RockOAuth).to receive(:random_string).and_return('random_access_token')
392
+ response = post_basic_auth(auth_params, query_params)
393
+ validate_json_response(response, 200, 'access_token' => 'random_access_token', 'expires_in' => 10800)
394
+ end
395
+
396
+ describe "with a scope parameter" do
397
+ before do
398
+ @authorization.update_attribute(:scope, 'foo bar')
399
+ end
400
+
401
+ it "passes the scope back in the success response" do
402
+ allow(RockOAuth).to receive(:random_string).and_return('random_access_token')
403
+ response = post_basic_auth(auth_params, query_params)
404
+ validate_json_response(response, 200,
405
+ 'access_token' => 'random_access_token',
406
+ 'scope' => 'foo bar',
407
+ 'expires_in' => 10800
408
+ )
409
+ end
410
+ end
411
+ end
412
+
413
+ describe "with invalid parameters" do
414
+ before { query_params.delete('code') }
415
+
416
+ it "returns an error response" do
417
+ response = post_basic_auth(auth_params, query_params)
418
+ validate_json_response(response, 400,
419
+ 'error' => 'invalid_request',
420
+ 'error_description' => 'Missing required parameter code'
421
+ )
422
+ end
423
+ end
424
+
425
+ describe "with mismatched client_id in POST params and Basic Auth params" do
426
+ before { query_params['client_id'] = 'foo' }
427
+
428
+ it "returns an error response" do
429
+ response = post_basic_auth(auth_params, query_params)
430
+ validate_json_response(response, 400,
431
+ 'error' => 'invalid_request',
432
+ 'error_description' => 'Bad request: client_id from Basic Auth and request body do not match'
433
+ )
434
+ end
435
+ end
436
+
437
+ describe "when there is an Authorization with code and token" do
438
+ before do
439
+ @authorization.update_attributes(:code => 'pending_code', :access_token => 'working_token')
440
+ allow(RockOAuth).to receive(:random_string).and_return('random_access_token')
441
+ end
442
+
443
+ it "returns a new access token" do
444
+ response = post(params)
445
+ validate_json_response(response, 200,
446
+ 'access_token' => 'random_access_token',
447
+ 'expires_in' => 10800
448
+ )
449
+ end
450
+
451
+ it "exchanges the code for the new token on the existing Authorization" do
452
+ post(params)
453
+ @authorization.reload
454
+ expect(@authorization.code).to be_nil
455
+ expect(@authorization.access_token_hash).to eq(RockOAuth.hashify('random_access_token'))
456
+ end
457
+ end
458
+ end
459
+ end
460
+
461
+ describe "protected resource request" do
462
+ before do
463
+ @authorization = create_authorization(
464
+ :owner => @owner,
465
+ :client => @client,
466
+ :access_token => 'magic-key',
467
+ :scope => 'profile')
468
+ end
469
+
470
+ shared_examples_for "protected resource" do
471
+ it "creates an AccessToken response" do
472
+ mock_token = double(RockOAuth::Provider::AccessToken)
473
+ expect(mock_token).to receive(:response_headers).and_return({})
474
+ expect(mock_token).to receive(:response_status).and_return(200)
475
+ expect(mock_token).to receive(:valid?).and_return(true)
476
+ expect(RockOAuth::Provider::AccessToken).to receive(:new).with(TestApp::User['Bob'], ['profile'], 'magic-key', nil).and_return(mock_token)
477
+ request('/user_profile', 'oauth_token' => 'magic-key')
478
+ end
479
+
480
+ it "allows access when the key is passed" do
481
+ response = request('/user_profile', 'oauth_token' => 'magic-key')
482
+ expect(JSON.parse(response.body)['data']).to eq('Top secret')
483
+ expect(response.code.to_i).to eq(200)
484
+ end
485
+
486
+ it "blocks access when the wrong key is passed" do
487
+ response = request('/user_profile', 'oauth_token' => 'is-the-password-books')
488
+ expect(JSON.parse(response.body)['data']).to eq('No soup for you')
489
+ expect(response.code.to_i).to eq(401)
490
+ expect(response['WWW-Authenticate']).to eq("OAuth realm='Demo App', error='invalid_token'")
491
+ end
492
+
493
+ it "blocks access when the no key is passed" do
494
+ response = request('/user_profile')
495
+ expect(JSON.parse(response.body)['data']).to eq('No soup for you')
496
+ expect(response.code.to_i).to eq(401)
497
+ expect(response['WWW-Authenticate']).to eq("OAuth realm='Demo App'")
498
+ end
499
+
500
+ describe "enforcing SSL" do
501
+ before { RockOAuth::Provider.enforce_ssl = true }
502
+
503
+ let(:authorization) do
504
+ RockOAuth::Model::Authorization.find_by_access_token_hash(RockOAuth.hashify('magic-key'))
505
+ end
506
+
507
+ it "blocks access when not using HTTPS" do
508
+ response = request('/user_profile', 'oauth_token' => 'magic-key')
509
+ expect(JSON.parse(response.body)['data']).to eq('No soup for you')
510
+ expect(response.code.to_i).to eq(401)
511
+ expect(response['WWW-Authenticate']).to eq("OAuth realm='Demo App', error='invalid_request'")
512
+ end
513
+
514
+ it "destroys the access token since it's been leaked" do
515
+ expect(authorization.access_token_hash).to eq(RockOAuth.hashify('magic-key'))
516
+ request('/user_profile', 'oauth_token' => 'magic-key')
517
+ authorization.reload
518
+ expect(authorization.access_token_hash).to be_nil
519
+ end
520
+
521
+ it "keeps the access token if the wrong key is passed" do
522
+ expect(authorization.access_token_hash).to eq(RockOAuth.hashify('magic-key'))
523
+ request('/user_profile', 'oauth_token' => 'is-the-password-books')
524
+ authorization.reload
525
+ expect(authorization.access_token_hash).to eq(RockOAuth.hashify('magic-key'))
526
+ end
527
+ end
528
+ end
529
+
530
+ describe "for header-based requests" do
531
+ def request(path, params = {})
532
+ access_token = params.delete('oauth_token')
533
+ http = Net::HTTP.new('localhost', RequestHelpers::SERVER_PORT)
534
+ qs = params.map { |k,v| "#{ CGI.escape k.to_s }=#{ CGI.escape v.to_s }" }.join('&')
535
+ header = {'Authorization' => "OAuth #{access_token}"}
536
+ http.request_get(path + '?' + qs, header)
537
+ end
538
+
539
+ it_should_behave_like "protected resource"
540
+ end
541
+
542
+ describe "for GET requests" do
543
+ def request(path, params = {})
544
+ qs = params.map { |k,v| "#{ CGI.escape k.to_s }=#{ CGI.escape v.to_s }" }.join('&')
545
+ uri = URI.parse("http://localhost:#{RequestHelpers::SERVER_PORT}" + path + '?' + qs)
546
+ Net::HTTP.get_response(uri)
547
+ end
548
+
549
+ it_should_behave_like "protected resource"
550
+ end
551
+
552
+ describe "for POST requests" do
553
+ def request(path, params = {})
554
+ Net::HTTP.post_form(URI.parse("http://localhost:#{RequestHelpers::SERVER_PORT}" + path), params)
555
+ end
556
+
557
+ it_should_behave_like "protected resource"
558
+ end
559
+ end
560
+ end
@@ -0,0 +1,80 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'active_record'
5
+
6
+ require 'rockoauth/provider'
7
+
8
+ case ENV['DB']
9
+ when 'mysql'
10
+ ActiveRecord::Base.establish_connection(
11
+ :adapter => 'mysql',
12
+ :host => '127.0.0.1',
13
+ :username => 'root',
14
+ :database => 'oauth2_test')
15
+ when 'postgres'
16
+ ActiveRecord::Base.establish_connection(
17
+ :adapter => 'postgresql',
18
+ :host => '127.0.0.1',
19
+ :username => 'postgres',
20
+ :database => 'oauth2_test')
21
+ else
22
+ dbfile = File.expand_path('../test.sqlite3', __FILE__)
23
+ File.unlink(dbfile) if File.file?(dbfile)
24
+
25
+ ActiveRecord::Base.establish_connection(
26
+ :adapter => 'sqlite3',
27
+ :database => dbfile)
28
+ end
29
+
30
+ require 'logger'
31
+ ActiveRecord::Base.logger = Logger.new(STDERR)
32
+ ActiveRecord::Base.logger.level = Logger::INFO
33
+
34
+ RockOAuth::Model::Schema.up
35
+
36
+ ActiveRecord::Schema.define do |version|
37
+ create_table :users, :force => true do |t|
38
+ t.string :name
39
+ end
40
+ end
41
+
42
+ require 'test_app/provider/application'
43
+ require 'request_helpers'
44
+ require 'factories'
45
+
46
+ require 'thin'
47
+ Thin::Logging.silent = true
48
+ $VERBOSE = nil
49
+
50
+ RSpec.configure do |config|
51
+ # to run only specific specs, add :focus to the spec
52
+ # describe "foo", :focus do
53
+ # OR
54
+ # it "should foo", :focus do
55
+
56
+ config.filter_run :focus => true
57
+ config.run_all_when_everything_filtered = true
58
+
59
+ config.before do
60
+ RockOAuth::Provider.enforce_ssl = false
61
+ time = Time.now
62
+ allow(Time).to receive(:now).and_return time
63
+ end
64
+
65
+ config.after do
66
+ [ RockOAuth::Model::Client,
67
+ RockOAuth::Model::Authorization,
68
+ TestApp::User
69
+
70
+ ].each { |k| k.delete_all }
71
+ end
72
+ end
73
+
74
+ def create_authorization(params)
75
+ RockOAuth::Model::Authorization.__send__(:create) do |authorization|
76
+ params.each do |key, value|
77
+ authorization.__send__ "#{key}=", value
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,36 @@
1
+ module TestApp
2
+
3
+ class User < ActiveRecord::Base
4
+ self.table_name = :users
5
+
6
+ include RockOAuth::Model::ResourceOwner
7
+ include RockOAuth::Model::ClientOwner
8
+
9
+ def self.[](name)
10
+ if respond_to?(:find_or_create_by)
11
+ find_or_create_by(:name => name)
12
+ else
13
+ find_or_create_by_name(name)
14
+ end
15
+ end
16
+ end
17
+
18
+ module Helper
19
+ module RackRunner
20
+ def start(port)
21
+ handler = Rack::Handler.get('thin')
22
+ Thread.new do
23
+ handler.run(new, :Port => port) { |server| @server = server }
24
+ end
25
+ sleep 0.1 until @server
26
+ end
27
+
28
+ def stop
29
+ @server.stop if @server
30
+ @server = nil
31
+ sleep 0.1 while EM.reactor_running?
32
+ end
33
+ end
34
+ end
35
+
36
+ end