doorkeeper 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.hound.yml +4 -1
- data/CHANGELOG.md +18 -0
- data/README.md +2 -1
- data/app/controllers/doorkeeper/application_metal_controller.rb +16 -0
- data/app/controllers/doorkeeper/applications_controller.rb +0 -6
- data/app/controllers/doorkeeper/authorizations_controller.rb +14 -15
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +10 -8
- data/app/controllers/doorkeeper/token_info_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +3 -11
- data/app/validators/redirect_uri_validator.rb +0 -1
- data/config/locales/en.yml +0 -3
- data/doorkeeper.gemspec +1 -0
- data/lib/doorkeeper.rb +1 -0
- data/lib/doorkeeper/config.rb +5 -5
- data/lib/doorkeeper/doorkeeper_for.rb +7 -17
- data/lib/doorkeeper/helpers/controller.rb +11 -8
- data/lib/doorkeeper/helpers/filter.rb +35 -13
- data/lib/doorkeeper/models/access_grant.rb +5 -5
- data/lib/doorkeeper/models/access_token.rb +9 -5
- data/lib/doorkeeper/models/active_record/access_grant.rb +1 -1
- data/lib/doorkeeper/models/active_record/access_token.rb +1 -1
- data/lib/doorkeeper/models/active_record/application.rb +3 -3
- data/lib/doorkeeper/models/application.rb +1 -1
- data/lib/doorkeeper/models/mongo_mapper/access_grant.rb +0 -3
- data/lib/doorkeeper/models/mongo_mapper/access_token.rb +0 -3
- data/lib/doorkeeper/models/mongoid2/access_grant.rb +1 -3
- data/lib/doorkeeper/models/mongoid2/access_token.rb +1 -3
- data/lib/doorkeeper/models/mongoid3_4/access_grant.rb +2 -4
- data/lib/doorkeeper/models/mongoid3_4/access_token.rb +2 -4
- data/lib/doorkeeper/models/revocable.rb +1 -1
- data/lib/doorkeeper/models/scopes.rb +6 -2
- data/lib/doorkeeper/oauth/authorization/code.rb +4 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +8 -0
- data/lib/doorkeeper/oauth/authorization_code_request.rb +2 -2
- data/lib/doorkeeper/oauth/client.rb +2 -2
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +2 -2
- data/lib/doorkeeper/oauth/client_credentials_request.rb +3 -12
- data/lib/doorkeeper/oauth/code_response.rb +3 -4
- data/lib/doorkeeper/oauth/error_response.rb +3 -3
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +29 -0
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
- data/lib/doorkeeper/oauth/password_access_token_request.rb +5 -5
- data/lib/doorkeeper/oauth/pre_authorization.rb +2 -2
- data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -6
- data/lib/doorkeeper/oauth/request_concern.rb +2 -2
- data/lib/doorkeeper/oauth/token.rb +1 -1
- data/lib/doorkeeper/server.rb +2 -2
- data/lib/doorkeeper/version.rb +1 -1
- data/spec/controllers/authorizations_controller_spec.rb +46 -0
- data/spec/controllers/protected_resources_controller_spec.rb +13 -6
- data/spec/lib/models/revocable_spec.rb +1 -1
- data/spec/lib/models/scopes_spec.rb +11 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +5 -0
- data/spec/lib/oauth/forbidden_token_response_spec.rb +23 -0
- data/spec/models/doorkeeper/access_token_spec.rb +30 -0
- data/spec/requests/flows/refresh_token_spec.rb +2 -2
- data/spec/requests/protected_resources/private_api_spec.rb +5 -5
- data/spec/support/shared/controllers_shared_context.rb +2 -2
- data/spec/validators/redirect_uri_validator_spec.rb +1 -2
- metadata +19 -4
- data/lib/doorkeeper/models/mongo_mapper/revocable.rb +0 -15
- data/lib/doorkeeper/models/mongoid/revocable.rb +0 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2effc07ab96a92f6ce4bf22833e99079c1309b01
|
4
|
+
data.tar.gz: b2d4793140041f6a71b3eddc5ce74c61bca8de8e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 55e4089805323ebc56efff0306872bfea4b19b814131632c62885975aebe452338612ced9f3137e20500b9dfa298bec2f8b3de7b385d3e1be16df804a0c8ccb7
|
7
|
+
data.tar.gz: 50b4631d1e4f14557aba937edb12d225e2a704d80142b3e3e487d8f36a5c097a89bfdd871bda1012e690324c3833605ca51c23820aa47a5b7baba242bf782287
|
data/.hound.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,23 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## master
|
4
|
+
|
5
|
+
## 1.4.0
|
6
|
+
|
7
|
+
- internals
|
8
|
+
- [#427] Adds specs expectations.
|
9
|
+
- [#428] Error response refactor.
|
10
|
+
- [#417] Moves token validation into Access Token class.
|
11
|
+
- [#439] Removes redundant module includes.
|
12
|
+
- [#443] TokensController and TokenInfoController inherit from ActionController::Metal
|
13
|
+
- bug
|
14
|
+
- [#418] fixes #243, requests with insufficient scope now respond 403 instead
|
15
|
+
of 401. (API change)
|
16
|
+
- [#438] fixes #398, native redirect for implicit token grant bug.
|
17
|
+
- [#440] namespace fixes
|
18
|
+
- enhancements
|
19
|
+
- [#432] Keeps query parameters
|
20
|
+
|
3
21
|
## 1.3.1
|
4
22
|
|
5
23
|
- enhancements
|
data/README.md
CHANGED
@@ -20,7 +20,8 @@ Doorkeeper is a gem that makes it easy to introduce OAuth 2 provider functionali
|
|
20
20
|
- [Routes](#routes)
|
21
21
|
- [Authenticating](#authenticating)
|
22
22
|
- [Protecting resources with OAuth (a.k.a your API endpoint)](#protecting-resources-with-oauth-aka-your-api-endpoint)
|
23
|
-
- [ActionController::Metal integration
|
23
|
+
- [ActionController::Metal integration](#actioncontrollermetal-integration)
|
24
|
+
- [Route Constraints and other integrations](#route-constraints-and-other-integrations)
|
24
25
|
- [Access Token Scopes](#access-token-scopes)
|
25
26
|
- [Authenticated resource owner](#authenticated-resource-owner)
|
26
27
|
- [Applications list](#applications-list)
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Doorkeeper
|
2
|
+
class ApplicationMetalController < ActionController::Metal
|
3
|
+
MODULES = [
|
4
|
+
ActionController::RackDelegation,
|
5
|
+
ActionController::Instrumentation,
|
6
|
+
AbstractController::Rendering,
|
7
|
+
ActionController::Rendering,
|
8
|
+
ActionController::Renderers::All,
|
9
|
+
Helpers::Controller
|
10
|
+
]
|
11
|
+
|
12
|
+
MODULES.each do |mod|
|
13
|
+
include mod
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,10 +1,10 @@
|
|
1
1
|
module Doorkeeper
|
2
|
-
class AuthorizationsController <
|
2
|
+
class AuthorizationsController < Doorkeeper::ApplicationController
|
3
3
|
before_filter :authenticate_resource_owner!
|
4
4
|
|
5
5
|
def new
|
6
6
|
if pre_auth.authorizable?
|
7
|
-
if
|
7
|
+
if matching_token? || skip_authorization?
|
8
8
|
auth = authorization.authorize
|
9
9
|
redirect_to auth.redirect_uri
|
10
10
|
else
|
@@ -15,23 +15,24 @@ module Doorkeeper
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def show
|
19
|
-
end
|
20
|
-
|
21
18
|
# TODO: Handle raise invalid authorization
|
22
19
|
def create
|
23
|
-
|
24
|
-
|
25
|
-
if auth.redirectable?
|
26
|
-
redirect_to auth.redirect_uri
|
27
|
-
else
|
28
|
-
render json: auth.body, status: auth.status
|
29
|
-
end
|
20
|
+
redirect_or_render authorization.authorize
|
30
21
|
end
|
31
22
|
|
32
23
|
def destroy
|
33
|
-
|
24
|
+
redirect_or_render authorization.deny
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
34
28
|
|
29
|
+
def matching_token?
|
30
|
+
AccessToken.matching_token_for pre_auth.client,
|
31
|
+
current_resource_owner.id,
|
32
|
+
pre_auth.scopes
|
33
|
+
end
|
34
|
+
|
35
|
+
def redirect_or_render(auth)
|
35
36
|
if auth.redirectable?
|
36
37
|
redirect_to auth.redirect_uri
|
37
38
|
else
|
@@ -39,8 +40,6 @@ module Doorkeeper
|
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
42
|
-
private
|
43
|
-
|
44
43
|
def pre_auth
|
45
44
|
@pre_auth ||= OAuth::PreAuthorization.new(Doorkeeper.configuration, server.client_via_uid, params)
|
46
45
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
module Doorkeeper
|
2
|
+
class AuthorizedApplicationsController < Doorkeeper::ApplicationController
|
3
|
+
before_filter :authenticate_resource_owner!
|
3
4
|
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
def index
|
6
|
+
@applications = Application.authorized_for(current_resource_owner)
|
7
|
+
end
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def destroy
|
10
|
+
AccessToken.revoke_all_for params[:id], current_resource_owner
|
11
|
+
redirect_to oauth_authorized_applications_url, notice: I18n.t(:notice, scope: [:doorkeeper, :flash, :authorized_applications, :destroy])
|
12
|
+
end
|
11
13
|
end
|
12
14
|
end
|
@@ -1,9 +1,5 @@
|
|
1
1
|
module Doorkeeper
|
2
|
-
class TokensController <
|
3
|
-
include Helpers::Controller
|
4
|
-
include ActionController::RackDelegation
|
5
|
-
include ActionController::Instrumentation
|
6
|
-
|
2
|
+
class TokensController < Doorkeeper::ApplicationMetalController
|
7
3
|
def create
|
8
4
|
response = strategy.authorize
|
9
5
|
self.headers.merge! response.headers
|
@@ -13,11 +9,7 @@ module Doorkeeper
|
|
13
9
|
handle_token_exception e
|
14
10
|
end
|
15
11
|
|
16
|
-
|
17
|
-
# RFC 7009 - OAuth 2.0 Token Revocation #
|
18
|
-
# #
|
19
|
-
# http://tools.ietf.org/html/rfc7009 #
|
20
|
-
#############################################
|
12
|
+
# OAuth 2.0 Token Revocation - http://tools.ietf.org/html/rfc7009
|
21
13
|
def revoke
|
22
14
|
# The authorization server first validates the client credentials
|
23
15
|
if doorkeeper_token && doorkeeper_token.accessible?
|
@@ -33,7 +25,7 @@ module Doorkeeper
|
|
33
25
|
private
|
34
26
|
|
35
27
|
def revoke_token(token)
|
36
|
-
token =
|
28
|
+
token = AccessToken.authenticate(token) || AccessToken.by_refresh_token(token)
|
37
29
|
if token && doorkeeper_token.same_credential?(token)
|
38
30
|
token.revoke
|
39
31
|
true
|
@@ -14,7 +14,6 @@ class RedirectUriValidator < ActiveModel::EachValidator
|
|
14
14
|
return if native_redirect_uri?(uri)
|
15
15
|
record.errors.add(attribute, :fragment_present) unless uri.fragment.nil?
|
16
16
|
record.errors.add(attribute, :relative_uri) if uri.scheme.nil? || uri.host.nil?
|
17
|
-
record.errors.add(attribute, :has_query_parameter) unless uri.query.nil?
|
18
17
|
end
|
19
18
|
end
|
20
19
|
rescue URI::InvalidURIError
|
data/config/locales/en.yml
CHANGED
@@ -6,7 +6,6 @@ en:
|
|
6
6
|
attributes:
|
7
7
|
redirect_uri:
|
8
8
|
fragment_present: 'cannot contain a fragment.'
|
9
|
-
has_query_parameter: 'cannot contain a query parameter.'
|
10
9
|
invalid_uri: 'must be a valid URI.'
|
11
10
|
relative_uri: 'must be an absolute URI.'
|
12
11
|
mongoid:
|
@@ -16,7 +15,6 @@ en:
|
|
16
15
|
attributes:
|
17
16
|
redirect_uri:
|
18
17
|
fragment_present: 'cannot contain a fragment.'
|
19
|
-
has_query_parameter: 'cannot contain a query parameter.'
|
20
18
|
invalid_uri: 'must be a valid URI.'
|
21
19
|
relative_uri: 'must be an absolute URI.'
|
22
20
|
mongo_mapper:
|
@@ -26,7 +24,6 @@ en:
|
|
26
24
|
attributes:
|
27
25
|
redirect_uri:
|
28
26
|
fragment_present: 'cannot contain a fragment.'
|
29
|
-
has_query_parameter: 'cannot contain a query parameter.'
|
30
27
|
invalid_uri: 'must be a valid URI.'
|
31
28
|
relative_uri: 'must be an absolute URI.'
|
32
29
|
doorkeeper:
|
data/doorkeeper.gemspec
CHANGED
@@ -27,4 +27,5 @@ Gem::Specification.new do |s|
|
|
27
27
|
s.add_development_dependency "database_cleaner", "~> 1.3.0"
|
28
28
|
s.add_development_dependency "rspec-activemodel-mocks", "~> 1.0.0"
|
29
29
|
s.add_development_dependency "bcrypt-ruby", "~> 3.0.1"
|
30
|
+
s.add_development_dependency "pry", "~> 0.10.0"
|
30
31
|
end
|
data/lib/doorkeeper.rb
CHANGED
@@ -31,6 +31,7 @@ require 'doorkeeper/oauth/token_request'
|
|
31
31
|
require 'doorkeeper/oauth/client'
|
32
32
|
require 'doorkeeper/oauth/token'
|
33
33
|
require 'doorkeeper/oauth/invalid_token_response'
|
34
|
+
require 'doorkeeper/oauth/forbidden_token_response'
|
34
35
|
|
35
36
|
require 'doorkeeper/models/scopes'
|
36
37
|
require 'doorkeeper/models/expirable'
|
data/lib/doorkeeper/config.rb
CHANGED
@@ -35,7 +35,7 @@ module Doorkeeper
|
|
35
35
|
|
36
36
|
def self.setup_application_owner
|
37
37
|
require File.join(File.dirname(__FILE__), 'models', 'ownership')
|
38
|
-
|
38
|
+
Application.send :include, Models::Ownership
|
39
39
|
end
|
40
40
|
|
41
41
|
class Config
|
@@ -59,11 +59,11 @@ module Doorkeeper
|
|
59
59
|
end
|
60
60
|
|
61
61
|
def default_scopes(*scopes)
|
62
|
-
@config.instance_variable_set('@default_scopes',
|
62
|
+
@config.instance_variable_set('@default_scopes', OAuth::Scopes.from_array(scopes))
|
63
63
|
end
|
64
64
|
|
65
65
|
def optional_scopes(*scopes)
|
66
|
-
@config.instance_variable_set('@optional_scopes',
|
66
|
+
@config.instance_variable_set('@optional_scopes', OAuth::Scopes.from_array(scopes))
|
67
67
|
end
|
68
68
|
|
69
69
|
def client_credentials(*methods)
|
@@ -198,11 +198,11 @@ module Doorkeeper
|
|
198
198
|
end
|
199
199
|
|
200
200
|
def default_scopes
|
201
|
-
@default_scopes ||=
|
201
|
+
@default_scopes ||= OAuth::Scopes.new
|
202
202
|
end
|
203
203
|
|
204
204
|
def optional_scopes
|
205
|
-
@optional_scopes ||=
|
205
|
+
@optional_scopes ||= OAuth::Scopes.new
|
206
206
|
end
|
207
207
|
|
208
208
|
def scopes
|
@@ -1,51 +1,41 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
class InvalidSyntax < StandardError; end
|
3
3
|
class DoorkeeperFor
|
4
|
+
attr_reader :scopes
|
5
|
+
|
4
6
|
def initialize(options)
|
5
7
|
options ||= {}
|
6
8
|
fail InvalidSyntax unless options.is_a? Hash
|
7
9
|
@filter_options = {}
|
8
10
|
|
9
11
|
options.each do |k, v|
|
10
|
-
|
12
|
+
send("#{k}=", v)
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
14
|
-
# TODO: move this to Token class
|
15
|
-
def validate_token(token)
|
16
|
-
return false unless token
|
17
|
-
token.accessible? && validate_token_scopes(token)
|
18
|
-
end
|
19
|
-
|
20
16
|
def filter_options
|
21
17
|
@filter_options
|
22
18
|
end
|
23
19
|
|
24
20
|
private
|
25
21
|
|
26
|
-
def scopes(scopes)
|
22
|
+
def scopes=(scopes)
|
27
23
|
@scopes = scopes.map(&:to_s)
|
28
24
|
end
|
29
25
|
|
30
|
-
def if(if_block)
|
26
|
+
def if=(if_block)
|
31
27
|
@filter_options[:if] = if_block
|
32
28
|
end
|
33
29
|
|
34
|
-
def unless(unless_block)
|
30
|
+
def unless=(unless_block)
|
35
31
|
@filter_options[:unless] = unless_block
|
36
32
|
end
|
37
|
-
|
38
|
-
# TODO: move this to Token class
|
39
|
-
def validate_token_scopes(token)
|
40
|
-
return true if @scopes.blank?
|
41
|
-
token.scopes.any? { |scope| @scopes.include? scope }
|
42
|
-
end
|
43
33
|
end
|
44
34
|
|
45
35
|
class AllDoorkeeperFor < DoorkeeperFor
|
46
36
|
private
|
47
37
|
|
48
|
-
def except(actions)
|
38
|
+
def except=(actions)
|
49
39
|
@filter_options[:except] = actions
|
50
40
|
end
|
51
41
|
end
|
@@ -1,14 +1,9 @@
|
|
1
1
|
module Doorkeeper
|
2
2
|
module Helpers
|
3
3
|
module Controller
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
:authenticate_admin!,
|
8
|
-
:current_resource_owner,
|
9
|
-
:resource_owner_from_credentials,
|
10
|
-
:skip_authorization?
|
11
|
-
end
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
private
|
12
7
|
|
13
8
|
def authenticate_resource_owner!
|
14
9
|
current_resource_owner
|
@@ -30,6 +25,14 @@ module Doorkeeper
|
|
30
25
|
@server ||= Server.new(self)
|
31
26
|
end
|
32
27
|
|
28
|
+
def doorkeeper_token
|
29
|
+
@token ||= OAuth::Token.authenticate request, *config_methods
|
30
|
+
end
|
31
|
+
|
32
|
+
def config_methods
|
33
|
+
@methods ||= Doorkeeper.configuration.access_token_methods
|
34
|
+
end
|
35
|
+
|
33
36
|
def get_error_response_from_exception(exception)
|
34
37
|
error_name = case exception
|
35
38
|
when Errors::InvalidTokenStrategy
|
@@ -6,18 +6,18 @@ module Doorkeeper
|
|
6
6
|
doorkeeper_for = DoorkeeperForBuilder.create_doorkeeper_for(*args)
|
7
7
|
|
8
8
|
before_filter doorkeeper_for.filter_options do
|
9
|
-
unless doorkeeper_for.
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
if render_options.nil? || render_options.empty?
|
15
|
-
head :unauthorized
|
9
|
+
unless valid_token?(doorkeeper_for.scopes)
|
10
|
+
if !doorkeeper_token || !doorkeeper_token.accessible?
|
11
|
+
@error = OAuth::InvalidTokenResponse.from_access_token(doorkeeper_token)
|
12
|
+
error_status = :unauthorized
|
13
|
+
options = doorkeeper_unauthorized_render_options
|
16
14
|
else
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
@error = OAuth::ForbiddenTokenResponse.from_scopes(doorkeeper_for.scopes)
|
16
|
+
error_status = :forbidden
|
17
|
+
options = doorkeeper_forbidden_render_options
|
20
18
|
end
|
19
|
+
headers.merge!(@error.headers.reject { |k, v| ['Content-Type'].include? k })
|
20
|
+
render_error(error_status, options)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
@@ -29,14 +29,36 @@ module Doorkeeper
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def doorkeeper_token
|
32
|
-
|
33
|
-
|
34
|
-
|
32
|
+
@token ||= OAuth::Token.authenticate request, *config_methods
|
33
|
+
end
|
34
|
+
|
35
|
+
def config_methods
|
36
|
+
@methods ||= Doorkeeper.configuration.access_token_methods
|
35
37
|
end
|
36
38
|
|
37
39
|
def doorkeeper_unauthorized_render_options
|
38
40
|
nil
|
39
41
|
end
|
42
|
+
|
43
|
+
def doorkeeper_forbidden_render_options
|
44
|
+
nil
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def valid_token?(scopes)
|
50
|
+
doorkeeper_token && doorkeeper_token.acceptable?(scopes)
|
51
|
+
end
|
52
|
+
|
53
|
+
def render_error(error, options)
|
54
|
+
if options.blank?
|
55
|
+
head error
|
56
|
+
else
|
57
|
+
options[:status] = error
|
58
|
+
options[:layout] = false if options[:layout].nil?
|
59
|
+
render options
|
60
|
+
end
|
61
|
+
end
|
40
62
|
end
|
41
63
|
end
|
42
64
|
end
|