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.
@@ -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