tpitale-rack-oauth2-server 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +202 -0
- data/Gemfile +16 -0
- data/MIT-LICENSE +21 -0
- data/README.rdoc +604 -0
- data/Rakefile +90 -0
- data/VERSION +1 -0
- data/bin/oauth2-server +206 -0
- data/lib/rack-oauth2-server.rb +4 -0
- data/lib/rack/oauth2/admin/css/screen.css +347 -0
- data/lib/rack/oauth2/admin/images/loading.gif +0 -0
- data/lib/rack/oauth2/admin/images/oauth-2.png +0 -0
- data/lib/rack/oauth2/admin/js/application.coffee +220 -0
- data/lib/rack/oauth2/admin/js/jquery.js +166 -0
- data/lib/rack/oauth2/admin/js/jquery.tmpl.js +414 -0
- data/lib/rack/oauth2/admin/js/protovis-r3.2.js +277 -0
- data/lib/rack/oauth2/admin/js/sammy.js +5 -0
- data/lib/rack/oauth2/admin/js/sammy.json.js +5 -0
- data/lib/rack/oauth2/admin/js/sammy.oauth2.js +142 -0
- data/lib/rack/oauth2/admin/js/sammy.storage.js +5 -0
- data/lib/rack/oauth2/admin/js/sammy.title.js +5 -0
- data/lib/rack/oauth2/admin/js/sammy.tmpl.js +5 -0
- data/lib/rack/oauth2/admin/js/underscore.js +722 -0
- data/lib/rack/oauth2/admin/views/client.tmpl +58 -0
- data/lib/rack/oauth2/admin/views/clients.tmpl +52 -0
- data/lib/rack/oauth2/admin/views/edit.tmpl +80 -0
- data/lib/rack/oauth2/admin/views/index.html +39 -0
- data/lib/rack/oauth2/admin/views/no_access.tmpl +4 -0
- data/lib/rack/oauth2/models.rb +27 -0
- data/lib/rack/oauth2/models/access_grant.rb +54 -0
- data/lib/rack/oauth2/models/access_token.rb +129 -0
- data/lib/rack/oauth2/models/auth_request.rb +61 -0
- data/lib/rack/oauth2/models/client.rb +93 -0
- data/lib/rack/oauth2/rails.rb +105 -0
- data/lib/rack/oauth2/server.rb +458 -0
- data/lib/rack/oauth2/server/admin.rb +250 -0
- data/lib/rack/oauth2/server/errors.rb +104 -0
- data/lib/rack/oauth2/server/helper.rb +147 -0
- data/lib/rack/oauth2/server/practice.rb +79 -0
- data/lib/rack/oauth2/server/railtie.rb +24 -0
- data/lib/rack/oauth2/server/utils.rb +30 -0
- data/lib/rack/oauth2/sinatra.rb +71 -0
- data/rack-oauth2-server.gemspec +24 -0
- data/rails/init.rb +11 -0
- data/test/admin/api_test.rb +228 -0
- data/test/admin/ui_test.rb +38 -0
- data/test/oauth/access_grant_test.rb +276 -0
- data/test/oauth/access_token_test.rb +311 -0
- data/test/oauth/authorization_test.rb +298 -0
- data/test/oauth/server_methods_test.rb +292 -0
- data/test/rails2/app/controllers/api_controller.rb +40 -0
- data/test/rails2/app/controllers/application_controller.rb +2 -0
- data/test/rails2/app/controllers/oauth_controller.rb +17 -0
- data/test/rails2/config/environment.rb +19 -0
- data/test/rails2/config/environments/test.rb +0 -0
- data/test/rails2/config/routes.rb +13 -0
- data/test/rails3/app/controllers/api_controller.rb +40 -0
- data/test/rails3/app/controllers/application_controller.rb +2 -0
- data/test/rails3/app/controllers/oauth_controller.rb +17 -0
- data/test/rails3/config/application.rb +19 -0
- data/test/rails3/config/environment.rb +2 -0
- data/test/rails3/config/routes.rb +12 -0
- data/test/setup.rb +120 -0
- data/test/sinatra/my_app.rb +69 -0
- metadata +145 -0
@@ -0,0 +1,250 @@
|
|
1
|
+
require "sinatra/base"
|
2
|
+
require "json"
|
3
|
+
require "rack/oauth2/server"
|
4
|
+
require "rack/oauth2/sinatra"
|
5
|
+
|
6
|
+
module Rack
|
7
|
+
module OAuth2
|
8
|
+
class Server
|
9
|
+
class Admin < ::Sinatra::Base
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# Rack module that mounts the specified class on the specified path,
|
14
|
+
# and passes all other request to the application.
|
15
|
+
class Mount
|
16
|
+
class << self
|
17
|
+
def mount(klass, path)
|
18
|
+
@klass = klass
|
19
|
+
@path = path
|
20
|
+
@match = /^#{Regexp.escape(path)}(\/.*|$)?/
|
21
|
+
end
|
22
|
+
|
23
|
+
attr_reader :klass, :path, :match
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(app)
|
27
|
+
@pass = app
|
28
|
+
@admin = self.class.klass.new
|
29
|
+
end
|
30
|
+
|
31
|
+
def call(env)
|
32
|
+
path = env["PATH_INFO"].to_s
|
33
|
+
script_name = env['SCRIPT_NAME']
|
34
|
+
if path =~ self.class.match && rest = $1
|
35
|
+
env.merge! "SCRIPT_NAME"=>(script_name + self.class.path), "PATH_INFO"=>rest
|
36
|
+
return @admin.call(env)
|
37
|
+
else
|
38
|
+
return @pass.call(env)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Returns Rack handle that mounts Admin on the specified path, and
|
44
|
+
# forwards all other requests back to the application.
|
45
|
+
#
|
46
|
+
# @param [String, nil] path The path to mount on, defaults to
|
47
|
+
# /oauth/admin
|
48
|
+
# @return [Object] Rack module
|
49
|
+
#
|
50
|
+
# @example To include Web admin in Rails 2.x app:
|
51
|
+
# config.middleware.use Rack::OAuth2::Server::Admin.mount
|
52
|
+
def mount(path = "/oauth/admin")
|
53
|
+
mount = Class.new(Mount)
|
54
|
+
mount.mount Admin, "/oauth/admin"
|
55
|
+
mount
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Client application identified, require to authenticate.
|
62
|
+
set :client_id, nil
|
63
|
+
# Client application secret, required to authenticate.
|
64
|
+
set :client_secret, nil
|
65
|
+
# Endpoint for requesing authorization, defaults to /oauth/admin.
|
66
|
+
set :authorize, nil
|
67
|
+
# Will map an access token identity into a URL in your application,
|
68
|
+
# using the substitution value "{id}", e.g.
|
69
|
+
# "http://example.com/users/#{id}")
|
70
|
+
set :template_url, nil
|
71
|
+
# Forces all requests to use HTTPS (true by default except in
|
72
|
+
# development mode).
|
73
|
+
set :force_ssl, !development?
|
74
|
+
# Common scope shown and added by default to new clients.
|
75
|
+
set :scope, []
|
76
|
+
|
77
|
+
|
78
|
+
set :logger, ::Rails.logger if defined?(::Rails)
|
79
|
+
# Number of tokens to return in each page.
|
80
|
+
set :tokens_per_page, 100
|
81
|
+
set :public, ::File.dirname(__FILE__) + "/../admin"
|
82
|
+
set :method_override, true
|
83
|
+
mime_type :js, "text/javascript"
|
84
|
+
mime_type :tmpl, "text/x-jquery-template"
|
85
|
+
|
86
|
+
register Rack::OAuth2::Sinatra
|
87
|
+
|
88
|
+
# Force HTTPS except for development environment.
|
89
|
+
before do
|
90
|
+
redirect request.url.sub(/^http:/, "https:") if settings.force_ssl && request.scheme != "https"
|
91
|
+
end
|
92
|
+
|
93
|
+
|
94
|
+
# -- Static content --
|
95
|
+
|
96
|
+
# It's a single-page app, this is that single page.
|
97
|
+
get "/" do
|
98
|
+
send_file settings.public + "/views/index.html"
|
99
|
+
end
|
100
|
+
|
101
|
+
# Service JavaScript, CSS and jQuery templates from the gem.
|
102
|
+
%w{js css views}.each do |path|
|
103
|
+
get "/#{path}/:name" do
|
104
|
+
send_file settings.public + "/#{path}/" + params[:name]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
# -- Getting an access token --
|
110
|
+
|
111
|
+
# To get an OAuth token, you need client ID and secret, two values we
|
112
|
+
# didn't pass on to the JavaScript code, so it has no way to request
|
113
|
+
# authorization directly. Instead, it redirects to this URL which in turn
|
114
|
+
# redirects to the authorization endpoint. This redirect does accept the
|
115
|
+
# state parameter, which will be returned after authorization.
|
116
|
+
get "/authorize" do
|
117
|
+
redirect_uri = "#{request.scheme}://#{request.host}:#{request.port}#{request.script_name}"
|
118
|
+
query = { :client_id=>settings.client_id, :client_secret=>settings.client_secret, :state=>params[:state],
|
119
|
+
:response_type=>"token", :scope=>"oauth-admin", :redirect_uri=>redirect_uri }
|
120
|
+
auth_url = settings.authorize || "#{request.scheme}://#{request.host}:#{request.port}/oauth/authorize"
|
121
|
+
redirect "#{auth_url}?#{Rack::Utils.build_query(query)}"
|
122
|
+
end
|
123
|
+
|
124
|
+
|
125
|
+
# -- API --
|
126
|
+
|
127
|
+
oauth_required "/api/clients", "/api/client/:id", "/api/client/:id/revoke", "/api/token/:token/revoke", :scope=>"oauth-admin"
|
128
|
+
|
129
|
+
get "/api/clients" do
|
130
|
+
content_type "application/json"
|
131
|
+
json = { :list=>Server::Client.all.map { |client| client_as_json(client) },
|
132
|
+
:scope=>Server::Utils.normalize_scope(settings.scope),
|
133
|
+
:history=>"#{request.script_name}/api/clients/history",
|
134
|
+
:tokens=>{ :total=>Server::AccessToken.count, :week=>Server::AccessToken.count(:days=>7),
|
135
|
+
:revoked=>Server::AccessToken.count(:days=>7, :revoked=>true) } }
|
136
|
+
json.to_json
|
137
|
+
end
|
138
|
+
|
139
|
+
# get "/api/clients/history" do
|
140
|
+
# content_type "application/json"
|
141
|
+
# { :data=>Server::AccessToken.historical }.to_json
|
142
|
+
# end
|
143
|
+
|
144
|
+
post "/api/clients" do
|
145
|
+
begin
|
146
|
+
client = Server::Client.create(validate_params(params))
|
147
|
+
redirect "#{request.script_name}/api/client/#{client.id}"
|
148
|
+
rescue
|
149
|
+
halt 400, $!.message
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
get "/api/client/:id" do
|
154
|
+
content_type "application/json"
|
155
|
+
client = Server::Client.find(params[:id])
|
156
|
+
json = client_as_json(client, true)
|
157
|
+
|
158
|
+
page = [params[:page].to_i, 1].max
|
159
|
+
offset = (page - 1) * settings.tokens_per_page
|
160
|
+
total = Server::AccessToken.count(:client_id=>client.id)
|
161
|
+
tokens = Server::AccessToken.for_client(params[:id], offset, settings.tokens_per_page)
|
162
|
+
json[:tokens] = { :list=>tokens.map { |token| token_as_json(token) } }
|
163
|
+
json[:tokens][:total] = total
|
164
|
+
json[:tokens][:page] = page
|
165
|
+
json[:tokens][:next] = "#{request.script_name}/client/#{params[:id]}?page=#{page + 1}" if total > page * settings.tokens_per_page
|
166
|
+
json[:tokens][:previous] = "#{request.script_name}/client/#{params[:id]}?page=#{page - 1}" if page > 1
|
167
|
+
json[:tokens][:total] = Server::AccessToken.count(:client_id=>client.id)
|
168
|
+
json[:tokens][:week] = Server::AccessToken.count(:client_id=>client.id, :days=>7)
|
169
|
+
json[:tokens][:revoked] = Server::AccessToken.count(:client_id=>client.id, :days=>7, :revoked=>true)
|
170
|
+
|
171
|
+
json.to_json
|
172
|
+
end
|
173
|
+
|
174
|
+
# get "/api/client/:id/history" do
|
175
|
+
# content_type "application/json"
|
176
|
+
# client = Server::Client.find(params[:id])
|
177
|
+
# { :data=>Server::AccessToken.historical(:client_id=>client.id) }.to_json
|
178
|
+
# end
|
179
|
+
|
180
|
+
put "/api/client/:id" do
|
181
|
+
client = Server::Client.find(params[:id])
|
182
|
+
begin
|
183
|
+
client.update validate_params(params)
|
184
|
+
redirect "#{request.script_name}/api/client/#{client.id}"
|
185
|
+
rescue
|
186
|
+
halt 400, $!.message
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
delete "/api/client/:id" do
|
191
|
+
Server::Client.delete(params[:id])
|
192
|
+
200
|
193
|
+
end
|
194
|
+
|
195
|
+
post "/api/client/:id/revoke" do
|
196
|
+
client = Server::Client.find(params[:id])
|
197
|
+
client.revoke!
|
198
|
+
200
|
199
|
+
end
|
200
|
+
|
201
|
+
post "/api/token/:token/revoke" do
|
202
|
+
token = Server::AccessToken.from_token(params[:token])
|
203
|
+
token.revoke!
|
204
|
+
200
|
205
|
+
end
|
206
|
+
|
207
|
+
helpers do
|
208
|
+
def validate_params(params)
|
209
|
+
display_name = params[:displayName].to_s.strip
|
210
|
+
halt 400, "Missing display name" if display_name.empty?
|
211
|
+
link = URI.parse(params[:link].to_s.strip).normalize rescue nil
|
212
|
+
halt 400, "Link is not a URL (must be http://....)" unless link
|
213
|
+
halt 400, "Link must be an absolute URL with HTTP/S scheme" unless link.absolute? && %{http https}.include?(link.scheme)
|
214
|
+
redirect_uri = URI.parse(params[:redirectUri].to_s.strip).normalize rescue nil
|
215
|
+
halt 400, "Redirect URL is not a URL (must be http://....)" unless redirect_uri
|
216
|
+
halt 400, "Redirect URL must be an absolute URL with HTTP/S scheme" unless
|
217
|
+
redirect_uri.absolute? && %{http https}.include?(redirect_uri.scheme)
|
218
|
+
unless params[:imageUrl].nil? || params[:imageUrl].to_s.empty?
|
219
|
+
image_url = URI.parse(params[:imageUrl].to_s.strip).normalize rescue nil
|
220
|
+
halt 400, "Image URL must be an absolute URL with HTTP/S scheme" unless
|
221
|
+
image_url.absolute? && %{http https}.include?(image_url.scheme)
|
222
|
+
end
|
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] }
|
226
|
+
end
|
227
|
+
|
228
|
+
def client_as_json(client, with_stats = false)
|
229
|
+
{ "id"=>client.id.to_s, "secret"=>client.secret, :redirectUri=>client.redirect_uri,
|
230
|
+
:displayName=>client.display_name, :link=>client.link, :imageUrl=>client.image_url,
|
231
|
+
:notes=>client.notes, :scope=>client.scope,
|
232
|
+
:url=>"#{request.script_name}/api/client/#{client.id}",
|
233
|
+
:revoke=>"#{request.script_name}/api/client/#{client.id}/revoke",
|
234
|
+
:history=>"#{request.script_name}/api/client/#{client.id}/history",
|
235
|
+
:created=>client.created_at, :revoked=>client.revoked }
|
236
|
+
end
|
237
|
+
|
238
|
+
def token_as_json(token)
|
239
|
+
{ :token=>token.token, :identity=>token.identity, :scope=>token.scope, :created=>token.created_at,
|
240
|
+
:expired=>token.expires_at, :revoked=>token.revoked,
|
241
|
+
:link=>settings.template_url && settings.template_url.gsub("{id}", token.identity),
|
242
|
+
:last_access=>token.last_access,
|
243
|
+
:revoke=>"#{request.script_name}/api/token/#{token.token}/revoke" }
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
end
|
248
|
+
end
|
249
|
+
end
|
250
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
module Rack
|
2
|
+
module OAuth2
|
3
|
+
class Server
|
4
|
+
|
5
|
+
# Base class for all OAuth errors. These map to error codes in the spec.
|
6
|
+
class OAuthError < StandardError
|
7
|
+
|
8
|
+
def initialize(code, message)
|
9
|
+
super message
|
10
|
+
@code = code.to_sym
|
11
|
+
end
|
12
|
+
|
13
|
+
# The OAuth error code.
|
14
|
+
attr_reader :code
|
15
|
+
end
|
16
|
+
|
17
|
+
# The end-user or authorization server denied the request.
|
18
|
+
class AccessDeniedError < OAuthError
|
19
|
+
def initialize
|
20
|
+
super :access_denied, "You are now allowed to access this resource."
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# Access token expired, client expected to request new one using refresh
|
25
|
+
# token.
|
26
|
+
class ExpiredTokenError < OAuthError
|
27
|
+
def initialize
|
28
|
+
super :expired_token, "The access token has expired."
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# The client identifier provided is invalid, the client failed to
|
33
|
+
# authenticate, the client did not include its credentials, provided
|
34
|
+
# multiple client credentials, or used unsupported credentials type.
|
35
|
+
class InvalidClientError < OAuthError
|
36
|
+
def initialize
|
37
|
+
super :invalid_client, "Client ID and client secret do not match."
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# The provided access grant is invalid, expired, or revoked (e.g. invalid
|
42
|
+
# assertion, expired authorization token, bad end-user password credentials,
|
43
|
+
# or mismatching authorization code and redirection URI).
|
44
|
+
class InvalidGrantError < OAuthError
|
45
|
+
def initialize(message = nil)
|
46
|
+
super :invalid_grant, message || "This access grant is no longer valid."
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Invalid_request, the request is missing a required parameter, includes an
|
51
|
+
# unsupported parameter or parameter value, repeats the same parameter, uses
|
52
|
+
# more than one method for including an access token, or is otherwise
|
53
|
+
# malformed.
|
54
|
+
class InvalidRequestError < OAuthError
|
55
|
+
def initialize(message)
|
56
|
+
super :invalid_request, message || "The request has the wrong parameters."
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# The requested scope is invalid, unknown, or malformed.
|
61
|
+
class InvalidScopeError < OAuthError
|
62
|
+
def initialize
|
63
|
+
super :invalid_scope, "The requested scope is not supported."
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Access token expired, client cannot refresh and needs new authorization.
|
68
|
+
class InvalidTokenError < OAuthError
|
69
|
+
def initialize
|
70
|
+
super :invalid_token, "The access token is no longer valid."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# The redirection URI provided does not match a pre-registered value.
|
75
|
+
class RedirectUriMismatchError < OAuthError
|
76
|
+
def initialize
|
77
|
+
super :redirect_uri_mismatch, "Must use the same redirect URI you registered with us."
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# The authenticated client is not authorized to use the access grant type provided.
|
82
|
+
class UnauthorizedClientError < OAuthError
|
83
|
+
def initialize
|
84
|
+
super :unauthorized_client, "You are not allowed to access this resource."
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
# This access grant type is not supported by this server.
|
89
|
+
class UnsupportedGrantType < OAuthError
|
90
|
+
def initialize
|
91
|
+
super :unsupported_grant_type, "This access grant type is not supported by this server."
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# The requested response type is not supported by the authorization server.
|
96
|
+
class UnsupportedResponseTypeError < OAuthError
|
97
|
+
def initialize
|
98
|
+
super :unsupported_response_type, "The requested response type is not supported."
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,147 @@
|
|
1
|
+
module Rack
|
2
|
+
module OAuth2
|
3
|
+
class Server
|
4
|
+
|
5
|
+
# Helper methods that provide access to the OAuth state during the
|
6
|
+
# authorization flow, and from authenticated requests. For example:
|
7
|
+
#
|
8
|
+
# def show
|
9
|
+
# logger.info "#{oauth.client.display_name} accessing #{oauth.scope}"
|
10
|
+
# end
|
11
|
+
class Helper
|
12
|
+
|
13
|
+
def initialize(request, response)
|
14
|
+
@request, @response = request, response
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns the access token. Only applies if client authenticated.
|
18
|
+
#
|
19
|
+
# @return [String, nil] Access token, if authenticated
|
20
|
+
def access_token
|
21
|
+
@access_token ||= @request.env["oauth.access_token"]
|
22
|
+
end
|
23
|
+
|
24
|
+
# True if client authenticated.
|
25
|
+
#
|
26
|
+
# @return [true, false] True if authenticated
|
27
|
+
def authenticated?
|
28
|
+
!!access_token
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the authenticated identity. Only applies if client
|
32
|
+
# authenticated.
|
33
|
+
#
|
34
|
+
# @return [String, nil] Identity, if authenticated
|
35
|
+
def identity
|
36
|
+
@identity ||= @request.env["oauth.identity"]
|
37
|
+
end
|
38
|
+
|
39
|
+
# Returns the Client object associated with this request. Available if
|
40
|
+
# client authenticated, or while processing authorization request.
|
41
|
+
#
|
42
|
+
# @return [Client, nil] Client if authenticated, or while authorizing
|
43
|
+
def client
|
44
|
+
if access_token
|
45
|
+
@client ||= Server.get_access_token(access_token).client
|
46
|
+
elsif authorization
|
47
|
+
@client ||= Server.get_auth_request(authorization).client
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Returns scope associated with this request. Available if client
|
52
|
+
# authenticated, or while processing authorization request.
|
53
|
+
#
|
54
|
+
# @return [Array<String>, nil] Scope names, e.g ["read, "write"]
|
55
|
+
def scope
|
56
|
+
if access_token
|
57
|
+
@scope ||= Server.get_access_token(access_token).scope
|
58
|
+
elsif authorization
|
59
|
+
@scope ||= Server.get_auth_request(authorization).scope
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Rejects the request and returns 401 (Unauthorized). You can just
|
64
|
+
# return 401, but this also sets the WWW-Authenticate header the right
|
65
|
+
# value.
|
66
|
+
#
|
67
|
+
# @return 401
|
68
|
+
def no_access!
|
69
|
+
@response["oauth.no_access"] = "true"
|
70
|
+
@response.status = 401
|
71
|
+
end
|
72
|
+
|
73
|
+
# Rejects the request and returns 403 (Forbidden). You can just
|
74
|
+
# return 403, but this also sets the WWW-Authenticate header the right
|
75
|
+
# value. Indicates which scope the client needs to make this request.
|
76
|
+
#
|
77
|
+
# @param [String] scope The missing scope, e.g. "read"
|
78
|
+
# @return 403
|
79
|
+
def no_scope!(scope)
|
80
|
+
@response["oauth.no_scope"] = scope.to_s
|
81
|
+
@response.status = 403
|
82
|
+
end
|
83
|
+
|
84
|
+
# Returns the authorization request handle. Available when starting an
|
85
|
+
# authorization request (i.e. /oauth/authorize).
|
86
|
+
#
|
87
|
+
# @return [String] Authorization handle
|
88
|
+
def authorization
|
89
|
+
@request_id ||= @request.env["oauth.authorization"] || @request.params["authorization"]
|
90
|
+
end
|
91
|
+
|
92
|
+
# Sets the authorization request handle. Use this during the
|
93
|
+
# authorization flow.
|
94
|
+
#
|
95
|
+
# @param [String] authorization handle
|
96
|
+
def authorization=(authorization)
|
97
|
+
@scope, @client = nil
|
98
|
+
@request_id = authorization
|
99
|
+
end
|
100
|
+
|
101
|
+
# Grant authorization request. Call this at the end of the authorization
|
102
|
+
# flow to signal that the user has authorized the client to access the
|
103
|
+
# specified identity. Don't render anything else. Argument required if
|
104
|
+
# authorization handle is not passed in the request parameter
|
105
|
+
# +authorization+.
|
106
|
+
#
|
107
|
+
# @param [String, nil] authorization Authorization handle
|
108
|
+
# @param [String] identity Identity string
|
109
|
+
# @return 200
|
110
|
+
def grant!(auth, identity = nil)
|
111
|
+
auth, identity = authorization, auth unless identity
|
112
|
+
@response["oauth.authorization"] = auth.to_s
|
113
|
+
@response["oauth.identity"] = identity.to_s
|
114
|
+
@response.status = 200
|
115
|
+
end
|
116
|
+
|
117
|
+
# Deny authorization request. Call this at the end of the authorization
|
118
|
+
# flow to signal that the user has not authorized the client. Don't
|
119
|
+
# render anything else. Argument required if authorization handle is not
|
120
|
+
# passed in the request parameter +authorization+.
|
121
|
+
#
|
122
|
+
# @param [String, nil] auth Authorization handle
|
123
|
+
# @return 401
|
124
|
+
def deny!(auth = nil)
|
125
|
+
auth ||= authorization
|
126
|
+
@response["oauth.authorization"] = auth.to_s
|
127
|
+
@response.status = 403
|
128
|
+
end
|
129
|
+
|
130
|
+
# Returns all access tokens associated with this identity.
|
131
|
+
#
|
132
|
+
# @param [String] identity Identity string
|
133
|
+
# @return [Array<AccessToken>]
|
134
|
+
def list_access_tokens(identity)
|
135
|
+
Rack::OAuth2::Server.list_access_tokens(identity)
|
136
|
+
end
|
137
|
+
|
138
|
+
def inspect
|
139
|
+
authorization ? "Authorization request for #{Utils.normalize_scope(scope).join(",")} on behalf of #{client.display_name}" :
|
140
|
+
authenticated? ? "Authenticated as #{identity}" : nil
|
141
|
+
end
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|