tpitale-rack-oauth2-server 2.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +202 -0
- data/Gemfile +16 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +604 -0
- data/Rakefile +90 -0
- data/VERSION +1 -0
- data/bin/oauth2-server +206 -0
- data/lib/rack-oauth2-server.rb +4 -0
- data/lib/rack/oauth2/admin/css/screen.css +347 -0
- data/lib/rack/oauth2/admin/images/loading.gif +0 -0
- data/lib/rack/oauth2/admin/images/oauth-2.png +0 -0
- data/lib/rack/oauth2/admin/js/application.coffee +220 -0
- data/lib/rack/oauth2/admin/js/jquery.js +166 -0
- data/lib/rack/oauth2/admin/js/jquery.tmpl.js +414 -0
- data/lib/rack/oauth2/admin/js/protovis-r3.2.js +277 -0
- data/lib/rack/oauth2/admin/js/sammy.js +5 -0
- data/lib/rack/oauth2/admin/js/sammy.json.js +5 -0
- data/lib/rack/oauth2/admin/js/sammy.oauth2.js +142 -0
- data/lib/rack/oauth2/admin/js/sammy.storage.js +5 -0
- data/lib/rack/oauth2/admin/js/sammy.title.js +5 -0
- data/lib/rack/oauth2/admin/js/sammy.tmpl.js +5 -0
- data/lib/rack/oauth2/admin/js/underscore.js +722 -0
- data/lib/rack/oauth2/admin/views/client.tmpl +58 -0
- data/lib/rack/oauth2/admin/views/clients.tmpl +52 -0
- data/lib/rack/oauth2/admin/views/edit.tmpl +80 -0
- data/lib/rack/oauth2/admin/views/index.html +39 -0
- data/lib/rack/oauth2/admin/views/no_access.tmpl +4 -0
- data/lib/rack/oauth2/models.rb +27 -0
- data/lib/rack/oauth2/models/access_grant.rb +54 -0
- data/lib/rack/oauth2/models/access_token.rb +129 -0
- data/lib/rack/oauth2/models/auth_request.rb +61 -0
- data/lib/rack/oauth2/models/client.rb +93 -0
- data/lib/rack/oauth2/rails.rb +105 -0
- data/lib/rack/oauth2/server.rb +458 -0
- data/lib/rack/oauth2/server/admin.rb +250 -0
- data/lib/rack/oauth2/server/errors.rb +104 -0
- data/lib/rack/oauth2/server/helper.rb +147 -0
- data/lib/rack/oauth2/server/practice.rb +79 -0
- data/lib/rack/oauth2/server/railtie.rb +24 -0
- data/lib/rack/oauth2/server/utils.rb +30 -0
- data/lib/rack/oauth2/sinatra.rb +71 -0
- data/rack-oauth2-server.gemspec +24 -0
- data/rails/init.rb +11 -0
- data/test/admin/api_test.rb +228 -0
- data/test/admin/ui_test.rb +38 -0
- data/test/oauth/access_grant_test.rb +276 -0
- data/test/oauth/access_token_test.rb +311 -0
- data/test/oauth/authorization_test.rb +298 -0
- data/test/oauth/server_methods_test.rb +292 -0
- data/test/rails2/app/controllers/api_controller.rb +40 -0
- data/test/rails2/app/controllers/application_controller.rb +2 -0
- data/test/rails2/app/controllers/oauth_controller.rb +17 -0
- data/test/rails2/config/environment.rb +19 -0
- data/test/rails2/config/environments/test.rb +0 -0
- data/test/rails2/config/routes.rb +13 -0
- data/test/rails3/app/controllers/api_controller.rb +40 -0
- data/test/rails3/app/controllers/application_controller.rb +2 -0
- data/test/rails3/app/controllers/oauth_controller.rb +17 -0
- data/test/rails3/config/application.rb +19 -0
- data/test/rails3/config/environment.rb +2 -0
- data/test/rails3/config/routes.rb +12 -0
- data/test/setup.rb +120 -0
- data/test/sinatra/my_app.rb +69 -0
- metadata +145 -0
@@ -0,0 +1,298 @@
|
|
1
|
+
require "test/setup"
|
2
|
+
|
3
|
+
|
4
|
+
# 3. Obtaining End-User Authorization
|
5
|
+
class AuthorizationTest < Test::Unit::TestCase
|
6
|
+
module Helpers
|
7
|
+
|
8
|
+
def should_redirect_with_error(error)
|
9
|
+
should "respond with status code 302 (Found)" do
|
10
|
+
assert_equal 302, last_response.status
|
11
|
+
end
|
12
|
+
should "redirect back to redirect_uri" do
|
13
|
+
assert_equal URI.parse(last_response["Location"]).host, "uberclient.dot"
|
14
|
+
end
|
15
|
+
should "redirect with error code #{error}" do
|
16
|
+
assert_equal error.to_s, Rack::Utils.parse_query(URI.parse(last_response["Location"]).query)["error"]
|
17
|
+
end
|
18
|
+
should "redirect with state parameter" do
|
19
|
+
assert_equal "bring this back", Rack::Utils.parse_query(URI.parse(last_response["Location"]).query)["state"]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def should_ask_user_for_authorization(&block)
|
24
|
+
should "inform user about client" do
|
25
|
+
response = last_response.body.split("\n").inject({}) { |h,l| n,v = l.split(/:\s*/) ; h[n.downcase] = v ; h }
|
26
|
+
assert_equal "UberClient", response["client"]
|
27
|
+
end
|
28
|
+
should "inform user about scope" do
|
29
|
+
response = last_response.body.split("\n").inject({}) { |h,l| n,v = l.split(/:\s*/) ; h[n.downcase] = v ; h }
|
30
|
+
assert_equal "read, write", response["scope"]
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
extend Helpers
|
36
|
+
|
37
|
+
def setup
|
38
|
+
super
|
39
|
+
@params = { :redirect_uri=>client.redirect_uri, :client_id=>client.id, :client_secret=>client.secret, :response_type=>"code",
|
40
|
+
:scope=>"read write", :state=>"bring this back" }
|
41
|
+
end
|
42
|
+
|
43
|
+
def request_authorization(changes = nil)
|
44
|
+
get "/oauth/authorize?" + Rack::Utils.build_query(@params.merge(changes || {}))
|
45
|
+
get last_response["Location"] if last_response.status == 303
|
46
|
+
end
|
47
|
+
|
48
|
+
def authorization
|
49
|
+
last_response.body[/authorization:\s*(\S+)/, 1]
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
# Checks before we request user for authorization.
|
54
|
+
# 3.2. Error Response
|
55
|
+
|
56
|
+
context "no redirect URI" do
|
57
|
+
setup { request_authorization :redirect_uri=>nil }
|
58
|
+
should "return status 400" do
|
59
|
+
assert_equal 400, last_response.status
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "invalid redirect URI" do
|
64
|
+
setup { request_authorization :redirect_uri=>"http:not-valid" }
|
65
|
+
should "return status 400" do
|
66
|
+
assert_equal 400, last_response.status
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "no client ID" do
|
71
|
+
setup { request_authorization :client_id=>nil }
|
72
|
+
should_redirect_with_error :invalid_client
|
73
|
+
end
|
74
|
+
|
75
|
+
context "invalid client ID" do
|
76
|
+
setup { request_authorization :client_id=>"foobar" }
|
77
|
+
should_redirect_with_error :invalid_client
|
78
|
+
end
|
79
|
+
|
80
|
+
context "client ID but no such client" do
|
81
|
+
setup { request_authorization :client_id=>"4cc7bc483321e814b8000000" }
|
82
|
+
should_redirect_with_error :invalid_client
|
83
|
+
end
|
84
|
+
|
85
|
+
context "mismatched redirect URI" do
|
86
|
+
setup { request_authorization :redirect_uri=>"http://uberclient.dot/oz" }
|
87
|
+
should_redirect_with_error :redirect_uri_mismatch
|
88
|
+
end
|
89
|
+
|
90
|
+
context "revoked client" do
|
91
|
+
setup do
|
92
|
+
client.revoke!
|
93
|
+
request_authorization
|
94
|
+
end
|
95
|
+
should_redirect_with_error :invalid_client
|
96
|
+
end
|
97
|
+
|
98
|
+
context "no response type" do
|
99
|
+
setup { request_authorization :response_type=>nil }
|
100
|
+
should_redirect_with_error :unsupported_response_type
|
101
|
+
end
|
102
|
+
|
103
|
+
context "unknown response type" do
|
104
|
+
setup { request_authorization :response_type=>"foobar" }
|
105
|
+
should_redirect_with_error :unsupported_response_type
|
106
|
+
end
|
107
|
+
|
108
|
+
context "unsupported scope" do
|
109
|
+
setup do
|
110
|
+
request_authorization :scope=>"read write math"
|
111
|
+
end
|
112
|
+
should_redirect_with_error :invalid_scope
|
113
|
+
end
|
114
|
+
|
115
|
+
|
116
|
+
# 3.1. Authorization Response
|
117
|
+
|
118
|
+
context "expecting authorization code" do
|
119
|
+
setup do
|
120
|
+
@params[:response_type] = "code"
|
121
|
+
request_authorization
|
122
|
+
end
|
123
|
+
should_ask_user_for_authorization
|
124
|
+
|
125
|
+
context "and granted" do
|
126
|
+
setup { post "/oauth/grant", :authorization=>authorization }
|
127
|
+
|
128
|
+
should "redirect" do
|
129
|
+
assert_equal 302, last_response.status
|
130
|
+
end
|
131
|
+
should "redirect back to client" do
|
132
|
+
uri = URI.parse(last_response["Location"])
|
133
|
+
assert_equal "uberclient.dot", uri.host
|
134
|
+
assert_equal "/callback", uri.path
|
135
|
+
end
|
136
|
+
|
137
|
+
context "redirect URL query parameters" do
|
138
|
+
setup { @return = Rack::Utils.parse_query(URI.parse(last_response["Location"]).query) }
|
139
|
+
|
140
|
+
should "include authorization code" do
|
141
|
+
assert_match /[a-f0-9]{32}/i, @return["code"]
|
142
|
+
end
|
143
|
+
|
144
|
+
should "include original scope" do
|
145
|
+
assert_equal "read write", @return["scope"]
|
146
|
+
end
|
147
|
+
|
148
|
+
should "include state from requet" do
|
149
|
+
assert_equal "bring this back", @return["state"]
|
150
|
+
end
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "and denied" do
|
155
|
+
setup { post "/oauth/deny", :authorization=>authorization }
|
156
|
+
|
157
|
+
should "redirect" do
|
158
|
+
assert_equal 302, last_response.status
|
159
|
+
end
|
160
|
+
should "redirect back to client" do
|
161
|
+
uri = URI.parse(last_response["Location"])
|
162
|
+
assert_equal "uberclient.dot", uri.host
|
163
|
+
assert_equal "/callback", uri.path
|
164
|
+
end
|
165
|
+
|
166
|
+
context "redirect URL" do
|
167
|
+
setup { @return = Rack::Utils.parse_query(URI.parse(last_response["Location"]).query) }
|
168
|
+
|
169
|
+
should "not include authorization code" do
|
170
|
+
assert !@return["code"]
|
171
|
+
end
|
172
|
+
|
173
|
+
should "include error code" do
|
174
|
+
assert_equal "access_denied", @return["error"]
|
175
|
+
end
|
176
|
+
|
177
|
+
should "include state from requet" do
|
178
|
+
assert_equal "bring this back", @return["state"]
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
|
184
|
+
|
185
|
+
context "expecting access token" do
|
186
|
+
setup do
|
187
|
+
@params[:response_type] = "token"
|
188
|
+
request_authorization
|
189
|
+
end
|
190
|
+
should_ask_user_for_authorization
|
191
|
+
|
192
|
+
context "and granted" do
|
193
|
+
setup { post "/oauth/grant", :authorization=>authorization }
|
194
|
+
|
195
|
+
should "redirect" do
|
196
|
+
assert_equal 302, last_response.status
|
197
|
+
end
|
198
|
+
should "redirect back to client" do
|
199
|
+
uri = URI.parse(last_response["Location"])
|
200
|
+
assert_equal "uberclient.dot", uri.host
|
201
|
+
assert_equal "/callback", uri.path
|
202
|
+
end
|
203
|
+
|
204
|
+
context "redirect URL fragment identifier" do
|
205
|
+
setup { @return = Rack::Utils.parse_query(URI.parse(last_response["Location"]).fragment) }
|
206
|
+
|
207
|
+
should "include access token" do
|
208
|
+
assert_match /[a-f0-9]{32}/i, @return["access_token"]
|
209
|
+
end
|
210
|
+
|
211
|
+
should "include original scope" do
|
212
|
+
assert_equal "read write", @return["scope"]
|
213
|
+
end
|
214
|
+
|
215
|
+
should "include state from requet" do
|
216
|
+
assert_equal "bring this back", @return["state"]
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
context "and denied" do
|
222
|
+
setup { post "/oauth/deny", :authorization=>authorization }
|
223
|
+
|
224
|
+
should "redirect" do
|
225
|
+
assert_equal 302, last_response.status
|
226
|
+
end
|
227
|
+
should "redirect back to client" do
|
228
|
+
uri = URI.parse(last_response["Location"])
|
229
|
+
assert_equal "uberclient.dot", uri.host
|
230
|
+
assert_equal "/callback", uri.path
|
231
|
+
end
|
232
|
+
|
233
|
+
context "redirect URL" do
|
234
|
+
setup { @return = Rack::Utils.parse_query(URI.parse(last_response["Location"]).fragment) }
|
235
|
+
|
236
|
+
should "not include authorization code" do
|
237
|
+
assert !@return["code"]
|
238
|
+
end
|
239
|
+
|
240
|
+
should "include error code" do
|
241
|
+
assert_equal "access_denied", @return["error"]
|
242
|
+
end
|
243
|
+
|
244
|
+
should "include state from requet" do
|
245
|
+
assert_equal "bring this back", @return["state"]
|
246
|
+
end
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
|
252
|
+
# Using existing authorization request
|
253
|
+
|
254
|
+
context "with authorization request" do
|
255
|
+
setup do
|
256
|
+
request_authorization
|
257
|
+
get "/oauth/authorize?" + Rack::Utils.build_query(:authorization=>authorization)
|
258
|
+
end
|
259
|
+
|
260
|
+
should_ask_user_for_authorization
|
261
|
+
end
|
262
|
+
|
263
|
+
context "with invalid authorization request" do
|
264
|
+
setup do
|
265
|
+
request_authorization
|
266
|
+
get "/oauth/authorize?" + Rack::Utils.build_query(:authorization=>"foobar")
|
267
|
+
end
|
268
|
+
|
269
|
+
should "return status 400" do
|
270
|
+
assert_equal 400, last_response.status
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
context "with revoked authorization request" do
|
275
|
+
setup do
|
276
|
+
request_authorization
|
277
|
+
response = last_response.body.split("\n").inject({}) { |h,l| n,v = l.split(/:\s*/) ; h[n.downcase] = v ; h }
|
278
|
+
client.revoke!
|
279
|
+
get "/oauth/authorize?" + Rack::Utils.build_query(:authorization=>response["authorization"])
|
280
|
+
end
|
281
|
+
|
282
|
+
should "return status 400" do
|
283
|
+
assert_equal 400, last_response.status
|
284
|
+
end
|
285
|
+
end
|
286
|
+
|
287
|
+
|
288
|
+
# Edge cases
|
289
|
+
|
290
|
+
context "unregistered redirect URI" do
|
291
|
+
setup do
|
292
|
+
Rack::OAuth2::Server::Client.collection.update({ :_id=>client._id }, { :$set=>{ :redirect_uri=>nil } })
|
293
|
+
request_authorization :redirect_uri=>"http://uberclient.dot/oz"
|
294
|
+
end
|
295
|
+
should_ask_user_for_authorization
|
296
|
+
end
|
297
|
+
|
298
|
+
end
|
@@ -0,0 +1,292 @@
|
|
1
|
+
require "test/setup"
|
2
|
+
|
3
|
+
|
4
|
+
# Tests the Server API
|
5
|
+
class ServerTest < Test::Unit::TestCase
|
6
|
+
def setup
|
7
|
+
super
|
8
|
+
end
|
9
|
+
|
10
|
+
context "get_auth_request" do
|
11
|
+
setup { @request = Server::AuthRequest.create(client, client.scope.join(" "), client.redirect_uri, "token", nil) }
|
12
|
+
should "return authorization request" do
|
13
|
+
assert_equal @request.id, Server.get_auth_request(@request.id).id
|
14
|
+
end
|
15
|
+
|
16
|
+
should "return nil if no request found" do
|
17
|
+
assert !Server.get_auth_request("4ce2488e3321e87ac1000004")
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
context "get_client" do
|
23
|
+
should "return authorization request" do
|
24
|
+
assert_equal client.display_name, Server.get_client(client.id).display_name
|
25
|
+
end
|
26
|
+
|
27
|
+
should "return nil if no client found" do
|
28
|
+
assert !Server.get_client("4ce2488e3321e87ac1000004")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
context "register" do
|
34
|
+
context "no client ID" do
|
35
|
+
setup do
|
36
|
+
@client = Server.register(:display_name=>"MyApp", :link=>"http://example.org", :image_url=>"http://example.org/favicon.ico",
|
37
|
+
:redirect_uri=>"http://example.org/oauth/callback", :scope=>%w{read write})
|
38
|
+
end
|
39
|
+
|
40
|
+
should "create new client" do
|
41
|
+
assert_equal 2, Server::Client.collection.count
|
42
|
+
assert_contains Server::Client.all.map(&:id), @client.id
|
43
|
+
end
|
44
|
+
|
45
|
+
should "set display name" do
|
46
|
+
assert_equal "MyApp", Server.get_client(@client.id).display_name
|
47
|
+
end
|
48
|
+
|
49
|
+
should "set link" do
|
50
|
+
assert_equal "http://example.org", Server.get_client(@client.id).link
|
51
|
+
end
|
52
|
+
|
53
|
+
should "set image URL" do
|
54
|
+
assert_equal "http://example.org/favicon.ico", Server.get_client(@client.id).image_url
|
55
|
+
end
|
56
|
+
|
57
|
+
should "set redirect URI" do
|
58
|
+
assert_equal "http://example.org/oauth/callback", Server.get_client(@client.id).redirect_uri
|
59
|
+
end
|
60
|
+
|
61
|
+
should "set scope" do
|
62
|
+
assert_equal %w{read write}, Server.get_client(@client.id).scope
|
63
|
+
end
|
64
|
+
|
65
|
+
should "assign client an ID" do
|
66
|
+
assert_match /[0-9a-f]{24}/, @client.id.to_s
|
67
|
+
end
|
68
|
+
|
69
|
+
should "assign client a secret" do
|
70
|
+
assert_match /[0-9a-f]{64}/, @client.secret
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context "with client ID" do
|
75
|
+
|
76
|
+
context "no such client" do
|
77
|
+
setup do
|
78
|
+
@client = Server.register(:id=>"4ce24c423321e88ac5000015", :secret=>"foobar", :display_name=>"MyApp")
|
79
|
+
end
|
80
|
+
|
81
|
+
should "create new client" do
|
82
|
+
assert_equal 2, Server::Client.collection.count
|
83
|
+
end
|
84
|
+
|
85
|
+
should "should assign it the client identifier" do
|
86
|
+
assert_equal "4ce24c423321e88ac5000015", @client.id.to_s
|
87
|
+
end
|
88
|
+
|
89
|
+
should "should assign it the client secret" do
|
90
|
+
assert_equal "foobar", @client.secret
|
91
|
+
end
|
92
|
+
|
93
|
+
should "should assign it the other properties" do
|
94
|
+
assert_equal "MyApp", @client.display_name
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "existing client" do
|
99
|
+
setup do
|
100
|
+
Server.register(:id=>"4ce24c423321e88ac5000015", :secret=>"foobar", :display_name=>"MyApp")
|
101
|
+
@client = Server.register(:id=>"4ce24c423321e88ac5000015", :secret=>"foobar", :display_name=>"Rock Star")
|
102
|
+
end
|
103
|
+
|
104
|
+
should "not create new client" do
|
105
|
+
assert_equal 2, Server::Client.collection.count
|
106
|
+
end
|
107
|
+
|
108
|
+
should "should not change the client identifier" do
|
109
|
+
assert_equal "4ce24c423321e88ac5000015", @client.id.to_s
|
110
|
+
end
|
111
|
+
|
112
|
+
should "should not change the client secret" do
|
113
|
+
assert_equal "foobar", @client.secret
|
114
|
+
end
|
115
|
+
|
116
|
+
should "should change all the other properties" do
|
117
|
+
assert_equal "Rock Star", @client.display_name
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context "secret mismatch" do
|
122
|
+
setup do
|
123
|
+
Server.register(:id=>"4ce24c423321e88ac5000015", :secret=>"foobar", :display_name=>"MyApp")
|
124
|
+
end
|
125
|
+
|
126
|
+
should "raise error" do
|
127
|
+
assert_raises RuntimeError do
|
128
|
+
Server.register(:id=>"4ce24c423321e88ac5000015", :secret=>"wrong", :display_name=>"MyApp")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
|
137
|
+
context "access_grant" do
|
138
|
+
setup do
|
139
|
+
code = Server.access_grant("Batman", client.id, %w{read})
|
140
|
+
basic_authorize client.id, client.secret
|
141
|
+
post "/oauth/access_token", :scope=>"read", :grant_type=>"authorization_code", :code=>code, :redirect_uri=>client.redirect_uri
|
142
|
+
@token = JSON.parse(last_response.body)["access_token"]
|
143
|
+
end
|
144
|
+
|
145
|
+
should "resolve into an access token" do
|
146
|
+
assert Server.get_access_token(@token)
|
147
|
+
end
|
148
|
+
|
149
|
+
should "resolve into access token with grant identity" do
|
150
|
+
assert_equal "Batman", Server.get_access_token(@token).identity
|
151
|
+
end
|
152
|
+
|
153
|
+
should "resolve into access token with grant scope" do
|
154
|
+
assert_equal %w{read}, Server.get_access_token(@token).scope
|
155
|
+
end
|
156
|
+
|
157
|
+
should "resolve into access token with grant client" do
|
158
|
+
assert_equal client.id, Server.get_access_token(@token).client_id
|
159
|
+
end
|
160
|
+
|
161
|
+
context "with no scope" do
|
162
|
+
setup { @code = Server.access_grant("Batman", client.id) }
|
163
|
+
|
164
|
+
should "pick client scope" do
|
165
|
+
assert_equal %w{oauth-admin read write}, Server::AccessGrant.from_code(@code).scope
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
context "no expiration" do
|
170
|
+
setup do
|
171
|
+
@code = Server.access_grant("Batman", client.id)
|
172
|
+
end
|
173
|
+
|
174
|
+
should "not expire in a minute" do
|
175
|
+
Timecop.travel 60 do
|
176
|
+
basic_authorize client.id, client.secret
|
177
|
+
post "/oauth/access_token", :scope=>"read", :grant_type=>"authorization_code", :code=>@code, :redirect_uri=>client.redirect_uri
|
178
|
+
assert_equal 200, last_response.status
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
should "expire after 5 minutes" do
|
183
|
+
Timecop.travel 300 do
|
184
|
+
basic_authorize client.id, client.secret
|
185
|
+
post "/oauth/access_token", :scope=>"read", :grant_type=>"authorization_code", :code=>@code, :redirect_uri=>client.redirect_uri
|
186
|
+
assert_equal 400, last_response.status
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
context "expiration set" do
|
192
|
+
setup do
|
193
|
+
@code = Server.access_grant("Batman", client.id, nil, 1800)
|
194
|
+
end
|
195
|
+
|
196
|
+
should "not expire prematurely" do
|
197
|
+
Timecop.travel 1750 do
|
198
|
+
basic_authorize client.id, client.secret
|
199
|
+
post "/oauth/access_token", :scope=>"read", :grant_type=>"authorization_code", :code=>@code, :redirect_uri=>client.redirect_uri
|
200
|
+
assert_equal 200, last_response.status
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
should "expire after specified seconds" do
|
205
|
+
Timecop.travel 1800 do
|
206
|
+
basic_authorize client.id, client.secret
|
207
|
+
post "/oauth/access_token", :scope=>"read", :grant_type=>"authorization_code", :code=>@code, :redirect_uri=>client.redirect_uri
|
208
|
+
assert_equal 400, last_response.status
|
209
|
+
end
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
end
|
214
|
+
|
215
|
+
|
216
|
+
context "get_access_token" do
|
217
|
+
setup { @token = Server.token_for("Batman", client.id, %w{read}) }
|
218
|
+
should "return authorization request" do
|
219
|
+
assert_equal @token, Server.get_access_token(@token).token
|
220
|
+
end
|
221
|
+
|
222
|
+
should "return nil if no client found" do
|
223
|
+
assert !Server.get_access_token("4ce2488e3321e87ac1000004")
|
224
|
+
end
|
225
|
+
|
226
|
+
context "with no scope" do
|
227
|
+
setup { @token = Server.token_for("Batman", client.id) }
|
228
|
+
|
229
|
+
should "pick client scope" do
|
230
|
+
assert_equal %w{oauth-admin read write}, Server::AccessToken.from_token(@token).scope
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
|
236
|
+
context "token_for" do
|
237
|
+
setup { @token = Server.token_for("Batman", client.id, %w{read write}) }
|
238
|
+
|
239
|
+
should "return access token" do
|
240
|
+
assert_match /[0-9a-f]{32}/, @token
|
241
|
+
end
|
242
|
+
|
243
|
+
should "associate token with client" do
|
244
|
+
assert_equal client.id, Server.get_access_token(@token).client_id
|
245
|
+
end
|
246
|
+
|
247
|
+
should "associate token with identity" do
|
248
|
+
assert_equal "Batman", Server.get_access_token(@token).identity
|
249
|
+
end
|
250
|
+
|
251
|
+
should "associate token with scope" do
|
252
|
+
assert_equal %w{read write}, Server.get_access_token(@token).scope
|
253
|
+
end
|
254
|
+
|
255
|
+
should "return same token for same parameters" do
|
256
|
+
assert_equal @token, Server.token_for("Batman", client.id, %w{write read})
|
257
|
+
end
|
258
|
+
|
259
|
+
should "return different token for different identity" do
|
260
|
+
assert @token != Server.token_for("Superman", client.id, %w{read write})
|
261
|
+
end
|
262
|
+
|
263
|
+
should "return different token for different client" do
|
264
|
+
client = Server.register(:display_name=>"MyApp")
|
265
|
+
assert @token != Server.token_for("Batman", client.id, %w{read write})
|
266
|
+
end
|
267
|
+
|
268
|
+
should "return different token for different scope" do
|
269
|
+
assert @token != Server.token_for("Batman", client.id, %w{read})
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
|
274
|
+
context "list access tokens" do
|
275
|
+
setup do
|
276
|
+
@one = Server.token_for("Batman", client.id, %w{read})
|
277
|
+
@two = Server.token_for("Superman", client.id, %w{read})
|
278
|
+
@three = Server.token_for("Batman", client.id, %w{write})
|
279
|
+
end
|
280
|
+
|
281
|
+
should "return all tokens for identity" do
|
282
|
+
assert_contains Server.list_access_tokens("Batman").map(&:token), @one
|
283
|
+
assert_contains Server.list_access_tokens("Batman").map(&:token), @three
|
284
|
+
end
|
285
|
+
|
286
|
+
should "not return tokens for other identities" do
|
287
|
+
assert !Server.list_access_tokens("Batman").map(&:token).include?(@two)
|
288
|
+
end
|
289
|
+
|
290
|
+
end
|
291
|
+
|
292
|
+
end
|