tpitale-rack-oauth2-server 2.2.1
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.
- 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
|