rockoauth 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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,361 @@
1
+ require 'spec_helper'
2
+
3
+ describe RockOAuth::Provider::Exchange do
4
+ before do
5
+ @client = Factory(:client)
6
+ @alice = TestApp::User['Alice']
7
+ @bob = TestApp::User['Bob']
8
+ @authorization = create_authorization(:client => @client, :owner => @bob, :code => 'a_fake_code', :scope => 'foo bar')
9
+ allow(RockOAuth).to receive(:random_string).and_return('random_string')
10
+ end
11
+
12
+ let(:exchange) { RockOAuth::Provider::Exchange.new(@bob, params) }
13
+
14
+ shared_examples_for "validates required parameters" do
15
+ describe "missing grant_type" do
16
+ before { params.delete('client_id') }
17
+
18
+ it "is invalid" do
19
+ expect(exchange.error).to eq("invalid_request")
20
+ expect(exchange.error_description).to eq("Missing required parameter client_id")
21
+ end
22
+ end
23
+
24
+ describe "with an unknown grant type" do
25
+ before { params['grant_type'] = 'unknown' }
26
+
27
+ it "is invalid" do
28
+ expect(exchange.error).to eq("unsupported_grant_type")
29
+ expect(exchange.error_description).to eq("The grant type unknown is not recognized")
30
+ end
31
+ end
32
+
33
+ describe "missing client_id" do
34
+ before { params.delete('client_id') }
35
+
36
+ it "is invalid" do
37
+ expect(exchange.error).to eq("invalid_request")
38
+ expect(exchange.error_description).to eq("Missing required parameter client_id")
39
+ end
40
+ end
41
+
42
+ describe "with an unknown client_id" do
43
+ before { params['client_id'] = "unknown" }
44
+
45
+ it "is invalid" do
46
+ expect(exchange.error).to eq("invalid_client")
47
+ expect(exchange.error_description).to eq("Unknown client ID unknown")
48
+ end
49
+ end
50
+
51
+ describe "missing client_secret" do
52
+ before { params.delete('client_secret') }
53
+
54
+ it "is invalid" do
55
+ expect(exchange.error).to eq("invalid_request")
56
+ expect(exchange.error_description).to eq("Missing required parameter client_secret")
57
+ end
58
+ end
59
+
60
+ describe "with a mismatched client_secret" do
61
+ before { params['client_secret'] = "nosoupforyou" }
62
+
63
+ it "is invalid" do
64
+ expect(exchange.error).to eq("invalid_client")
65
+ expect(exchange.error_description).to eq("Parameter client_secret does not match")
66
+ end
67
+ end
68
+
69
+ describe "with lesser scope than the authorization code represents" do
70
+ before { params['scope'] = 'bar' }
71
+
72
+ it "is valid" do
73
+ expect(exchange.error).to be_nil
74
+ end
75
+ end
76
+
77
+ describe "with scopes not covered by the authorization code" do
78
+ before { params['scope'] = 'qux' }
79
+
80
+ it "is invalid" do
81
+ expect(exchange.error).to eq('invalid_scope')
82
+ expect(exchange.error_description).to eq('The request scope was never granted by the user')
83
+ end
84
+ end
85
+ end
86
+
87
+ shared_examples_for "valid token request" do
88
+ before do
89
+ allow(RockOAuth).to receive(:random_string).and_return('random_access_token')
90
+ end
91
+
92
+ it "is valid" do
93
+ expect(exchange.error).to be_nil
94
+ end
95
+
96
+ it "updates the Authorization with tokens" do
97
+ exchange.update_authorization
98
+ authorization.reload
99
+ expect(authorization.code).to be_nil
100
+ expect(authorization.access_token_hash).to eq(RockOAuth.hashify('random_access_token'))
101
+ expect(authorization.refresh_token).to be_nil
102
+ end
103
+ end
104
+
105
+ describe "using authorization_code grant type" do
106
+ let(:params) { { 'client_id' => @client.client_id,
107
+ 'client_secret' => @client.client_secret,
108
+ 'grant_type' => 'authorization_code',
109
+ 'code' => @authorization.code,
110
+ 'redirect_uri' => @client.redirect_uri }
111
+ }
112
+
113
+ let(:authorization) { @authorization }
114
+
115
+ it_should_behave_like "validates required parameters"
116
+ it_should_behave_like "valid token request"
117
+
118
+ describe "missing redirect_uri" do
119
+ before { params.delete('redirect_uri') }
120
+
121
+ it "is invalid" do
122
+ expect(exchange.error).to eq("invalid_request")
123
+ expect(exchange.error_description).to eq("Missing required parameter redirect_uri")
124
+ end
125
+ end
126
+
127
+ describe "with a mismatched redirect_uri" do
128
+ before { params['redirect_uri'] = "http://songkick.com" }
129
+
130
+ it "is invalid" do
131
+ expect(exchange.error).to eq("redirect_uri_mismatch")
132
+ expect(exchange.error_description).to eq("Parameter redirect_uri does not match registered URI")
133
+ end
134
+
135
+ describe "when the client has not registered a redirect_uri" do
136
+ before { @client.update_attribute(:redirect_uri, nil) }
137
+
138
+ it "is valid" do
139
+ expect(exchange.error).to be_nil
140
+ end
141
+ end
142
+ end
143
+
144
+ describe "missing code" do
145
+ before { params.delete('code') }
146
+
147
+ it "is invalid" do
148
+ expect(exchange.error).to eq("invalid_request")
149
+ expect(exchange.error_description).to eq("Missing required parameter code")
150
+ end
151
+ end
152
+
153
+ describe "with an unknown code" do
154
+ before { params['code'] = "unknown" }
155
+
156
+ it "is invalid" do
157
+ expect(exchange.error).to eq("invalid_grant")
158
+ expect(exchange.error_description).to eq("The access grant you supplied is invalid")
159
+ end
160
+ end
161
+
162
+ describe "with an expired code" do
163
+ before { @authorization.update_attribute(:expires_at, 1.day.ago) }
164
+
165
+ it "is invalid" do
166
+ expect(exchange.error).to eq("invalid_grant")
167
+ expect(exchange.error_description).to eq("The access grant you supplied is invalid")
168
+ end
169
+ end
170
+ end
171
+
172
+ describe "using password grant type" do
173
+ let(:params) { { 'client_id' => @client.client_id,
174
+ 'client_secret' => @client.client_secret,
175
+ 'grant_type' => 'password',
176
+ 'password' => 'soldier' }
177
+ }
178
+
179
+ before do
180
+ RockOAuth::Provider.handle_passwords do |client, username, password, scopes|
181
+ user = TestApp::User[username]
182
+ if password == 'soldier'
183
+ user.grant_access!(client, :scopes => scopes.reject { |s| s == 'qux' })
184
+ else
185
+ nil
186
+ end
187
+ end
188
+ end
189
+
190
+ describe "for a user with existing authorization" do
191
+ let(:authorization) { @authorization }
192
+ before { params['username'] = 'Bob' }
193
+
194
+ it_should_behave_like "validates required parameters"
195
+ it_should_behave_like "valid token request"
196
+
197
+ describe "missing username" do
198
+ before { params.delete('username') }
199
+
200
+ it "is invalid" do
201
+ expect(exchange.error).to eq('invalid_request')
202
+ expect(exchange.error_description).to eq('Missing required parameter username')
203
+ end
204
+ end
205
+
206
+ describe "missing password" do
207
+ before { params.delete('password') }
208
+
209
+ it "is invalid" do
210
+ expect(exchange.error).to eq('invalid_request')
211
+ expect(exchange.error_description).to eq('Missing required parameter password')
212
+ end
213
+ end
214
+
215
+ describe "with a bad password" do
216
+ before { params['password'] = 'bad' }
217
+
218
+ it "is invalid" do
219
+ expect(exchange.error).to eq('invalid_grant')
220
+ expect(exchange.error_description).to eq('The access grant you supplied is invalid')
221
+ end
222
+ end
223
+ end
224
+
225
+ describe "for a user with no existing authorization" do
226
+ let(:authorization) { RockOAuth::Model::Authorization.find_by_oauth2_resource_owner_id(@alice.id) }
227
+ before { params['username'] = 'Alice' }
228
+
229
+ it_should_behave_like "validates required parameters"
230
+ it_should_behave_like "valid token request"
231
+
232
+ describe "with ungranted but permissible scopes" do
233
+ before { params['scope'] = 'lol' }
234
+ it_should_behave_like "validates required parameters"
235
+ it_should_behave_like "valid token request"
236
+
237
+ it "sets the scope from the request" do
238
+ exchange.update_authorization
239
+ authorization.reload
240
+ expect(authorization.scopes).to eq(Set.new(['lol']))
241
+ end
242
+ end
243
+ end
244
+ end
245
+
246
+ describe "using assertion grant type" do
247
+ let(:params) { { 'client_id' => @client.client_id,
248
+ 'client_secret' => @client.client_secret,
249
+ 'grant_type' => 'assertion',
250
+ 'assertion_type' => 'https://graph.facebook.com/me',
251
+ 'assertion' => 'Bob' }
252
+ }
253
+
254
+ let(:authorization) { @authorization }
255
+
256
+ before do
257
+ RockOAuth::Provider.filter_assertions { |client| @client == client }
258
+
259
+ RockOAuth::Provider.handle_assertions('https://graph.facebook.com/me') do |client, assertion|
260
+ user = TestApp::User[assertion]
261
+ user.grant_access!(client, :scopes => ['foo', 'bar'])
262
+ end
263
+ end
264
+
265
+ after do
266
+ RockOAuth::Provider.clear_assertion_handlers!
267
+ end
268
+
269
+ it_should_behave_like "validates required parameters"
270
+ it_should_behave_like "valid token request"
271
+
272
+ it "provides the resource_owner to the assertion handler" do
273
+ RockOAuth::Provider.handle_assertions('https://graph.facebook.com/me') do |client, assertion, scopes, resource_owner|
274
+ expect(resource_owner).to be_a TestApp::User
275
+ user = TestApp::User[assertion]
276
+ user.grant_access!(client, :scopes => ['foo', 'bar'])
277
+ end
278
+ exchange
279
+ end
280
+
281
+ describe "missing assertion_type" do
282
+ before { params.delete('assertion_type') }
283
+
284
+ it "is invalid" do
285
+ expect(exchange.error).to eq('invalid_request')
286
+ expect(exchange.error_description).to eq('Missing required parameter assertion_type')
287
+ end
288
+ end
289
+
290
+ describe "with a non-URI assertion_type" do
291
+ before { params['assertion_type'] = 'invalid' }
292
+
293
+ it "is invalid" do
294
+ expect(exchange.error).to eq('invalid_request')
295
+ expect(exchange.error_description).to eq('Parameter assertion_type must be an absolute URI')
296
+ end
297
+ end
298
+
299
+ describe "missing assertion" do
300
+ before { params.delete('assertion') }
301
+
302
+ it "is invalid" do
303
+ expect(exchange.error).to eq('invalid_request')
304
+ expect(exchange.error_description).to eq('Missing required parameter assertion')
305
+ end
306
+ end
307
+
308
+ describe "with an unrecognized assertion_type" do
309
+ before { params['assertion_type'] = 'https://oauth.what.com/ohai' }
310
+
311
+ it "is invalid" do
312
+ expect(exchange.error).to eq('unauthorized_client')
313
+ expect(exchange.error_description).to eq('Client cannot use the given assertion type')
314
+ end
315
+ end
316
+
317
+ describe "with a client unauthorized to use the assertion scheme" do
318
+ before do
319
+ client = Factory(:client)
320
+ params['client_id'] = client.client_id
321
+ params['client_secret'] = client.client_secret
322
+ end
323
+
324
+ it "is invalid" do
325
+ expect(exchange.error).to eq('unauthorized_client')
326
+ expect(exchange.error_description).to eq('Client cannot use the given assertion type')
327
+ end
328
+ end
329
+ end
330
+
331
+ describe "using refresh_token grant type" do
332
+ before do
333
+ @refresher = create_authorization(:client => @client,
334
+ :owner => @alice,
335
+ :scope => 'foo bar',
336
+ :code => nil,
337
+ :refresh_token => 'roflscale')
338
+ end
339
+
340
+ let(:params) { { 'client_id' => @client.client_id,
341
+ 'client_secret' => @client.client_secret,
342
+ 'grant_type' => 'refresh_token',
343
+ 'refresh_token' => 'roflscale' }
344
+ }
345
+
346
+ let(:authorization) { @refresher }
347
+
348
+ it_should_behave_like "validates required parameters"
349
+ it_should_behave_like "valid token request"
350
+
351
+ describe "with unknown refresh_token" do
352
+ before { params['refresh_token'] = 'woops' }
353
+
354
+ it "is invalid" do
355
+ expect(exchange.error).to eq("invalid_grant")
356
+ expect(exchange.error_description).to eq("The access grant you supplied is invalid")
357
+ end
358
+ end
359
+
360
+ end
361
+ end