rack-oauth2-server 2.0.0.beta3 → 2.0.0.beta4
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 +25 -7
- data/README.rdoc +18 -7
- data/VERSION +1 -1
- data/bin/oauth2-server +6 -6
- data/lib/rack/oauth2/admin/css/screen.css +8 -2
- data/lib/rack/oauth2/admin/js/application.js +44 -37
- data/lib/rack/oauth2/admin/js/sammy.oauth2.js +10 -3
- data/lib/rack/oauth2/admin/views/client.tmpl +3 -2
- data/lib/rack/oauth2/admin/views/edit.tmpl +13 -9
- data/lib/rack/oauth2/models/access_grant.rb +6 -4
- data/lib/rack/oauth2/models/access_token.rb +12 -14
- data/lib/rack/oauth2/models/auth_request.rb +10 -7
- data/lib/rack/oauth2/models/client.rb +11 -7
- data/lib/rack/oauth2/rails.rb +2 -2
- data/lib/rack/oauth2/server/admin.rb +8 -6
- data/lib/rack/oauth2/server/helper.rb +2 -2
- data/lib/rack/oauth2/server/practice.rb +1 -1
- data/lib/rack/oauth2/server/utils.rb +4 -4
- data/lib/rack/oauth2/server.rb +53 -26
- data/lib/rack/oauth2/sinatra.rb +2 -2
- data/test/admin/api_test.rb +13 -11
- data/test/oauth/access_grant_test.rb +27 -3
- data/test/oauth/access_token_test.rb +2 -25
- data/test/oauth/server_test.rb +64 -21
- data/test/rails2/log/test.log +10567 -0
- data/test/rails3/log/test.log +15977 -0
- data/test/setup.rb +2 -2
- metadata +5 -5
@@ -71,8 +71,8 @@ module Rack
|
|
71
71
|
# Forces all requests to use HTTPS (true by default except in
|
72
72
|
# development mode).
|
73
73
|
set :force_ssl, !development?
|
74
|
-
# Common
|
75
|
-
set :
|
74
|
+
# Common scope shown and added by default to new clients.
|
75
|
+
set :scope, []
|
76
76
|
|
77
77
|
|
78
78
|
set :logger, defined?(::Rails) && ::Rails.logger
|
@@ -129,7 +129,7 @@ module Rack
|
|
129
129
|
get "/api/clients" do
|
130
130
|
content_type "application/json"
|
131
131
|
json = { :list=>Server::Client.all.map { |client| client_as_json(client) },
|
132
|
-
:
|
132
|
+
:scope=>Server::Utils.normalize_scope(settings.scope),
|
133
133
|
:history=>"#{request.script_name}/api/clients/history",
|
134
134
|
:tokens=>{ :total=>Server::AccessToken.count, :week=>Server::AccessToken.count(:days=>7),
|
135
135
|
:revoked=>Server::AccessToken.count(:days=>7, :revoked=>true) } }
|
@@ -220,13 +220,15 @@ module Rack
|
|
220
220
|
halt 400, "Image URL must be an absolute URL with HTTP/S scheme" unless
|
221
221
|
image_url.absolute? && %{http https}.include?(image_url.scheme)
|
222
222
|
end
|
223
|
-
|
224
|
-
{ :display_name=>display_name, :link=>link.to_s, :image_url=>image_url.to_s,
|
223
|
+
scope = Server::Utils.normalize_scope(params[:scope])
|
224
|
+
{ :display_name=>display_name, :link=>link.to_s, :image_url=>image_url.to_s,
|
225
|
+
:redirect_uri=>redirect_uri.to_s, :scope=>scope, :notes=>params[:notes] }
|
225
226
|
end
|
226
227
|
|
227
228
|
def client_as_json(client, with_stats = false)
|
228
229
|
{ "id"=>client.id.to_s, "secret"=>client.secret, :redirectUri=>client.redirect_uri,
|
229
|
-
:displayName=>client.display_name, :link=>client.link, :imageUrl=>client.image_url,
|
230
|
+
:displayName=>client.display_name, :link=>client.link, :imageUrl=>client.image_url,
|
231
|
+
:notes=>client.notes, :scope=>client.scope,
|
230
232
|
:url=>"#{request.script_name}/api/client/#{client.id}",
|
231
233
|
:revoke=>"#{request.script_name}/api/client/#{client.id}/revoke",
|
232
234
|
:history=>"#{request.script_name}/api/client/#{client.id}/history",
|
@@ -54,9 +54,9 @@ module Rack
|
|
54
54
|
# @return [Array<String>, nil] Scope names, e.g ["read, "write"]
|
55
55
|
def scope
|
56
56
|
if access_token
|
57
|
-
@scope ||= Server
|
57
|
+
@scope ||= Server.get_access_token(access_token).scope
|
58
58
|
elsif authorization
|
59
|
-
@scope ||= Server
|
59
|
+
@scope ||= Server.get_auth_request(authorization).scope
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
@@ -21,7 +21,7 @@ module Rack
|
|
21
21
|
<dt>Resource requiring authorization and scope "sudo":</dt>
|
22
22
|
<dd>http://#{request.host}:#{request.port}/make</dd>
|
23
23
|
</dl>
|
24
|
-
<p>The
|
24
|
+
<p>The scope can be "nobody", "sudo", "oauth-admin" or combination of the three.</p>
|
25
25
|
<p>You can manage client applications and tokens from the <a href="/oauth/admin">OAuth console</a>.</p>
|
26
26
|
HTML
|
27
27
|
end
|
@@ -17,10 +17,10 @@ module Rack
|
|
17
17
|
raise InvalidRequestError, "Redirect URL looks fishy to me"
|
18
18
|
end
|
19
19
|
|
20
|
-
#
|
21
|
-
#
|
22
|
-
def
|
23
|
-
(Array ===
|
20
|
+
# Given scope as either array or string, return array of same names,
|
21
|
+
# unique and sorted.
|
22
|
+
def normalize_scope(scope)
|
23
|
+
(Array === scope ? scope.join(" ") : scope || "").split(/\s+/).compact.uniq.sort
|
24
24
|
end
|
25
25
|
|
26
26
|
end
|
data/lib/rack/oauth2/server.rb
CHANGED
@@ -35,8 +35,7 @@ module Rack
|
|
35
35
|
# Registers and returns a new Client. Can also be used to update
|
36
36
|
# existing client registration, by passing identifier (and secret) of
|
37
37
|
# existing client record. That way, your setup script can create a new
|
38
|
-
# client application and run repeatedly without fail.
|
39
|
-
# adding new scopes to your existing client application.
|
38
|
+
# client application and run repeatedly without fail.
|
40
39
|
#
|
41
40
|
# @param [Hash] args Arguments for registering client application
|
42
41
|
# @option args [String] :id Client identifier. Use this to update
|
@@ -50,17 +49,19 @@ module Rack
|
|
50
49
|
# name.
|
51
50
|
# @option args [String] redirect_uri Redirect URL: authorization
|
52
51
|
# requests for this client will always redirect back to this URL.
|
53
|
-
# @option args [Array]
|
52
|
+
# @option args [Array] scope Scope that client application can request
|
53
|
+
# (list of names).
|
54
|
+
# @option args [Array] notes Free form text, for internal use.
|
54
55
|
#
|
55
56
|
# @example Registering new client application
|
56
57
|
# Server.register :display_name=>"My Application",
|
57
|
-
# :link=>"http://example.com", :
|
58
|
+
# :link=>"http://example.com", :scope=>%w{read write},
|
58
59
|
# :redirect_uri=>"http://example.com/oauth/callback"
|
59
60
|
# @example Migration using configuration file
|
60
61
|
# config = YAML.load_file(Rails.root + "config/oauth.yml")
|
61
62
|
# Server.register config["id"], config["secret"],
|
62
63
|
# :display_name=>"My Application", :link=>"http://example.com",
|
63
|
-
# :
|
64
|
+
# :scope=>config["scope"],
|
64
65
|
# :redirect_uri=>"http://example.com/oauth/callback"
|
65
66
|
def register(args)
|
66
67
|
if args[:id] && args[:secret] && (client = get_client(args[:id]))
|
@@ -71,6 +72,19 @@ module Rack
|
|
71
72
|
end
|
72
73
|
end
|
73
74
|
|
75
|
+
# Creates and returns a new access grant. Actually, returns only the
|
76
|
+
# authorization code which you can turn into an access token by
|
77
|
+
# making a request to /oauth/access_token.
|
78
|
+
#
|
79
|
+
# @param [String] identity User ID, account ID, etc
|
80
|
+
# @param [String] client_id Client identifier
|
81
|
+
# @param [Array, nil] scope Array of string, nil if you want 'em all
|
82
|
+
# @return [String] Access grant authorization code
|
83
|
+
def access_grant(identity, client_id, scope = nil)
|
84
|
+
client = get_client(client_id) or fail "No such client"
|
85
|
+
AccessGrant.create(identity, client, scope || client.scope).code
|
86
|
+
end
|
87
|
+
|
74
88
|
# Returns AccessToken from token.
|
75
89
|
#
|
76
90
|
# @param [String] token Access token (e.g. from oauth.access_token)
|
@@ -80,15 +94,16 @@ module Rack
|
|
80
94
|
end
|
81
95
|
|
82
96
|
# Returns AccessToken for the specified identity, client application and
|
83
|
-
#
|
97
|
+
# scope. You can use this method to request existing access token, new
|
84
98
|
# token generated if one does not already exists.
|
85
99
|
#
|
86
100
|
# @param [String] identity Identity, e.g. user ID, account ID
|
87
101
|
# @param [String] client_id Client application identifier
|
88
|
-
# @param [
|
89
|
-
# @return [
|
90
|
-
def
|
91
|
-
|
102
|
+
# @param [Array, nil] scope Array of names, nil if you want 'em all
|
103
|
+
# @return [String] Access token
|
104
|
+
def token_for(identity, client_id, scope = nil)
|
105
|
+
client = get_client(client_id) or fail "No such client"
|
106
|
+
AccessToken.get_token_for(identity, client, scope || client.scope).token
|
92
107
|
end
|
93
108
|
|
94
109
|
# Returns all AccessTokens for an identity.
|
@@ -121,6 +136,15 @@ module Rack
|
|
121
136
|
# Defaults to use the request host name.
|
122
137
|
# - :logger -- The logger to use. Under Rails, defaults to use the Rails
|
123
138
|
# logger. Will use Rack::Logger if available.
|
139
|
+
#
|
140
|
+
# Authenticator is a block that receives either two or four parameters.
|
141
|
+
# The first two are username and password. The other two are the client
|
142
|
+
# identifier and scope. It authenticated, it returns an identity,
|
143
|
+
# otherwise it can return nil or false. For example:
|
144
|
+
# oauth.authenticator = lambda do |username, password|
|
145
|
+
# user = User.find_by_username(username)
|
146
|
+
# user if user && user.authenticated?(password)
|
147
|
+
# end
|
124
148
|
Options = Struct.new(:access_token_path, :authenticator, :authorization_types,
|
125
149
|
:authorize_path, :database, :host, :param_authentication, :path, :realm, :logger)
|
126
150
|
|
@@ -184,8 +208,8 @@ module Rack
|
|
184
208
|
# and return appropriate WWW-Authenticate header.
|
185
209
|
response = @app.call(env)
|
186
210
|
if response[0] == 403
|
187
|
-
|
188
|
-
challenge = 'OAuth realm="%s", error="insufficient_scope", scope="%s"' % [(options.realm || request.host),
|
211
|
+
scope = Utils.normalize_scope(response[1]["oauth.no_scope"])
|
212
|
+
challenge = 'OAuth realm="%s", error="insufficient_scope", scope="%s"' % [(options.realm || request.host), scope.join(" ")]
|
189
213
|
response[1]["WWW-Authenticate"] = challenge
|
190
214
|
return response
|
191
215
|
else
|
@@ -228,7 +252,7 @@ module Rack
|
|
228
252
|
response_type = auth_request.response_type # Needed for error handling
|
229
253
|
client = self.class.get_client(auth_request.client_id)
|
230
254
|
# Pass back to application, watch for 403 (deny!)
|
231
|
-
logger.info "Request #{auth_request.id}: Client #{client.display_name} requested #{auth_request.response_type} with scope #{auth_request.scope}" if logger
|
255
|
+
logger.info "Request #{auth_request.id}: Client #{client.display_name} requested #{auth_request.response_type} with scope #{auth_request.scope.join(" ")}" if logger
|
232
256
|
request.env["oauth.authorization"] = auth_request.id.to_s
|
233
257
|
response = @app.call(request.env)
|
234
258
|
raise AccessDeniedError if response[0] == 403
|
@@ -249,15 +273,15 @@ module Rack
|
|
249
273
|
client = get_client(request)
|
250
274
|
raise RedirectUriMismatchError unless client.redirect_uri.nil? || client.redirect_uri == redirect_uri.to_s
|
251
275
|
raise UnsupportedResponseTypeError unless options.authorization_types.include?(response_type)
|
252
|
-
requested_scope = Utils.
|
253
|
-
|
254
|
-
raise InvalidScopeError unless (requested_scope -
|
276
|
+
requested_scope = Utils.normalize_scope(request.GET["scope"])
|
277
|
+
allowed_scope = client.scope
|
278
|
+
raise InvalidScopeError unless (requested_scope - allowed_scope).empty?
|
255
279
|
# Create object to track authorization request and let application
|
256
280
|
# handle the rest.
|
257
|
-
auth_request = AuthRequest.create(client
|
281
|
+
auth_request = AuthRequest.create(client, requested_scope, redirect_uri.to_s, response_type, state)
|
258
282
|
uri = URI.parse(request.url)
|
259
283
|
uri.query = "authorization=#{auth_request.id.to_s}"
|
260
|
-
return [303, { "Location"=>uri.to_s }, []]
|
284
|
+
return [303, { "Location"=>uri.to_s }, ["You are being redirected"]]
|
261
285
|
end
|
262
286
|
rescue OAuthError=>error
|
263
287
|
logger.error "Authorization request error: #{error.code} #{error.message}" if logger
|
@@ -326,13 +350,16 @@ module Rack
|
|
326
350
|
# 4.1.2. Resource Owner Password Credentials
|
327
351
|
username, password = request.POST.values_at("username", "password")
|
328
352
|
raise InvalidGrantError unless username && password
|
329
|
-
|
353
|
+
requested_scope = Utils.normalize_scope(request.POST["scope"])
|
354
|
+
allowed_scope = client.scope
|
355
|
+
raise InvalidScopeError unless (requested_scope - allowed_scope).empty?
|
356
|
+
args = [username, password]
|
357
|
+
args << client.id << requested_scope unless options.authenticator.arity == 2
|
358
|
+
identity = options.authenticator.call(*args)
|
330
359
|
raise InvalidGrantError unless identity
|
331
|
-
|
332
|
-
|
333
|
-
raise
|
334
|
-
access_token = AccessToken.get_token_for(identity, client.id, requested_scope)
|
335
|
-
else raise UnsupportedGrantType
|
360
|
+
access_token = AccessToken.get_token_for(identity, client, requested_scope)
|
361
|
+
else
|
362
|
+
raise UnsupportedGrantType
|
336
363
|
end
|
337
364
|
logger.info "Access token #{access_token.token} granted to client #{client.display_name}, identity #{access_token.identity}" if logger
|
338
365
|
response = { :access_token=>access_token.token }
|
@@ -368,7 +395,7 @@ module Rack
|
|
368
395
|
|
369
396
|
# Rack redirect response. The argument is typically a URI object.
|
370
397
|
def redirect_to(uri)
|
371
|
-
return [302, { "Location"=>uri.to_s }, []]
|
398
|
+
return [302, { "Location"=>uri.to_s }, ["You are being redirected"]]
|
372
399
|
end
|
373
400
|
|
374
401
|
def bad_request(message)
|
@@ -379,7 +406,7 @@ module Rack
|
|
379
406
|
def unauthorized(request, error = nil)
|
380
407
|
challenge = 'OAuth realm="%s"' % (options.realm || request.host)
|
381
408
|
challenge << ', error="%s", error_description="%s"' % [error.code, error.message] if error
|
382
|
-
return [401, { "WWW-Authenticate"=>challenge }, []]
|
409
|
+
return [401, { "WWW-Authenticate"=>challenge }, [error && error.message || ""]]
|
383
410
|
end
|
384
411
|
|
385
412
|
# Wraps Rack::Request to expose Basic and OAuth authentication
|
data/lib/rack/oauth2/sinatra.rb
CHANGED
@@ -13,13 +13,13 @@ module Rack
|
|
13
13
|
# access scope.
|
14
14
|
#
|
15
15
|
# Adds oauth setting you can use to configure the module (e.g. setting
|
16
|
-
# available
|
16
|
+
# available scope, see example).
|
17
17
|
#
|
18
18
|
# @example
|
19
19
|
# require "rack/oauth2/sinatra"
|
20
20
|
# class MyApp < Sinatra::Base
|
21
21
|
# register Rack::OAuth2::Sinatra
|
22
|
-
# oauth[:
|
22
|
+
# oauth[:scope] = %w{read write}
|
23
23
|
#
|
24
24
|
# oauth_required "/api"
|
25
25
|
# oauth_required "/api/edit", :scope=>"write"
|
data/test/admin/api_test.rb
CHANGED
@@ -18,13 +18,13 @@ class AdminApiTest < Test::Unit::TestCase
|
|
18
18
|
|
19
19
|
|
20
20
|
def without_scope
|
21
|
-
token = Server.
|
22
|
-
header "Authorization", "OAuth #{token
|
21
|
+
token = Server.token_for("Superman", client.id, "nobody")
|
22
|
+
header "Authorization", "OAuth #{token}"
|
23
23
|
end
|
24
24
|
|
25
25
|
def with_scope
|
26
|
-
token = Server.
|
27
|
-
header "Authorization", "OAuth #{token
|
26
|
+
token = Server.token_for("Superman", client.id, "oauth-admin")
|
27
|
+
header "Authorization", "OAuth #{token}"
|
28
28
|
end
|
29
29
|
|
30
30
|
def json
|
@@ -84,8 +84,8 @@ class AdminApiTest < Test::Unit::TestCase
|
|
84
84
|
should "return list of clients" do
|
85
85
|
assert Array === json["list"]
|
86
86
|
end
|
87
|
-
should "return
|
88
|
-
assert_equal %w{read write}, json["
|
87
|
+
should "return known scope" do
|
88
|
+
assert_equal %w{read write}, json["scope"]
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
@@ -123,8 +123,8 @@ class AdminApiTest < Test::Unit::TestCase
|
|
123
123
|
should "provide link to revoke resource"do
|
124
124
|
assert_equal ["/oauth/admin/api/client", client.id, "revoke"].join("/"), @first["revoke"]
|
125
125
|
end
|
126
|
-
should "provide
|
127
|
-
assert_equal %w{read write}, @first["
|
126
|
+
should "provide scope for client" do
|
127
|
+
assert_equal %w{oauth-admin read write}, @first["scope"]
|
128
128
|
end
|
129
129
|
should "tell if not revoked" do
|
130
130
|
assert @first["revoked"].nil?
|
@@ -149,12 +149,14 @@ class AdminApiTest < Test::Unit::TestCase
|
|
149
149
|
tokens = []
|
150
150
|
1.upto(10).map do |days|
|
151
151
|
Timecop.travel -days*86400 do
|
152
|
-
tokens << Server.
|
152
|
+
tokens << Server.token_for("Superman#{days}", client.id)
|
153
153
|
end
|
154
154
|
end
|
155
155
|
# Revoke one token today (within past 7 days), one 10 days ago (beyond)
|
156
|
-
|
157
|
-
|
156
|
+
Timecop.travel -7 * 86400 do
|
157
|
+
Server.get_access_token(tokens[0]).revoke!
|
158
|
+
end
|
159
|
+
Server.get_access_token(tokens[1]).revoke!
|
158
160
|
with_scope ; get "/oauth/admin/api/clients"
|
159
161
|
end
|
160
162
|
|
@@ -148,7 +148,7 @@ class AccessGrantTest < Test::Unit::TestCase
|
|
148
148
|
|
149
149
|
context "authorization code for different client" do
|
150
150
|
setup do
|
151
|
-
grant =
|
151
|
+
grant = Server::AccessGrant.create("foo bar", Server.register(:scope=>%w{read write}), "read write", nil)
|
152
152
|
request_access_token :code=>grant.code
|
153
153
|
end
|
154
154
|
should_return_error :invalid_grant
|
@@ -156,7 +156,7 @@ class AccessGrantTest < Test::Unit::TestCase
|
|
156
156
|
|
157
157
|
context "authorization code revoked" do
|
158
158
|
setup do
|
159
|
-
|
159
|
+
Server::AccessGrant.from_code(@code).revoke!
|
160
160
|
request_access_token
|
161
161
|
end
|
162
162
|
should_return_error :invalid_grant
|
@@ -169,7 +169,8 @@ class AccessGrantTest < Test::Unit::TestCase
|
|
169
169
|
|
170
170
|
context "no redirect URI to match" do
|
171
171
|
setup do
|
172
|
-
|
172
|
+
@client = Server.register(:display_name=>"No rediret", :scope=>"read write")
|
173
|
+
grant = Server::AccessGrant.create("foo bar", client, "read write", nil)
|
173
174
|
request_access_token :code=>grant.code, :redirect_uri=>"http://uberclient.dot/oz"
|
174
175
|
end
|
175
176
|
should_respond_with_access_token
|
@@ -203,6 +204,29 @@ class AccessGrantTest < Test::Unit::TestCase
|
|
203
204
|
should_return_error :invalid_scope
|
204
205
|
end
|
205
206
|
|
207
|
+
context "authenticator with 4 parameters" do
|
208
|
+
setup do
|
209
|
+
@old = config.authenticator
|
210
|
+
config.authenticator = lambda do |username, password, client_id, scope|
|
211
|
+
@client_id = client_id
|
212
|
+
@scope = scope
|
213
|
+
"Batman"
|
214
|
+
end
|
215
|
+
request_with_username_password "cowbell", "more", "read"
|
216
|
+
end
|
217
|
+
|
218
|
+
should_respond_with_access_token "read"
|
219
|
+
should "receive client identifier" do
|
220
|
+
assert_equal client.id, @client_id
|
221
|
+
end
|
222
|
+
should "receive scope" do
|
223
|
+
assert_equal %w{read}, @scope
|
224
|
+
end
|
225
|
+
|
226
|
+
teardown { config.authenticator = @old }
|
227
|
+
end
|
228
|
+
|
229
|
+
|
206
230
|
# 4.2. Access Token Response
|
207
231
|
|
208
232
|
context "using authorization code" do
|
@@ -103,7 +103,7 @@ class AccessTokenTest < Test::Unit::TestCase
|
|
103
103
|
|
104
104
|
context "revoked HTTP token" do
|
105
105
|
setup do
|
106
|
-
|
106
|
+
Server::AccessToken.from_token(@token).revoke!
|
107
107
|
with_token
|
108
108
|
get "/private"
|
109
109
|
end
|
@@ -257,7 +257,7 @@ class AccessTokenTest < Test::Unit::TestCase
|
|
257
257
|
|
258
258
|
context "list tokens" do
|
259
259
|
setup do
|
260
|
-
@other =
|
260
|
+
@other = Server.token_for("foobar", client.id, "read")
|
261
261
|
get "/list_tokens"
|
262
262
|
end
|
263
263
|
|
@@ -271,29 +271,6 @@ class AccessTokenTest < Test::Unit::TestCase
|
|
271
271
|
end
|
272
272
|
|
273
273
|
|
274
|
-
context "get_token_for" do
|
275
|
-
should "return two different tokens for two different clients" do
|
276
|
-
myapp = Rack::OAuth2::Server.get_token_for("Batman", "4cca30423321e895cb000001", "read write")
|
277
|
-
yourapp = Rack::OAuth2::Server.get_token_for("Batman", "4fff30423321e895cb000001", "read write")
|
278
|
-
assert myapp.token != yourapp.token
|
279
|
-
end
|
280
|
-
should "return two different tokens for two different identities" do
|
281
|
-
me = Rack::OAuth2::Server.get_token_for("Batman", "4cca30423321e895cb000001", "read write")
|
282
|
-
you = Rack::OAuth2::Server.get_token_for("Robin", "4cca30423321e895cb000001", "read write")
|
283
|
-
assert me.token != you.token
|
284
|
-
end
|
285
|
-
should "return two different tokens for two different scope" do
|
286
|
-
write = Rack::OAuth2::Server.get_token_for("Batman", "4cca30423321e895cb000001", "read write")
|
287
|
-
math = Rack::OAuth2::Server.get_token_for("Batman", "4cca30423321e895cb000001", "read math")
|
288
|
-
assert write.token != math.token
|
289
|
-
end
|
290
|
-
should "return same tokens regardless of order of scope" do
|
291
|
-
one = Rack::OAuth2::Server.get_token_for("Batman", "4cca30423321e895cb000001", "read write math")
|
292
|
-
two = Rack::OAuth2::Server.get_token_for("Batman", "4cca30423321e895cb000001", "math write read")
|
293
|
-
assert_equal one.token, two.token
|
294
|
-
end
|
295
|
-
end
|
296
|
-
|
297
274
|
context "with specific host" do
|
298
275
|
context "right host" do
|
299
276
|
setup do
|
data/test/oauth/server_test.rb
CHANGED
@@ -8,7 +8,7 @@ class ServerTest < Test::Unit::TestCase
|
|
8
8
|
end
|
9
9
|
|
10
10
|
context "get_auth_request" do
|
11
|
-
setup { @request = Server::AuthRequest.create(client
|
11
|
+
setup { @request = Server::AuthRequest.create(client, client.scope.join(" "), client.redirect_uri, "token", nil) }
|
12
12
|
should "return authorization request" do
|
13
13
|
assert_equal @request.id, Server.get_auth_request(@request.id).id
|
14
14
|
end
|
@@ -34,7 +34,7 @@ class ServerTest < Test::Unit::TestCase
|
|
34
34
|
context "no client ID" do
|
35
35
|
setup do
|
36
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", :
|
37
|
+
:redirect_uri=>"http://example.org/oauth/callback", :scope=>%w{read write})
|
38
38
|
end
|
39
39
|
|
40
40
|
should "create new client" do
|
@@ -58,8 +58,8 @@ class ServerTest < Test::Unit::TestCase
|
|
58
58
|
assert_equal "http://example.org/oauth/callback", Server.get_client(@client.id).redirect_uri
|
59
59
|
end
|
60
60
|
|
61
|
-
should "set
|
62
|
-
assert_equal %w{read write}, Server.get_client(@client.id).
|
61
|
+
should "set scope" do
|
62
|
+
assert_equal %w{read write}, Server.get_client(@client.id).scope
|
63
63
|
end
|
64
64
|
|
65
65
|
should "assign client an ID" do
|
@@ -134,8 +134,43 @@ class ServerTest < Test::Unit::TestCase
|
|
134
134
|
end
|
135
135
|
|
136
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
|
+
end
|
170
|
+
|
171
|
+
|
137
172
|
context "get_access_token" do
|
138
|
-
setup { @token = Server.
|
173
|
+
setup { @token = Server.token_for("Batman", client.id, %w{read}) }
|
139
174
|
should "return authorization request" do
|
140
175
|
assert_equal @token, Server.get_access_token(@token).token
|
141
176
|
end
|
@@ -143,61 +178,69 @@ class ServerTest < Test::Unit::TestCase
|
|
143
178
|
should "return nil if no client found" do
|
144
179
|
assert !Server.get_access_token("4ce2488e3321e87ac1000004")
|
145
180
|
end
|
181
|
+
|
182
|
+
context "with no scope" do
|
183
|
+
setup { @token = Server.token_for("Batman", client.id) }
|
184
|
+
|
185
|
+
should "pick client scope" do
|
186
|
+
assert_equal %w{oauth-admin read write}, Server::AccessToken.from_token(@token).scope
|
187
|
+
end
|
188
|
+
end
|
146
189
|
end
|
147
190
|
|
148
191
|
|
149
|
-
context "
|
150
|
-
setup { @token = Server.
|
192
|
+
context "token_for" do
|
193
|
+
setup { @token = Server.token_for("Batman", client.id, %w{read write}) }
|
151
194
|
|
152
195
|
should "return access token" do
|
153
|
-
|
196
|
+
assert_match /[0-9a-f]{32}/, @token
|
154
197
|
end
|
155
198
|
|
156
199
|
should "associate token with client" do
|
157
|
-
assert_equal client.id, @token.client_id
|
200
|
+
assert_equal client.id, Server.get_access_token(@token).client_id
|
158
201
|
end
|
159
202
|
|
160
203
|
should "associate token with identity" do
|
161
|
-
assert_equal "Batman", @token.identity
|
204
|
+
assert_equal "Batman", Server.get_access_token(@token).identity
|
162
205
|
end
|
163
206
|
|
164
207
|
should "associate token with scope" do
|
165
|
-
assert_equal %w{read write}, @token.scope
|
208
|
+
assert_equal %w{read write}, Server.get_access_token(@token).scope
|
166
209
|
end
|
167
210
|
|
168
211
|
should "return same token for same parameters" do
|
169
|
-
assert_equal @token
|
212
|
+
assert_equal @token, Server.token_for("Batman", client.id, %w{write read})
|
170
213
|
end
|
171
214
|
|
172
215
|
should "return different token for different identity" do
|
173
|
-
assert @token
|
216
|
+
assert @token != Server.token_for("Superman", client.id, %w{read write})
|
174
217
|
end
|
175
218
|
|
176
219
|
should "return different token for different client" do
|
177
220
|
client = Server.register(:display_name=>"MyApp")
|
178
|
-
assert @token
|
221
|
+
assert @token != Server.token_for("Batman", client.id, %w{read write})
|
179
222
|
end
|
180
223
|
|
181
224
|
should "return different token for different scope" do
|
182
|
-
assert @token
|
225
|
+
assert @token != Server.token_for("Batman", client.id, %w{read})
|
183
226
|
end
|
184
227
|
end
|
185
228
|
|
186
229
|
|
187
230
|
context "list access tokens" do
|
188
231
|
setup do
|
189
|
-
@one = Server.
|
190
|
-
@two = Server.
|
191
|
-
@three = Server.
|
232
|
+
@one = Server.token_for("Batman", client.id, %w{read})
|
233
|
+
@two = Server.token_for("Superman", client.id, %w{read})
|
234
|
+
@three = Server.token_for("Batman", client.id, %w{write})
|
192
235
|
end
|
193
236
|
|
194
237
|
should "return all tokens for identity" do
|
195
|
-
assert_contains Server.list_access_tokens("Batman").map(&:token), @one
|
196
|
-
assert_contains Server.list_access_tokens("Batman").map(&:token), @three
|
238
|
+
assert_contains Server.list_access_tokens("Batman").map(&:token), @one
|
239
|
+
assert_contains Server.list_access_tokens("Batman").map(&:token), @three
|
197
240
|
end
|
198
241
|
|
199
242
|
should "not return tokens for other identities" do
|
200
|
-
assert !Server.list_access_tokens("Batman").map(&:token).include?(@two
|
243
|
+
assert !Server.list_access_tokens("Batman").map(&:token).include?(@two)
|
201
244
|
end
|
202
245
|
|
203
246
|
end
|