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,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