rack-oauth2-server 1.3.1 → 1.4.0
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 +27 -1
- data/README.rdoc +25 -19
- data/Rakefile +3 -3
- data/VERSION +1 -1
- data/bin/oauth2-server +7 -7
- data/lib/rack/oauth2/admin/css/screen.css +11 -1
- data/lib/rack/oauth2/admin/js/application.js +21 -10
- data/lib/rack/oauth2/admin/views/client.tmpl +1 -1
- data/lib/rack/oauth2/admin/views/no_access.tmpl +4 -0
- data/lib/rack/oauth2/server.rb +55 -41
- data/lib/rack/oauth2/server/admin.rb +6 -2
- data/lib/rack/oauth2/server/errors.rb +18 -11
- data/lib/rack/oauth2/server/helper.rb +15 -10
- data/rack-oauth2-server.gemspec +1 -0
- data/test/admin/api_test.rb +0 -4
- data/test/admin/ui_test.rb +13 -0
- data/test/oauth/access_grant_test.rb +2 -1
- data/test/oauth/access_token_test.rb +12 -11
- data/test/oauth/authorization_test.rb +19 -9
- data/test/rails/app/controllers/api_controller.rb +1 -1
- data/test/rails/app/controllers/oauth_controller.rb +6 -3
- data/test/rails/config/environment.rb +2 -2
- data/test/rails/log/test.log +43862 -0
- data/test/setup.rb +1 -1
- data/test/sinatra/my_app.rb +9 -6
- metadata +10 -9
- data/test/admin_test_.rb +0 -49
data/CHANGELOG
CHANGED
@@ -1,4 +1,30 @@
|
|
1
|
-
2010-11-
|
1
|
+
2010-11-09 version 1.4.0
|
2
|
+
|
3
|
+
If authorization handle is passed as request parameter (the recommended way),
|
4
|
+
then you can call oauth.grant! with a single argument and oauth.deny! with no
|
5
|
+
arguments.
|
6
|
+
|
7
|
+
You can now call oauth.deny! at any point during the authorization flow, e.g.
|
8
|
+
automatically deny all requests based on scope and client.
|
9
|
+
|
10
|
+
To deny access, return status code 403 (was, incorrectly 401). Or just use
|
11
|
+
oauth.deny!.
|
12
|
+
|
13
|
+
Web console gets template_url setting you can use to map access token identity
|
14
|
+
into a URL in your application. The substitution variable is "{id}".
|
15
|
+
|
16
|
+
Added error page when authorization attempt fails (instead of endless
|
17
|
+
redirect).
|
18
|
+
|
19
|
+
Fixed mounting of Web console on Rails. If it failed you before, try again.
|
20
|
+
|
21
|
+
Fixed documentation for configuration under Rails, clarify that all the
|
22
|
+
interesting stuff happens in after_initialize.
|
23
|
+
|
24
|
+
Fixed error responses for response_type=token to use fragment identifier.
|
25
|
+
|
26
|
+
|
27
|
+
2010-11-08 version 1.3.1
|
2
28
|
|
3
29
|
Added command line tool, helps you get started and setup:
|
4
30
|
$ oauth2-server setup --db my_db
|
data/README.rdoc
CHANGED
@@ -30,14 +30,15 @@ when required, but you do need to configure it from within
|
|
30
30
|
example:
|
31
31
|
|
32
32
|
Rails::Initializer.run do |config|
|
33
|
-
config.oauth.database = Mongo::Connection.new["my_db"]
|
34
|
-
config.oauth.scopes = %w{read write}
|
35
|
-
config.oauth.authenticator = lambda do |username, password|
|
36
|
-
user = User.find(username)
|
37
|
-
user if user && user.authenticated?(password)
|
38
|
-
end
|
39
|
-
|
40
33
|
. . .
|
34
|
+
config.after_initialize do
|
35
|
+
config.oauth.database = Mongo::Connection.new["my_db"]
|
36
|
+
config.oauth.scopes = %w{read write}
|
37
|
+
config.oauth.authenticator = lambda do |username, password|
|
38
|
+
user = User.find(username)
|
39
|
+
user if user && user.authenticated?(password)
|
40
|
+
end
|
41
|
+
end
|
41
42
|
end
|
42
43
|
|
43
44
|
For Sinatra and Padrino, first require +rack/oauth2/sinatra+ and register
|
@@ -110,8 +111,8 @@ user back to the client application with an authorization code or access token.
|
|
110
111
|
|
111
112
|
To signal that the user denied the authorization requests your application sets
|
112
113
|
the response header oauth.authorization as before, and returns the status code
|
113
|
-
|
114
|
-
|
114
|
+
403 (Forbidden). Rack::OAuth2::Server will then redirect the user back to the
|
115
|
+
client application with a suitable error code.
|
115
116
|
|
116
117
|
In Rails, the entire flow would look something like this:
|
117
118
|
|
@@ -125,11 +126,11 @@ In Rails, the entire flow would look something like this:
|
|
125
126
|
end
|
126
127
|
|
127
128
|
def grant
|
128
|
-
head oauth.grant!(
|
129
|
+
head oauth.grant!(current_user.id)
|
129
130
|
end
|
130
131
|
|
131
132
|
def deny
|
132
|
-
head oauth.deny!
|
133
|
+
head oauth.deny!
|
133
134
|
end
|
134
135
|
end
|
135
136
|
|
@@ -149,11 +150,11 @@ In Sinatra/Padrino, it would look something like this:
|
|
149
150
|
end
|
150
151
|
|
151
152
|
post "/oauth/grant" do
|
152
|
-
oauth.grant!
|
153
|
+
oauth.grant! "Superman"
|
153
154
|
end
|
154
155
|
|
155
156
|
post "/oauth/deny" do
|
156
|
-
oauth.deny!
|
157
|
+
oauth.deny!
|
157
158
|
end
|
158
159
|
|
159
160
|
The view would look something like this:
|
@@ -374,9 +375,7 @@ the console, by granting them access to the +oauth-admin+ scope. For example:
|
|
374
375
|
|
375
376
|
def authorize
|
376
377
|
# Only admins allowed to authorize the scope oauth-admin
|
377
|
-
if oauth.scope.include?("oauth-admin") && !current_user.admin?
|
378
|
-
oauth.deny! oauth.authorization
|
379
|
-
end
|
378
|
+
head oauth.deny! if oauth.scope.include?("oauth-admin") && !current_user.admin?
|
380
379
|
end
|
381
380
|
|
382
381
|
Make sure you do that, or you'll allow anyone access to the OAuth Web console.
|
@@ -386,9 +385,11 @@ client ID/secret. For example, for Rails add this to +config/environment.rb+:
|
|
386
385
|
|
387
386
|
Rails::Initializer.run do |config|
|
388
387
|
. . .
|
389
|
-
config.
|
390
|
-
|
391
|
-
|
388
|
+
config.after_initialize do
|
389
|
+
config.middleware.use Rack::OAuth2::Server::Admin.mount
|
390
|
+
Rack::OAuth2::Server::Admin.set :client_id, "4dca20453e4859cb000007"
|
391
|
+
Rack::OAuth2::Server::Admin.set :client_secret, "981fa734e110496fcf667cbf52fbaf03"
|
392
|
+
end
|
392
393
|
end
|
393
394
|
|
394
395
|
For Sinatra, Padrino and other Rack-based applications, you'll want to mount
|
@@ -404,6 +405,11 @@ like so (e.g. in +config.ru+):
|
|
404
405
|
Next, open your browser to http://example.com/oauth/admin, or wherever you
|
405
406
|
mounted the console.
|
406
407
|
|
408
|
+
Another option, +template_url+ allows you to link access token identities to
|
409
|
+
URLs in your application, using the substitution variable "{id}". For example:
|
410
|
+
|
411
|
+
Rack::OAuth2::Server::Admin.set :template_url, "https://example.com/accounts/{id}"
|
412
|
+
|
407
413
|
The OAuth Web console is a single-page client application that operates by
|
408
414
|
accessing the OAuth API. The API is mounted at /oauth/admin/api (basically /api
|
409
415
|
relative to the console), you can access it yourself if you have an access
|
data/Rakefile
CHANGED
@@ -39,14 +39,14 @@ Rake::TestTask.new do |task|
|
|
39
39
|
end
|
40
40
|
|
41
41
|
namespace :test do
|
42
|
-
task :all=>["test:sinatra", "test:
|
42
|
+
task :all=>["test:sinatra", "test:rails"]
|
43
43
|
desc "Run all tests against Sinatra"
|
44
44
|
task :sinatra do
|
45
45
|
sh "rake test FRAMEWORK=sinatra"
|
46
46
|
end
|
47
47
|
desc "Run all tests against Rails 2.3.x"
|
48
|
-
task :
|
49
|
-
sh "rake test FRAMEWORK=
|
48
|
+
task :rails do
|
49
|
+
sh "rake test FRAMEWORK=rails"
|
50
50
|
end
|
51
51
|
end
|
52
52
|
task :default=>"test:all"
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.
|
1
|
+
1.4.0
|
data/bin/oauth2-server
CHANGED
@@ -62,18 +62,18 @@ when "setup"
|
|
62
62
|
Make sure you ONLY authorize administrators to use the oauth-admin scope.
|
63
63
|
For example:
|
64
64
|
|
65
|
-
|
65
|
+
before_filter do
|
66
66
|
# Only admins allowed to authorize the scope oauth-admin
|
67
|
-
if oauth.scope.include?("oauth-admin") && !current_user.admin?
|
68
|
-
oauth.deny! oauth.authorization
|
69
|
-
end
|
67
|
+
head oauth.deny! if oauth.scope.include?("oauth-admin") && !current_user.admin?
|
70
68
|
end
|
71
69
|
|
72
70
|
Rails 2.x, add the following to config/environment.rb:
|
73
71
|
|
74
|
-
config.
|
75
|
-
|
76
|
-
|
72
|
+
config.after_initialize do
|
73
|
+
config.middleware.use Rack::OAuth2::Server::Admin.mount "#{uri.path}"
|
74
|
+
Rack::OAuth2::Server::Admin.set :client_id, "#{client.id}"
|
75
|
+
Rack::OAuth2::Server::Admin.set :client_secret, "#{client.secret}"
|
76
|
+
end
|
77
77
|
|
78
78
|
Sinatra, Padrino and other Rack applications, mount the console:
|
79
79
|
|
@@ -107,8 +107,10 @@ button:active { background: -webkit-gradient(linear, 0% 0%, 0% 100%, from(rgba(0
|
|
107
107
|
}
|
108
108
|
|
109
109
|
#main {
|
110
|
+
margin: 0;
|
110
111
|
padding: 0 2em 4em 2em;
|
111
112
|
background: #fff;
|
113
|
+
border: 1px solid #fff;
|
112
114
|
}
|
113
115
|
#footer {
|
114
116
|
background: #eee;
|
@@ -189,7 +191,7 @@ table.clients td.secrets dd:after {
|
|
189
191
|
}
|
190
192
|
|
191
193
|
table.tokens td.token {
|
192
|
-
width:
|
194
|
+
width: 36em;
|
193
195
|
}
|
194
196
|
table.tokens td.scope {
|
195
197
|
}
|
@@ -264,6 +266,14 @@ table.tokens td.scope {
|
|
264
266
|
margin-left: 60px;
|
265
267
|
}
|
266
268
|
|
269
|
+
.no-access {
|
270
|
+
margin: 0;
|
271
|
+
padding: 0;
|
272
|
+
}
|
273
|
+
.no-access h1 {
|
274
|
+
color: red;
|
275
|
+
}
|
276
|
+
|
267
277
|
.loading {
|
268
278
|
background: url("../images/loading.gif") no-repeat 50% 50%;
|
269
279
|
}
|
@@ -6,28 +6,39 @@ Sammy("#main", function(app) {
|
|
6
6
|
|
7
7
|
// Use OAuth access token in all API requests.
|
8
8
|
$(document).ajaxSend(function(e, xhr) {
|
9
|
-
|
9
|
+
if (app.session("oauth.token"))
|
10
|
+
xhr.setRequestHeader("Authorization", "OAuth " + app.session("oauth.token"));
|
10
11
|
});
|
11
12
|
// For all request (except callback), if we don't have an OAuth access token,
|
12
13
|
// ask for one by requesting authorization.
|
13
|
-
this.before({ except: { path:
|
14
|
+
this.before({ except: { path: /^#\w+=.+/ } }, function(context) {
|
14
15
|
if (!app.session("oauth.token"))
|
15
16
|
context.redirect(document.location.pathname + "/authorize?state=" + escape(context.path));
|
16
17
|
})
|
18
|
+
function hashParams(hash) {
|
19
|
+
var pairs = hash.substring(1).split("&"), params = {};
|
20
|
+
for (var i in pairs) {
|
21
|
+
var splat = pairs[i].split("=");
|
22
|
+
params[splat[0]] = splat[1];
|
23
|
+
}
|
24
|
+
return params;
|
25
|
+
}
|
17
26
|
// We recognize the OAuth authorization callback based on one of its
|
18
27
|
// parameters. Crude but works here.
|
19
|
-
this.get(/^#(access_token=|[^\\]
|
28
|
+
this.get(/^#(access_token=|[^\\].*\&access_token=)/, function(context) {
|
20
29
|
// Instead of a hash we get query parameters, so turn those into an object.
|
21
|
-
var params = context.path
|
22
|
-
|
23
|
-
var splat = params[i].split("=");
|
24
|
-
args[splat[0]] = splat[1];
|
25
|
-
}
|
26
|
-
app.session("oauth.token", args.access_token);
|
30
|
+
var params = hashParams(context.path);
|
31
|
+
app.session("oauth.token", params.access_token);
|
27
32
|
// When the filter redirected the original request, it passed the original
|
28
33
|
// request's URL in the state parameter, which we get back after
|
29
34
|
// authorization.
|
30
|
-
context.redirect(
|
35
|
+
context.redirect(params.state.length == 0 ? "#/" : unescape(params.state));
|
36
|
+
});
|
37
|
+
// Authorization error/rejected.
|
38
|
+
this.get(/^#(error=|[^\\].*\&error=)/, function(context) {
|
39
|
+
var params = hashParams(context.path);
|
40
|
+
var error = params.error_description || "You were denied access";
|
41
|
+
context.partial("admin/views/no_access.tmpl", { error: error.replace(/\+/g, " ") });
|
31
42
|
});
|
32
43
|
|
33
44
|
|
@@ -28,7 +28,7 @@
|
|
28
28
|
{{each tokens.list}}
|
29
29
|
<tr>
|
30
30
|
<td class="token">${token}</td>
|
31
|
-
<td class="identity">${identity}</td>
|
31
|
+
<td class="identity">{{if link}}<a href="${link}">${identity}</a>{{else}}${identity}{{/if}}</td>
|
32
32
|
<td class="scope">${scope}</td>
|
33
33
|
<td class="created">{{html $.shortdate(created)}}</td>
|
34
34
|
<td class="revoke">
|
data/lib/rack/oauth2/server.rb
CHANGED
@@ -2,6 +2,7 @@ require "rack/oauth2/models"
|
|
2
2
|
require "rack/oauth2/server/errors"
|
3
3
|
require "rack/oauth2/server/utils"
|
4
4
|
require "rack/oauth2/server/helper"
|
5
|
+
require "rack/oauth2/server/admin"
|
5
6
|
|
6
7
|
|
7
8
|
module Rack
|
@@ -107,7 +108,7 @@ module Rack
|
|
107
108
|
request.env["oauth.access_token"] = token
|
108
109
|
request.env["oauth.identity"] = access_token.identity
|
109
110
|
logger.info "Authorized #{access_token.identity}" if logger
|
110
|
-
rescue
|
111
|
+
rescue OAuthError=>error
|
111
112
|
# 5.2. The WWW-Authenticate Response Header Field
|
112
113
|
logger.info "HTTP authorization failed #{error.code}" if logger
|
113
114
|
return unauthorized(request, error)
|
@@ -154,30 +155,32 @@ module Rack
|
|
154
155
|
# application.
|
155
156
|
def request_authorization(request, logger)
|
156
157
|
state = request.GET["state"]
|
157
|
-
|
158
|
-
auth_request = self.class.get_auth_request(request.GET["authorization"]) rescue nil
|
159
|
-
if !auth_request || auth_request.revoked
|
160
|
-
logger.error "Invalid authorization request #{auth_request}" if logger
|
161
|
-
return bad_request("Invalid authorization request")
|
162
|
-
end
|
163
|
-
client = self.class.get_client(auth_request.client_id)
|
158
|
+
begin
|
164
159
|
|
165
|
-
|
160
|
+
if request.GET["authorization"]
|
161
|
+
auth_request = self.class.get_auth_request(request.GET["authorization"]) rescue nil
|
162
|
+
if !auth_request || auth_request.revoked
|
163
|
+
logger.error "Invalid authorization request #{auth_request}" if logger
|
164
|
+
return bad_request("Invalid authorization request")
|
165
|
+
end
|
166
|
+
response_type = auth_request.response_type # Needed for error handling
|
167
|
+
client = self.class.get_client(auth_request.client_id)
|
166
168
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
169
|
+
else
|
170
|
+
|
171
|
+
# 3. Obtaining End-User Authorization
|
172
|
+
begin
|
173
|
+
redirect_uri = Utils.parse_redirect_uri(request.GET["redirect_uri"])
|
174
|
+
rescue InvalidRequestError=>error
|
175
|
+
logger.error "Authorization request with invalid redirect_uri: #{request.GET["redirect_uri"]} #{error.message}" if logger
|
176
|
+
return bad_request(error.message)
|
177
|
+
end
|
174
178
|
|
175
|
-
begin
|
176
179
|
# 3. Obtaining End-User Authorization
|
180
|
+
response_type = request.GET["response_type"].to_s # Need this first, for error handling
|
177
181
|
client = get_client(request)
|
178
182
|
raise RedirectUriMismatchError unless client.redirect_uri.nil? || client.redirect_uri == redirect_uri.to_s
|
179
183
|
requested_scope = request.GET["scope"].to_s.split.uniq.join(" ")
|
180
|
-
response_type = request.GET["response_type"].to_s
|
181
184
|
raise UnsupportedResponseTypeError unless options.authorization_types.include?(response_type)
|
182
185
|
if scopes = options.scopes
|
183
186
|
allowed_scope = scopes.respond_to?(:all?) ? scopes : scopes.split
|
@@ -186,17 +189,24 @@ module Rack
|
|
186
189
|
# Create object to track authorization request and let application
|
187
190
|
# handle the rest.
|
188
191
|
auth_request = AuthRequest.create(client.id, requested_scope, redirect_uri.to_s, response_type, state)
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
+
request.env["oauth.authorization"] = auth_request.id.to_s
|
193
|
+
end
|
194
|
+
# Pass back to application, watch for 403 (deny!)
|
195
|
+
logger.info "Request #{auth_request.id}: Client #{client.display_name} requested #{auth_request.response_type} with scope #{auth_request.scope}" if logger
|
196
|
+
response = @app.call(request.env)
|
197
|
+
raise AccessDeniedError if response[0] == 403
|
198
|
+
return response
|
199
|
+
rescue OAuthError=>error
|
200
|
+
logger.error "Authorization request error: #{error.code} #{error.message}" if logger
|
201
|
+
params = { :error=>error.code, :error_description=>error.message, :state=>state }
|
202
|
+
if response_type == "token"
|
203
|
+
redirect_uri.fragment = Rack::Utils.build_query(params)
|
204
|
+
else # response type is code, or invalid
|
205
|
+
params = Rack::Utils.parse_query(redirect_uri.query).merge(params)
|
192
206
|
redirect_uri.query = Rack::Utils.build_query(params)
|
193
|
-
return redirect_to(redirect_uri)
|
194
207
|
end
|
208
|
+
return redirect_to(redirect_uri)
|
195
209
|
end
|
196
|
-
|
197
|
-
request.env["oauth.authorization"] = auth_request.id.to_s
|
198
|
-
logger.info "Request #{auth_request.id}: Client #{client.display_name} requested #{auth_request.response_type} with scope #{auth_request.scope}" if logger
|
199
|
-
return @app.call(request.env)
|
200
210
|
end
|
201
211
|
|
202
212
|
# Get here on completion of the authorization. Authorization response in
|
@@ -206,29 +216,33 @@ module Rack
|
|
206
216
|
status, headers, body = response
|
207
217
|
auth_request = self.class.get_auth_request(headers["oauth.authorization"])
|
208
218
|
redirect_uri = URI.parse(auth_request.redirect_uri)
|
209
|
-
if status ==
|
219
|
+
if status == 403
|
210
220
|
auth_request.deny!
|
211
221
|
else
|
212
222
|
auth_request.grant! headers["oauth.identity"]
|
213
223
|
end
|
214
224
|
# 3.1. Authorization Response
|
215
|
-
if auth_request.response_type == "code"
|
216
|
-
|
217
|
-
|
225
|
+
if auth_request.response_type == "code"
|
226
|
+
if auth_request.grant_code
|
227
|
+
logger.info "Request #{auth_request.id}: Client #{auth_request.client_id} granted access code #{auth_request.grant_code}" if logger
|
228
|
+
params = { :code=>auth_request.grant_code, :scope=>auth_request.scope, :state=>auth_request.state }
|
229
|
+
else
|
230
|
+
logger.info "Request #{auth_request.id}: Client #{auth_request.client_id} denied authorization" if logger
|
231
|
+
params = { :error=>:access_denied, :state=>auth_request.state }
|
232
|
+
end
|
218
233
|
params = Rack::Utils.parse_query(redirect_uri.query).merge(params)
|
219
234
|
redirect_uri.query = Rack::Utils.build_query(params)
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
235
|
+
else # response type if token
|
236
|
+
if auth_request.access_token
|
237
|
+
logger.info "Request #{auth_request.id}: Client #{auth_request.client_id} granted access token #{auth_request.access_token}" if logger
|
238
|
+
params = { :access_token=>auth_request.access_token, :scope=>auth_request.scope, :state=>auth_request.state }
|
239
|
+
else
|
240
|
+
logger.info "Request #{auth_request.id}: Client #{auth_request.client_id} denied authorization" if logger
|
241
|
+
params = { :error=>:access_denied, :state=>auth_request.state }
|
242
|
+
end
|
224
243
|
redirect_uri.fragment = Rack::Utils.build_query(params)
|
225
|
-
return redirect_to(redirect_uri)
|
226
|
-
else
|
227
|
-
logger.info "Request #{auth_request.id}: Client #{auth_request.client_id} denied authorization" if logger
|
228
|
-
params = Rack::Utils.parse_query(redirect_uri.query).merge(:error=>:access_denied, :state=>auth_request.state)
|
229
|
-
redirect_uri.query = Rack::Utils.build_query(params)
|
230
|
-
return redirect_to(redirect_uri)
|
231
244
|
end
|
245
|
+
return redirect_to(redirect_uri)
|
232
246
|
end
|
233
247
|
|
234
248
|
# 4. Obtaining an Access Token
|
@@ -264,7 +278,7 @@ module Rack
|
|
264
278
|
response[:scope] = access_token.scope unless access_token.scope.empty?
|
265
279
|
return [200, { "Content-Type"=>"application/json", "Cache-Control"=>"no-store" }, response.to_json]
|
266
280
|
# 4.3. Error Response
|
267
|
-
rescue
|
281
|
+
rescue OAuthError=>error
|
268
282
|
logger.error "Access token request error: #{error.code} #{error.message}" if logger
|
269
283
|
return unauthorized(request, error) if InvalidClientError === error && request.basic?
|
270
284
|
return [400, { "Content-Type"=>"application/json", "Cache-Control"=>"no-store" },
|
@@ -16,7 +16,7 @@ module Rack
|
|
16
16
|
def mount(klass, path)
|
17
17
|
@klass = klass
|
18
18
|
@path = path
|
19
|
-
@match = /^#{Regexp.escape(path)}
|
19
|
+
@match = /^#{Regexp.escape(path)}(\/.*|$)?/
|
20
20
|
end
|
21
21
|
|
22
22
|
attr_reader :klass, :path, :match
|
@@ -31,7 +31,7 @@ module Rack
|
|
31
31
|
path = env["PATH_INFO"].to_s
|
32
32
|
script_name = env['SCRIPT_NAME']
|
33
33
|
if path =~ self.class.match && rest = $1
|
34
|
-
env.merge! "SCRIPT_NAME"=>(script_name + self.class.path), "PATH_INFO"=>
|
34
|
+
env.merge! "SCRIPT_NAME"=>(script_name + self.class.path), "PATH_INFO"=>rest
|
35
35
|
return @admin.call(env)
|
36
36
|
else
|
37
37
|
return @pass.call(env)
|
@@ -63,6 +63,9 @@ module Rack
|
|
63
63
|
# Use this URL to authorize access to this console. If not set, goes to
|
64
64
|
# /oauth/authorize.
|
65
65
|
set :authorize, nil
|
66
|
+
# Map access token identity to URL on your application, by replacing
|
67
|
+
# "{id}" with the token identity (e.g. "http://example.com/user/{id}")
|
68
|
+
set :template_url, nil
|
66
69
|
|
67
70
|
# Number of tokens to return in each page.
|
68
71
|
set :tokens_per_page, 100
|
@@ -213,6 +216,7 @@ module Rack
|
|
213
216
|
def token_as_json(token)
|
214
217
|
{ :token=>token.token, :identity=>token.identity, :scope=>token.scope, :created=>token.created_at,
|
215
218
|
:expired=>token.expires_at, :revoked=>token.revoked,
|
219
|
+
:link=>settings.template_url && settings.template_url.gsub("{id}", token.identity),
|
216
220
|
:revoke=>"#{request.script_name}/api/token/#{token.token}/revoke" }
|
217
221
|
end
|
218
222
|
end
|