oauth2-provider 0.0.16
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/.gitignore +8 -0
- data/Gemfile +3 -0
- data/README.md +49 -0
- data/Rakefile +24 -0
- data/examples/client/Gemfile +6 -0
- data/examples/client/Gemfile.lock +20 -0
- data/examples/client/README +8 -0
- data/examples/client/app.rb +59 -0
- data/examples/client/config.ru +3 -0
- data/examples/client/views/home.haml +3 -0
- data/examples/client/views/response.haml +11 -0
- data/examples/rails3-example/.gitignore +4 -0
- data/examples/rails3-example/Gemfile +10 -0
- data/examples/rails3-example/Gemfile.lock +82 -0
- data/examples/rails3-example/README +9 -0
- data/examples/rails3-example/Rakefile +7 -0
- data/examples/rails3-example/app/controllers/account_controller.rb +14 -0
- data/examples/rails3-example/app/controllers/application_controller.rb +18 -0
- data/examples/rails3-example/app/controllers/authorization_controller.rb +18 -0
- data/examples/rails3-example/app/controllers/home_controller.rb +4 -0
- data/examples/rails3-example/app/controllers/session_controller.rb +24 -0
- data/examples/rails3-example/app/helpers/application_helper.rb +2 -0
- data/examples/rails3-example/app/models/account.rb +6 -0
- data/examples/rails3-example/app/views/authorization/new.html.erb +5 -0
- data/examples/rails3-example/app/views/home/show.html.erb +1 -0
- data/examples/rails3-example/app/views/layouts/application.html.erb +16 -0
- data/examples/rails3-example/app/views/session/new.html.erb +7 -0
- data/examples/rails3-example/config.ru +4 -0
- data/examples/rails3-example/config/application.rb +42 -0
- data/examples/rails3-example/config/boot.rb +6 -0
- data/examples/rails3-example/config/database.yml +22 -0
- data/examples/rails3-example/config/environment.rb +5 -0
- data/examples/rails3-example/config/environments/development.rb +26 -0
- data/examples/rails3-example/config/environments/production.rb +49 -0
- data/examples/rails3-example/config/environments/test.rb +35 -0
- data/examples/rails3-example/config/initializers/backtrace_silencers.rb +7 -0
- data/examples/rails3-example/config/initializers/inflections.rb +10 -0
- data/examples/rails3-example/config/initializers/mime_types.rb +5 -0
- data/examples/rails3-example/config/initializers/secret_token.rb +7 -0
- data/examples/rails3-example/config/initializers/session_store.rb +8 -0
- data/examples/rails3-example/config/locales/en.yml +5 -0
- data/examples/rails3-example/config/routes.rb +9 -0
- data/examples/rails3-example/db/migrate/20110508151935_add_account_table.rb +12 -0
- data/examples/rails3-example/db/migrate/20110508151948_add_oauth2_tables.rb +43 -0
- data/examples/rails3-example/db/schema.rb +52 -0
- data/examples/rails3-example/db/seeds.rb +11 -0
- data/examples/rails3-example/doc/README_FOR_APP +2 -0
- data/examples/rails3-example/lib/tasks/.gitkeep +0 -0
- data/examples/rails3-example/public/404.html +26 -0
- data/examples/rails3-example/public/422.html +26 -0
- data/examples/rails3-example/public/500.html +26 -0
- data/examples/rails3-example/public/favicon.ico +0 -0
- data/examples/rails3-example/public/images/rails.png +0 -0
- data/examples/rails3-example/public/robots.txt +5 -0
- data/examples/rails3-example/public/stylesheets/.gitkeep +0 -0
- data/examples/rails3-example/script/rails +6 -0
- data/lib/oauth2-provider.rb +3 -0
- data/lib/oauth2/provider.rb +39 -0
- data/lib/oauth2/provider/models.rb +40 -0
- data/lib/oauth2/provider/models/access_token.rb +54 -0
- data/lib/oauth2/provider/models/active_record.rb +30 -0
- data/lib/oauth2/provider/models/active_record/access_token.rb +13 -0
- data/lib/oauth2/provider/models/active_record/authorization.rb +16 -0
- data/lib/oauth2/provider/models/active_record/authorization_code.rb +13 -0
- data/lib/oauth2/provider/models/active_record/client.rb +15 -0
- data/lib/oauth2/provider/models/authorization.rb +40 -0
- data/lib/oauth2/provider/models/authorization_code.rb +27 -0
- data/lib/oauth2/provider/models/client.rb +28 -0
- data/lib/oauth2/provider/models/mongoid.rb +30 -0
- data/lib/oauth2/provider/models/mongoid/access_token.rb +40 -0
- data/lib/oauth2/provider/models/mongoid/authorization.rb +32 -0
- data/lib/oauth2/provider/models/mongoid/authorization_code.rb +43 -0
- data/lib/oauth2/provider/models/mongoid/client.rb +40 -0
- data/lib/oauth2/provider/rack.rb +11 -0
- data/lib/oauth2/provider/rack/access_token_handler.rb +103 -0
- data/lib/oauth2/provider/rack/authorization_code_request.rb +74 -0
- data/lib/oauth2/provider/rack/authorization_codes_support.rb +25 -0
- data/lib/oauth2/provider/rack/middleware.rb +28 -0
- data/lib/oauth2/provider/rack/resource_request.rb +91 -0
- data/lib/oauth2/provider/rack/responses.rb +34 -0
- data/lib/oauth2/provider/rails.rb +37 -0
- data/lib/oauth2/provider/rails/controller_authentication.rb +21 -0
- data/lib/oauth2/provider/random.rb +30 -0
- data/lib/oauth2/provider/version.rb +5 -0
- data/oauth2-provider.gemspec +35 -0
- data/spec/models/access_token_spec.rb +123 -0
- data/spec/models/authorization_code_spec.rb +115 -0
- data/spec/models/authorization_spec.rb +110 -0
- data/spec/models/client_spec.rb +75 -0
- data/spec/requests/access_tokens_controller_spec.rb +360 -0
- data/spec/requests/authentication_spec.rb +150 -0
- data/spec/requests/authorization_codes_support_spec.rb +157 -0
- data/spec/schema.rb +38 -0
- data/spec/set_backend_env_to_mongoid.rb +1 -0
- data/spec/spec_helper.rb +27 -0
- data/spec/support/activerecord_backend.rb +18 -0
- data/spec/support/factories.rb +56 -0
- data/spec/support/macros.rb +46 -0
- data/spec/support/mongoid_backend.rb +34 -0
- data/spec/support/rack.rb +32 -0
- metadata +373 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
class OAuth2::Provider::Models::Mongoid::AccessToken
|
|
2
|
+
module Behaviour
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
include ::Mongoid::Document
|
|
7
|
+
include OAuth2::Provider::Models::AccessToken
|
|
8
|
+
|
|
9
|
+
field :access_token
|
|
10
|
+
field :expires_at, :type => Time
|
|
11
|
+
field :refresh_token
|
|
12
|
+
|
|
13
|
+
referenced_in(:authorization,
|
|
14
|
+
:class_name => OAuth2::Provider.authorization_class_name,
|
|
15
|
+
:foreign_key => :oauth_authorization_id
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
referenced_in(:client,
|
|
19
|
+
:class_name => OAuth2::Provider.client_class_name,
|
|
20
|
+
:foreign_key => :oauth_client_id
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
before_save do
|
|
24
|
+
self.client ||= authorization.client
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module ClassMethods
|
|
29
|
+
def find_by_refresh_token(refresh_token)
|
|
30
|
+
where(:refresh_token => refresh_token).first
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def find_by_access_token(access_token)
|
|
34
|
+
where(:access_token => access_token).first
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
include Behaviour
|
|
40
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
class OAuth2::Provider::Models::Mongoid::Authorization
|
|
2
|
+
module Behaviour
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
include ::Mongoid::Document
|
|
7
|
+
include OAuth2::Provider::Models::Authorization
|
|
8
|
+
|
|
9
|
+
field :scope
|
|
10
|
+
field :expires_at, :type => Time
|
|
11
|
+
field :resource_owner_id
|
|
12
|
+
field :resource_owner_type
|
|
13
|
+
|
|
14
|
+
referenced_in(:client,
|
|
15
|
+
:class_name => OAuth2::Provider.client_class_name,
|
|
16
|
+
:foreign_key => :oauth_client_id
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
references_many(:access_tokens,
|
|
20
|
+
:class_name => OAuth2::Provider.access_token_class_name,
|
|
21
|
+
:foreign_key => :oauth_authorization_id
|
|
22
|
+
)
|
|
23
|
+
|
|
24
|
+
references_many(:authorization_codes,
|
|
25
|
+
:class_name => OAuth2::Provider.authorization_code_class_name,
|
|
26
|
+
:foreign_key => :oauth_authorization_id
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
include Behaviour
|
|
32
|
+
end
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
class OAuth2::Provider::Models::Mongoid::AuthorizationCode
|
|
2
|
+
module Behaviour
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
include ::Mongoid::Document
|
|
7
|
+
include OAuth2::Provider::Models::AuthorizationCode
|
|
8
|
+
|
|
9
|
+
field :code
|
|
10
|
+
field :expires_at, :type => Time
|
|
11
|
+
|
|
12
|
+
referenced_in(:authorization,
|
|
13
|
+
:class_name => OAuth2::Provider.authorization_class_name,
|
|
14
|
+
:foreign_key => :oauth_authorization_id
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
referenced_in(:client,
|
|
18
|
+
:class_name => OAuth2::Provider.client_class_name,
|
|
19
|
+
:foreign_key => :oauth_client_id
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
before_save do
|
|
23
|
+
self.client ||= authorization.client
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module ClassMethods
|
|
28
|
+
def find_by_code_and_redirect_uri(code, redirect_uri)
|
|
29
|
+
where(:code => code, :redirect_uri => redirect_uri).first
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def find_by_id(id)
|
|
33
|
+
where(:id => id).first
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def find_by_code(code)
|
|
37
|
+
where(:code => code).first
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
include Behaviour
|
|
43
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
class OAuth2::Provider::Models::Mongoid::Client
|
|
2
|
+
module Behaviour
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
include ::Mongoid::Document
|
|
7
|
+
include OAuth2::Provider::Models::Client
|
|
8
|
+
|
|
9
|
+
field :oauth_secret
|
|
10
|
+
field :oauth_identifier
|
|
11
|
+
|
|
12
|
+
references_many(:authorizations,
|
|
13
|
+
:class_name => OAuth2::Provider.authorization_class_name,
|
|
14
|
+
:foreign_key => :oauth_client_id
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
references_many(:access_tokens,
|
|
18
|
+
:class_name => OAuth2::Provider.access_token_class_name,
|
|
19
|
+
:foreign_key => :oauth_client_id
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
references_many(:authorization_codes,
|
|
23
|
+
:class_name => OAuth2::Provider.authorization_code_class_name,
|
|
24
|
+
:foreign_key => :oauth_client_id
|
|
25
|
+
)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
module ClassMethods
|
|
29
|
+
def find_by_oauth_identifier(identifier)
|
|
30
|
+
where(:oauth_identifier => identifier).first
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def find_by_oauth_identifier_and_oauth_secret(identifier, secret)
|
|
34
|
+
where(:oauth_identifier => identifier, :oauth_secret => secret).first
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
include Behaviour
|
|
40
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module OAuth2::Provider::Rack
|
|
2
|
+
autoload :AccessTokenHandler, 'oauth2/provider/rack/access_token_handler'
|
|
3
|
+
autoload :AuthenticationHandler, 'oauth2/provider/rack/authentication_handler'
|
|
4
|
+
autoload :AuthenticationMediator, 'oauth2/provider/rack/authentication_mediator'
|
|
5
|
+
autoload :AuthorizationCodeRequest, 'oauth2/provider/rack/authorization_code_request'
|
|
6
|
+
autoload :Middleware, 'oauth2/provider/rack/middleware'
|
|
7
|
+
autoload :Request, 'oauth2/provider/rack/request'
|
|
8
|
+
autoload :ResourceRequest, 'oauth2/provider/rack/resource_request'
|
|
9
|
+
autoload :Responses, 'oauth2/provider/rack/responses'
|
|
10
|
+
autoload :AuthorizationCodesSupport, 'oauth2/provider/rack/authorization_codes_support'
|
|
11
|
+
end
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
module OAuth2::Provider::Rack
|
|
2
|
+
class AccessTokenHandler
|
|
3
|
+
attr_reader :app, :env, :request
|
|
4
|
+
|
|
5
|
+
def initialize(app, env)
|
|
6
|
+
@app = app
|
|
7
|
+
@env = env
|
|
8
|
+
@request = env['oauth2']
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def process
|
|
12
|
+
if request.post?
|
|
13
|
+
block_unsupported_grant_types || block_invalid_clients || handle_grant_type
|
|
14
|
+
else
|
|
15
|
+
Responses.only_supported 'POST'
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def handle_grant_type
|
|
20
|
+
send grant_type_handler_method(request.params["grant_type"])
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def handle_password_grant_type
|
|
24
|
+
with_required_params 'username', 'password' do |username, password|
|
|
25
|
+
if resource_owner = OAuth2::Provider.resource_owner_class.authenticate_with_username_and_password(username, password)
|
|
26
|
+
token_response OAuth2::Provider.access_token_class.create!(
|
|
27
|
+
:authorization => OAuth2::Provider.authorization_class.create!(:resource_owner => resource_owner, :client => oauth_client)
|
|
28
|
+
)
|
|
29
|
+
else
|
|
30
|
+
Responses.json_error 'invalid_grant'
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def handle_authorization_code_grant_type
|
|
36
|
+
with_required_params 'code', 'redirect_uri' do |code, redirect_uri|
|
|
37
|
+
if token = oauth_client.authorization_codes.claim(code, redirect_uri)
|
|
38
|
+
token_response token
|
|
39
|
+
else
|
|
40
|
+
Responses.json_error 'invalid_grant'
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def handle_refresh_token_grant_type
|
|
46
|
+
with_required_params 'refresh_token' do |refresh_token|
|
|
47
|
+
if token = oauth_client.access_tokens.refresh_with(refresh_token)
|
|
48
|
+
token_response token
|
|
49
|
+
else
|
|
50
|
+
Responses.json_error 'invalid_grant'
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def with_required_params(*names, &block)
|
|
56
|
+
missing_params = names - request.params.keys
|
|
57
|
+
if missing_params.empty?
|
|
58
|
+
yield *request.params.values_at(*names)
|
|
59
|
+
else
|
|
60
|
+
if missing_params.size == 1
|
|
61
|
+
Responses.json_error 'invalid_request', :description => "missing '#{missing_params.join}' parameter"
|
|
62
|
+
else
|
|
63
|
+
describe_parameters = missing_params.map{|x| "'#{x}'"}.join(", ")
|
|
64
|
+
Responses.json_error 'invalid_request', :description => "missing #{describe_parameters} parameters"
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def token_response(token)
|
|
70
|
+
json = token.as_json.tap do |json|
|
|
71
|
+
json[:state] = request.params['state'] if request.params['state']
|
|
72
|
+
end
|
|
73
|
+
[200, {'Content-Type' => 'application/json', 'Cache-Control' => 'no-cache, no-store, max-age=0, must-revalidate'}, [ActiveSupport::JSON.encode(json)]]
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def block_unsupported_grant_types
|
|
77
|
+
with_required_params 'grant_type' do |grant_type|
|
|
78
|
+
unless respond_to?(grant_type_handler_method(grant_type), true)
|
|
79
|
+
Responses.json_error 'unsupported_grant_type'
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def block_invalid_clients
|
|
85
|
+
with_required_params 'grant_type', 'client_id', 'client_secret' do |grant_type, client_id, client_secret|
|
|
86
|
+
@oauth_client = OAuth2::Provider.client_class.find_by_oauth_identifier_and_oauth_secret(client_id, client_secret)
|
|
87
|
+
if @oauth_client.nil?
|
|
88
|
+
Responses.json_error 'invalid_client'
|
|
89
|
+
elsif !@oauth_client.allow_grant_type?(grant_type)
|
|
90
|
+
Responses.json_error 'unauthorized_client'
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def oauth_client
|
|
96
|
+
@oauth_client
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def grant_type_handler_method(grant_type)
|
|
100
|
+
"handle_#{grant_type}_grant_type"
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
module OAuth2::Provider::Rack
|
|
2
|
+
class AuthorizationCodeRequest
|
|
3
|
+
def initialize(env, params)
|
|
4
|
+
@env = env
|
|
5
|
+
@params = params
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def validate!
|
|
9
|
+
unless redirect_uri
|
|
10
|
+
throw_response [400, {}, ['No redirect_uri provided']]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
unless redirect_uri_valid?
|
|
14
|
+
throw_response [400, {}, ['Provided redirect_uri is invalid']]
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
unless client_id
|
|
18
|
+
throw_response Responses.redirect_with_error('invalid_request', redirect_uri)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
unless client
|
|
22
|
+
throw_response Responses.redirect_with_error('invalid_client', redirect_uri)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def grant!(resource_owner = nil, authorization_expires_at = nil)
|
|
27
|
+
grant = client.authorizations.create!(
|
|
28
|
+
:resource_owner => resource_owner,
|
|
29
|
+
:client => client,
|
|
30
|
+
:scope => scope,
|
|
31
|
+
:expires_at => authorization_expires_at
|
|
32
|
+
)
|
|
33
|
+
code = grant.authorization_codes.create! :redirect_uri => redirect_uri
|
|
34
|
+
throw_response Responses.redirect_with_code(code.code, redirect_uri)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def deny!
|
|
38
|
+
throw_response Responses.redirect_with_error('access_denied', redirect_uri)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def invalid_scope!
|
|
42
|
+
throw_response Responses.redirect_with_error('invalid_scope', redirect_uri)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def client_id
|
|
46
|
+
@params['client_id']
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def client
|
|
50
|
+
@client ||= OAuth2::Provider.client_class.from_param(client_id)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def redirect_uri
|
|
54
|
+
@params['redirect_uri']
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def redirect_uri_valid?
|
|
58
|
+
Addressable::URI.parse(redirect_uri)
|
|
59
|
+
rescue
|
|
60
|
+
nil
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def scope
|
|
64
|
+
@params['scope']
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def throw_response(response)
|
|
70
|
+
@env['oauth2.response'] = response
|
|
71
|
+
throw :oauth2
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
require 'addressable/uri'
|
|
2
|
+
|
|
3
|
+
module OAuth2::Provider::Rack::AuthorizationCodesSupport
|
|
4
|
+
protected
|
|
5
|
+
|
|
6
|
+
def oauth2_authorization_request
|
|
7
|
+
request.env['oauth2.authorization_request'] ||= OAuth2::Provider::Rack::AuthorizationCodeRequest.new(request.env, request.params)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def block_invalid_authorization_code_requests
|
|
11
|
+
oauth2_authorization_request.validate!
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def grant_authorization_code(resource_owner = nil, authorization_expires_at = nil)
|
|
15
|
+
oauth2_authorization_request.grant! resource_owner, authorization_expires_at
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def deny_authorization_code
|
|
19
|
+
oauth2_authorization_request.deny!
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def declare_oauth_scope_invalid
|
|
23
|
+
oauth2_authorization_request.invalid_scope!
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
module OAuth2::Provider::Rack
|
|
2
|
+
class Middleware
|
|
3
|
+
def initialize(app)
|
|
4
|
+
@app = app
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def call(env)
|
|
8
|
+
request = env['oauth2'] = ResourceRequest.new(env)
|
|
9
|
+
|
|
10
|
+
response = catch :oauth2 do
|
|
11
|
+
if request.path == "/oauth/access_token"
|
|
12
|
+
AccessTokenHandler.new(@app, env).process
|
|
13
|
+
else
|
|
14
|
+
@app.call(env)
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
thrown_response(env) || response
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def thrown_response(env)
|
|
22
|
+
if env['oauth2.response']
|
|
23
|
+
env['warden'] && env['warden'].custom_failure!
|
|
24
|
+
env['oauth2.response']
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require 'rack/auth/abstract/request'
|
|
2
|
+
|
|
3
|
+
module OAuth2::Provider::Rack
|
|
4
|
+
class ResourceRequest < Rack::Request
|
|
5
|
+
delegate :has_scope?, :to => :authorization
|
|
6
|
+
|
|
7
|
+
def token
|
|
8
|
+
token_from_param || token_from_header
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def has_token?
|
|
12
|
+
!token.nil?
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def token_from_param
|
|
16
|
+
params["oauth_token"]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def token_from_header
|
|
20
|
+
if @env[authorization_key] =~ /OAuth (.*)/
|
|
21
|
+
$1
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def authorization_key
|
|
26
|
+
@authorization_key ||= Rack::Auth::AbstractRequest::AUTHORIZATION_KEYS.detect do |key|
|
|
27
|
+
@env.has_key?(key)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def authenticate_request!(options, &block)
|
|
32
|
+
if authenticated?
|
|
33
|
+
if options[:scope].nil? || has_scope?(options[:scope])
|
|
34
|
+
yield
|
|
35
|
+
else
|
|
36
|
+
insufficient_scope!
|
|
37
|
+
end
|
|
38
|
+
else
|
|
39
|
+
authentication_required!
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def authorization
|
|
44
|
+
validate_token!
|
|
45
|
+
@authorization
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def authenticated?
|
|
49
|
+
authorization.present?
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def resource_owner
|
|
53
|
+
authorization && authorization.resource_owner
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def authentication_required!
|
|
57
|
+
throw_response Responses.unauthorized
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def insufficient_scope!
|
|
61
|
+
throw_response Responses.json_error('insufficient_scope', :status => 403)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def validate_token!
|
|
65
|
+
if has_token? && @token_validated.nil?
|
|
66
|
+
@token_validated = true
|
|
67
|
+
block_bad_request
|
|
68
|
+
block_invalid_token
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def block_bad_request
|
|
73
|
+
if token_from_param && token_from_header && (token_from_param != token_from_header)
|
|
74
|
+
throw_response Responses.json_error('invalid_request', :description => 'both authorization header and oauth_token provided, with conflicting tokens')
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def block_invalid_token
|
|
79
|
+
access_token = OAuth2::Provider.access_token_class.find_by_access_token(token)
|
|
80
|
+
@authorization = access_token.authorization if access_token
|
|
81
|
+
throw_response Responses.unauthorized('invalid_token') if access_token.nil? || access_token.expired?
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def throw_response(response)
|
|
87
|
+
@env['oauth2.response'] = response
|
|
88
|
+
throw :oauth2
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|