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.
- checksums.yaml +7 -0
- data/History.txt +5 -0
- data/README.rdoc +422 -0
- data/example/README.rdoc +11 -0
- data/example/application.rb +158 -0
- data/example/config.ru +3 -0
- data/example/environment.rb +11 -0
- data/example/models/connection.rb +9 -0
- data/example/models/note.rb +4 -0
- data/example/models/user.rb +5 -0
- data/example/public/style.css +78 -0
- data/example/schema.rb +22 -0
- data/example/views/authorize.erb +28 -0
- data/example/views/create_user.erb +3 -0
- data/example/views/error.erb +6 -0
- data/example/views/home.erb +24 -0
- data/example/views/layout.erb +24 -0
- data/example/views/login.erb +20 -0
- data/example/views/new_client.erb +25 -0
- data/example/views/new_user.erb +22 -0
- data/example/views/show_client.erb +15 -0
- data/lib/rockoauth/model/authorization.rb +132 -0
- data/lib/rockoauth/model/client.rb +54 -0
- data/lib/rockoauth/model/client_owner.rb +13 -0
- data/lib/rockoauth/model/hashing.rb +26 -0
- data/lib/rockoauth/model/helpers.rb +14 -0
- data/lib/rockoauth/model/resource_owner.rb +22 -0
- data/lib/rockoauth/model.rb +38 -0
- data/lib/rockoauth/provider/access_token.rb +70 -0
- data/lib/rockoauth/provider/authorization.rb +185 -0
- data/lib/rockoauth/provider/error.rb +19 -0
- data/lib/rockoauth/provider/exchange.rb +225 -0
- data/lib/rockoauth/provider.rb +133 -0
- data/lib/rockoauth/router.rb +75 -0
- data/lib/rockoauth/schema/20120828112156_rockoauth_schema_original_schema.rb +35 -0
- data/lib/rockoauth/schema/20121024180930_rockoauth_schema_add_authorization_index.rb +13 -0
- data/lib/rockoauth/schema/20121025180447_rockoauth_schema_add_unique_indexes.rb +31 -0
- data/lib/rockoauth/schema.rb +25 -0
- data/lib/rockoauth.rb +1 -0
- data/spec/factories.rb +20 -0
- data/spec/request_helpers.rb +62 -0
- data/spec/rockoauth/model/authorization_spec.rb +237 -0
- data/spec/rockoauth/model/client_spec.rb +44 -0
- data/spec/rockoauth/model/helpers_spec.rb +25 -0
- data/spec/rockoauth/model/resource_owner_spec.rb +87 -0
- data/spec/rockoauth/provider/access_token_spec.rb +138 -0
- data/spec/rockoauth/provider/authorization_spec.rb +356 -0
- data/spec/rockoauth/provider/exchange_spec.rb +361 -0
- data/spec/rockoauth/provider_spec.rb +560 -0
- data/spec/spec_helper.rb +80 -0
- data/spec/test_app/helper.rb +36 -0
- data/spec/test_app/provider/application.rb +67 -0
- data/spec/test_app/provider/views/authorize.erb +19 -0
- 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
|