rack-oauth2-server 2.0.0.beta3 → 2.0.0.beta4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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 scopes shown and added by default to new clients.
75
- set :scopes, []
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
- :scopes=>Server::Utils.normalize_scopes(settings.scopes),
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
- scopes = Server::Utils.normalize_scopes(params[:scopes])
224
- { :display_name=>display_name, :link=>link.to_s, :image_url=>image_url.to_s, :redirect_uri=>redirect_uri.to_s, :scopes=>scopes }
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, :scopes=>client.scopes,
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::Utils.normalize_scopes(Server.get_access_token(access_token).scope)
57
+ @scope ||= Server.get_access_token(access_token).scope
58
58
  elsif authorization
59
- @scope ||= Server::Utils.normalize_scopes(Server.get_auth_request(authorization).scope)
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 scopes are "nobody", "sudo" and "oauth-admin".</p>
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
- # Gives list of scopes, as either array of string, return array of
21
- # scope names (unique and sorted).
22
- def normalize_scopes(scopes)
23
- (Array === scopes ? scopes.join(" ") : scopes || "").split(/\s+/).compact.uniq.sort
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
@@ -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. Also useful for
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] scopes Scopes that client application can request
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", :scopes=>%w{read write},
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
- # :scopes=>config["scopes"],
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
- # scopes. You can use this method to request existing access token, new
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 [String] scope Access scope (e.g. "read write")
89
- # @return [AccessToken]
90
- def get_token_for(identity, client_id, scope)
91
- AccessToken.get_token_for(identity, client_id, scope)
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
- scopes = Utils.normalize_scopes(response[1]["oauth.no_scope"])
188
- challenge = 'OAuth realm="%s", error="insufficient_scope", scope="%s"' % [(options.realm || request.host), scopes.join(" ")]
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.normalize_scopes(request.GET["scope"])
253
- allowed_scopes = client.scopes
254
- raise InvalidScopeError unless (requested_scope - allowed_scopes).empty?
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.id, requested_scope, redirect_uri.to_s, response_type, state)
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
- identity = options.authenticator.call(username, password)
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
- requested_scope = Utils.normalize_scopes(request.POST["scope"])
332
- allowed_scopes = client.scopes
333
- raise InvalidScopeError unless (requested_scope - allowed_scopes).empty?
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
@@ -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 scopes, see example).
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[:scopes] = %w{read write}
22
+ # oauth[:scope] = %w{read write}
23
23
  #
24
24
  # oauth_required "/api"
25
25
  # oauth_required "/api/edit", :scope=>"write"
@@ -18,13 +18,13 @@ class AdminApiTest < Test::Unit::TestCase
18
18
 
19
19
 
20
20
  def without_scope
21
- token = Server.get_token_for("Superman", client.id, "nobody")
22
- header "Authorization", "OAuth #{token.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.get_token_for("Superman", client.id, "oauth-admin")
27
- header "Authorization", "OAuth #{token.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 all known scopes" do
88
- assert_equal %w{read write}, json["scopes"]
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 scopes for client" do
127
- assert_equal %w{read write}, @first["scopes"]
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.get_token_for("Superman", client.id, days.to_s)
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
- tokens.first.revoke!
157
- tokens.last.revoke!
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 = Rack::OAuth2::Server::AccessGrant.create("foo bar", "read write", "4cc7bc483321e814b8000000", nil)
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
- Rack::OAuth2::Server::AccessGrant.from_code(@code).revoke!
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
- grant = Rack::OAuth2::Server::AccessGrant.create("foo bar", "read write", client.id, nil)
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
- Rack::OAuth2::Server::AccessToken.from_token(@token).revoke!
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 = Rack::OAuth2::Server.get_token_for("foobar", client.id, "read").token
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
@@ -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.id, client.scopes.join(" "), client.redirect_uri, "token", nil) }
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", :scopes=>%w{read write})
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 scopes" do
62
- assert_equal %w{read write}, Server.get_client(@client.id).scopes
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.get_token_for("Batman", client.id, %w{read}).token }
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 "get_token_for" do
150
- setup { @token = Server.get_token_for("Batman", client.id, %w{read write}) }
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
- assert Server::AccessToken === @token
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.token, Server.get_token_for("Batman", client.id, %w{write read}).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.token != Server.get_token_for("Superman", client.id, %w{read write}).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.token != Server.get_token_for("Batman", client.id, %w{read write}).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.token != Server.get_token_for("Batman", client.id, %w{read}).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.get_token_for("Batman", client.id, %w{read})
190
- @two = Server.get_token_for("Superman", client.id, %w{read})
191
- @three = Server.get_token_for("Batman", client.id, %w{write})
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.token
196
- assert_contains Server.list_access_tokens("Batman").map(&:token), @three.token
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.token)
243
+ assert !Server.list_access_tokens("Batman").map(&:token).include?(@two)
201
244
  end
202
245
 
203
246
  end