doorkeeper 3.1.0 → 4.4.3
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/.coveralls.yml +1 -0
- data/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +6 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +26 -10
- data/Appraisals +18 -0
- data/CODE_OF_CONDUCT.md +46 -0
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +5 -5
- data/NEWS.md +141 -2
- data/README.md +149 -66
- data/RELEASING.md +5 -12
- data/Rakefile +1 -1
- data/SECURITY.md +15 -0
- data/app/controllers/doorkeeper/application_controller.rb +4 -6
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +18 -8
- data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
- data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
- data/app/validators/redirect_uri_validator.rb +12 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/applications/_form.html.erb +13 -2
- data/app/views/doorkeeper/applications/index.html.erb +2 -0
- data/app/views/doorkeeper/applications/show.html.erb +4 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
- data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
- data/config/locales/en.yml +12 -7
- data/doorkeeper.gemspec +16 -11
- data/gemfiles/rails_4_2.gemfile +13 -0
- data/gemfiles/rails_5_0.gemfile +12 -0
- data/gemfiles/rails_5_1.gemfile +12 -0
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper/config.rb +119 -46
- data/lib/doorkeeper/engine.rb +11 -7
- data/lib/doorkeeper/errors.rb +18 -0
- data/lib/doorkeeper/grape/helpers.rb +14 -8
- data/lib/doorkeeper/helpers/controller.rb +8 -19
- data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
- data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
- data/lib/doorkeeper/models/application_mixin.rb +33 -35
- data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
- data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
- data/lib/doorkeeper/oauth/base_response.rb +29 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
- data/lib/doorkeeper/oauth/client.rb +2 -3
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
- data/lib/doorkeeper/oauth/code_response.rb +16 -16
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +10 -10
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
- data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
- data/lib/doorkeeper/oauth/scopes.rb +18 -8
- data/lib/doorkeeper/oauth/token.rb +20 -21
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_request.rb +1 -2
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
- data/lib/doorkeeper/orm/active_record/application.rb +48 -11
- data/lib/doorkeeper/orm/active_record.rb +17 -22
- data/lib/doorkeeper/rails/helpers.rb +6 -9
- data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
- data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
- data/lib/doorkeeper/rails/routes.rb +17 -11
- data/lib/doorkeeper/request/authorization_code.rb +7 -1
- data/lib/doorkeeper/request/password.rb +2 -2
- data/lib/doorkeeper/request/refresh_token.rb +1 -1
- data/lib/doorkeeper/request.rb +7 -1
- data/lib/doorkeeper/server.rb +0 -8
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +34 -1
- data/lib/doorkeeper.rb +10 -2
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -0
- data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
- data/lib/generators/doorkeeper/migration_generator.rb +13 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +35 -0
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
- data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
- data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
- data/spec/controllers/application_metal_controller.rb +10 -0
- data/spec/controllers/applications_controller_spec.rb +15 -4
- data/spec/controllers/authorizations_controller_spec.rb +74 -27
- data/spec/controllers/protected_resources_controller_spec.rb +70 -32
- data/spec/controllers/token_info_controller_spec.rb +17 -13
- data/spec/controllers/tokens_controller_spec.rb +198 -12
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
- data/spec/dummy/app/controllers/home_controller.rb +1 -1
- data/spec/dummy/app/controllers/metal_controller.rb +1 -1
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
- data/spec/dummy/app/models/user.rb +0 -4
- data/spec/dummy/config/application.rb +2 -36
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/test.rb +4 -15
- data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
- data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
- data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
- data/spec/dummy/db/schema.rb +24 -22
- data/spec/factories.rb +4 -2
- data/spec/generators/application_owner_generator_spec.rb +24 -5
- data/spec/generators/migration_generator_spec.rb +24 -3
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +159 -14
- data/spec/lib/doorkeeper_spec.rb +135 -13
- data/spec/lib/models/expirable_spec.rb +0 -1
- data/spec/lib/models/revocable_spec.rb +27 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
- data/spec/lib/oauth/base_request_spec.rb +155 -0
- data/spec/lib/oauth/base_response_spec.rb +45 -0
- data/spec/lib/oauth/client/credentials_spec.rb +45 -2
- data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
- data/spec/lib/oauth/code_request_spec.rb +1 -3
- data/spec/lib/oauth/code_response_spec.rb +34 -0
- data/spec/lib/oauth/error_response_spec.rb +9 -9
- data/spec/lib/oauth/error_spec.rb +1 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
- data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
- data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
- data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
- data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
- data/spec/lib/oauth/scopes_spec.rb +28 -2
- data/spec/lib/oauth/token_request_spec.rb +6 -8
- data/spec/lib/oauth/token_spec.rb +12 -5
- data/spec/lib/server_spec.rb +10 -3
- data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +116 -48
- data/spec/models/doorkeeper/application_spec.rb +145 -29
- data/spec/requests/applications/applications_request_spec.rb +5 -5
- data/spec/requests/endpoints/authorization_spec.rb +5 -6
- data/spec/requests/endpoints/token_spec.rb +8 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
- data/spec/requests/flows/authorization_code_spec.rb +6 -13
- data/spec/requests/flows/client_credentials_spec.rb +29 -1
- data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
- data/spec/requests/flows/password_spec.rb +118 -15
- data/spec/requests/flows/refresh_token_spec.rb +89 -19
- data/spec/requests/flows/revoke_token_spec.rb +105 -91
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +1 -1
- data/spec/routing/custom_controller_routes_spec.rb +4 -0
- data/spec/routing/default_routes_spec.rb +5 -1
- data/spec/spec_helper.rb +2 -0
- data/spec/spec_helper_integration.rb +22 -4
- data/spec/support/dependencies/factory_girl.rb +2 -2
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/model_helper.rb +34 -7
- data/spec/support/helpers/request_spec_helper.rb +17 -5
- data/spec/support/helpers/url_helper.rb +9 -8
- data/spec/support/http_method_shim.rb +38 -0
- data/spec/support/shared/controllers_shared_context.rb +15 -10
- data/spec/support/shared/models_shared_examples.rb +5 -5
- data/spec/validators/redirect_uri_validator_spec.rb +51 -6
- data/spec/version/version_spec.rb +15 -0
- metadata +128 -46
- data/lib/doorkeeper/oauth/client/methods.rb +0 -18
- data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
- data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
- data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
- data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
- data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -3,9 +3,8 @@ require 'doorkeeper/rails/routes/mapper'
|
|
3
3
|
|
4
4
|
module Doorkeeper
|
5
5
|
module Rails
|
6
|
-
class Routes
|
6
|
+
class Routes # :nodoc:
|
7
7
|
module Helper
|
8
|
-
# TODO: options hash is not being used
|
9
8
|
def use_doorkeeper(options = {}, &block)
|
10
9
|
Doorkeeper::Rails::Routes.new(self, &block).generate_routes!(options)
|
11
10
|
end
|
@@ -15,18 +14,19 @@ module Doorkeeper
|
|
15
14
|
ActionDispatch::Routing::Mapper.send :include, Doorkeeper::Rails::Routes::Helper
|
16
15
|
end
|
17
16
|
|
18
|
-
|
17
|
+
attr_reader :routes
|
19
18
|
|
20
19
|
def initialize(routes, &block)
|
21
|
-
@routes
|
20
|
+
@routes = routes
|
21
|
+
@mapping = Mapper.new.map(&block)
|
22
22
|
end
|
23
23
|
|
24
24
|
def generate_routes!(options)
|
25
|
-
@mapping = Mapper.new.map(&@block)
|
26
25
|
routes.scope options[:scope] || 'oauth', as: 'oauth' do
|
27
26
|
map_route(:authorizations, :authorization_routes)
|
28
27
|
map_route(:tokens, :token_routes)
|
29
28
|
map_route(:tokens, :revoke_routes)
|
29
|
+
map_route(:tokens, :introspect_routes)
|
30
30
|
map_route(:applications, :application_routes)
|
31
31
|
map_route(:authorized_applications, :authorized_applications_routes)
|
32
32
|
map_route(:token_info, :token_info_routes)
|
@@ -36,20 +36,18 @@ module Doorkeeper
|
|
36
36
|
private
|
37
37
|
|
38
38
|
def map_route(name, method)
|
39
|
-
unless @mapping.skipped?(name)
|
40
|
-
send method, @mapping[name]
|
41
|
-
end
|
39
|
+
send(method, @mapping[name]) unless @mapping.skipped?(name)
|
42
40
|
end
|
43
41
|
|
44
42
|
def authorization_routes(mapping)
|
45
43
|
routes.resource(
|
46
44
|
:authorization,
|
47
45
|
path: 'authorize',
|
48
|
-
only: [
|
46
|
+
only: %i[create destroy],
|
49
47
|
as: mapping[:as],
|
50
48
|
controller: mapping[:controllers]
|
51
49
|
) do
|
52
|
-
routes.get
|
50
|
+
routes.get native_authorization_code_route, action: :show, on: :member
|
53
51
|
routes.get '/', action: :new, on: :member
|
54
52
|
end
|
55
53
|
end
|
@@ -67,6 +65,10 @@ module Doorkeeper
|
|
67
65
|
routes.post 'revoke', controller: mapping[:controllers], action: :revoke
|
68
66
|
end
|
69
67
|
|
68
|
+
def introspect_routes(mapping)
|
69
|
+
routes.post 'introspect', controller: mapping[:controllers], action: :introspect
|
70
|
+
end
|
71
|
+
|
70
72
|
def token_info_routes(mapping)
|
71
73
|
routes.resource(
|
72
74
|
:token_info,
|
@@ -81,7 +83,11 @@ module Doorkeeper
|
|
81
83
|
end
|
82
84
|
|
83
85
|
def authorized_applications_routes(mapping)
|
84
|
-
routes.resources :authorized_applications, only: [
|
86
|
+
routes.resources :authorized_applications, only: %i[index destroy], controller: mapping[:controllers]
|
87
|
+
end
|
88
|
+
|
89
|
+
def native_authorization_code_route
|
90
|
+
Doorkeeper.configuration.native_authorization_code_route
|
85
91
|
end
|
86
92
|
end
|
87
93
|
end
|
@@ -3,7 +3,7 @@ require 'doorkeeper/request/strategy'
|
|
3
3
|
module Doorkeeper
|
4
4
|
module Request
|
5
5
|
class AuthorizationCode < Strategy
|
6
|
-
delegate :
|
6
|
+
delegate :client, :parameters, to: :server
|
7
7
|
|
8
8
|
def request
|
9
9
|
@request ||= OAuth::AuthorizationCodeRequest.new(
|
@@ -13,6 +13,12 @@ module Doorkeeper
|
|
13
13
|
parameters
|
14
14
|
)
|
15
15
|
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
def grant
|
20
|
+
AccessGrant.by_token(parameters[:code])
|
21
|
+
end
|
16
22
|
end
|
17
23
|
end
|
18
24
|
end
|
@@ -3,12 +3,12 @@ require 'doorkeeper/request/strategy'
|
|
3
3
|
module Doorkeeper
|
4
4
|
module Request
|
5
5
|
class Password < Strategy
|
6
|
-
delegate :credentials, :resource_owner, :parameters, to: :server
|
6
|
+
delegate :credentials, :resource_owner, :parameters, :client, to: :server
|
7
7
|
|
8
8
|
def request
|
9
9
|
@request ||= OAuth::PasswordAccessTokenRequest.new(
|
10
10
|
Doorkeeper.configuration,
|
11
|
-
|
11
|
+
client,
|
12
12
|
resource_owner,
|
13
13
|
parameters
|
14
14
|
)
|
data/lib/doorkeeper/request.rb
CHANGED
@@ -24,7 +24,7 @@ module Doorkeeper
|
|
24
24
|
def get_strategy(grant_or_request_type, available)
|
25
25
|
fail Errors::MissingRequestStrategy unless grant_or_request_type.present?
|
26
26
|
fail NameError unless available.include?(grant_or_request_type.to_s)
|
27
|
-
|
27
|
+
strategy_class(grant_or_request_type)
|
28
28
|
end
|
29
29
|
|
30
30
|
def authorization_response_types
|
@@ -36,5 +36,11 @@ module Doorkeeper
|
|
36
36
|
Doorkeeper.configuration.token_grant_types
|
37
37
|
end
|
38
38
|
private_class_method :token_grant_types
|
39
|
+
|
40
|
+
def strategy_class(grant_or_request_type)
|
41
|
+
strategy_class_name = grant_or_request_type.to_s.tr(' ', '_').camelize
|
42
|
+
"Doorkeeper::Request::#{strategy_class_name}".constantize
|
43
|
+
end
|
44
|
+
private_class_method :strategy_class
|
39
45
|
end
|
40
46
|
end
|
data/lib/doorkeeper/server.rb
CHANGED
@@ -33,14 +33,6 @@ module Doorkeeper
|
|
33
33
|
context.send :current_resource_owner
|
34
34
|
end
|
35
35
|
|
36
|
-
def current_refresh_token
|
37
|
-
AccessToken.by_refresh_token(parameters[:refresh_token])
|
38
|
-
end
|
39
|
-
|
40
|
-
def grant
|
41
|
-
AccessGrant.by_token(parameters[:code])
|
42
|
-
end
|
43
|
-
|
44
36
|
# TODO: Use configuration and evaluate proper context on block
|
45
37
|
def resource_owner
|
46
38
|
context.send :resource_owner_from_credentials
|
@@ -6,9 +6,10 @@ module Doorkeeper
|
|
6
6
|
|
7
7
|
def validate
|
8
8
|
@error = nil
|
9
|
+
|
9
10
|
self.class.validations.each do |validation|
|
11
|
+
@error = validation[:options][:error] unless send("validate_#{validation[:attribute]}")
|
10
12
|
break if @error
|
11
|
-
@error = validation.last unless send("validate_#{validation.first}")
|
12
13
|
end
|
13
14
|
end
|
14
15
|
|
@@ -19,7 +20,7 @@ module Doorkeeper
|
|
19
20
|
|
20
21
|
module ClassMethods
|
21
22
|
def validate(attribute, options = {})
|
22
|
-
validations <<
|
23
|
+
validations << { attribute: attribute, options: options }
|
23
24
|
end
|
24
25
|
|
25
26
|
def validations
|
data/lib/doorkeeper/version.rb
CHANGED
@@ -1,3 +1,36 @@
|
|
1
1
|
module Doorkeeper
|
2
|
-
|
2
|
+
CVE_2018_1000211_WARNING = <<-HEREDOC.freeze
|
3
|
+
|
4
|
+
|
5
|
+
WARNING: This is a security release that addresses token revocation not working for public apps (CVE-2018-1000211)
|
6
|
+
|
7
|
+
There is no breaking change in this release, however to take advantage of the security fix you must:
|
8
|
+
|
9
|
+
1. Run `rails generate doorkeeper:add_client_confidentiality` for the migration
|
10
|
+
2. Review your OAuth apps and determine which ones exclusively use public grant flows (eg implicit)
|
11
|
+
3. Update their `confidential` column to `false` for those public apps
|
12
|
+
|
13
|
+
This is a backported security release.
|
14
|
+
|
15
|
+
For more information:
|
16
|
+
|
17
|
+
* https://github.com/doorkeeper-gem/doorkeeper/pull/1119
|
18
|
+
* https://github.com/doorkeeper-gem/doorkeeper/issues/891
|
19
|
+
|
20
|
+
|
21
|
+
HEREDOC
|
22
|
+
|
23
|
+
def self.gem_version
|
24
|
+
Gem::Version.new VERSION::STRING
|
25
|
+
end
|
26
|
+
|
27
|
+
module VERSION
|
28
|
+
# Semantic versioning
|
29
|
+
MAJOR = 4
|
30
|
+
MINOR = 4
|
31
|
+
TINY = 3
|
32
|
+
|
33
|
+
# Full version number
|
34
|
+
STRING = [MAJOR, MINOR, TINY].compact.join('.')
|
35
|
+
end
|
3
36
|
end
|
data/lib/doorkeeper.rb
CHANGED
@@ -16,11 +16,12 @@ require 'doorkeeper/oauth/helpers/unique_token'
|
|
16
16
|
|
17
17
|
require 'doorkeeper/oauth/scopes'
|
18
18
|
require 'doorkeeper/oauth/error'
|
19
|
+
require 'doorkeeper/oauth/base_response'
|
19
20
|
require 'doorkeeper/oauth/code_response'
|
20
21
|
require 'doorkeeper/oauth/token_response'
|
21
22
|
require 'doorkeeper/oauth/error_response'
|
22
23
|
require 'doorkeeper/oauth/pre_authorization'
|
23
|
-
require 'doorkeeper/oauth/
|
24
|
+
require 'doorkeeper/oauth/base_request'
|
24
25
|
require 'doorkeeper/oauth/authorization_code_request'
|
25
26
|
require 'doorkeeper/oauth/refresh_token_request'
|
26
27
|
require 'doorkeeper/oauth/password_access_token_request'
|
@@ -29,9 +30,11 @@ require 'doorkeeper/oauth/code_request'
|
|
29
30
|
require 'doorkeeper/oauth/token_request'
|
30
31
|
require 'doorkeeper/oauth/client'
|
31
32
|
require 'doorkeeper/oauth/token'
|
33
|
+
require 'doorkeeper/oauth/token_introspection'
|
32
34
|
require 'doorkeeper/oauth/invalid_token_response'
|
33
35
|
require 'doorkeeper/oauth/forbidden_token_response'
|
34
36
|
|
37
|
+
require 'doorkeeper/models/concerns/orderable'
|
35
38
|
require 'doorkeeper/models/concerns/scopes'
|
36
39
|
require 'doorkeeper/models/concerns/expirable'
|
37
40
|
require 'doorkeeper/models/concerns/revocable'
|
@@ -48,16 +51,21 @@ require 'doorkeeper/rails/helpers'
|
|
48
51
|
|
49
52
|
require 'doorkeeper/orm/active_record'
|
50
53
|
|
54
|
+
require 'active_support/deprecation'
|
55
|
+
|
51
56
|
module Doorkeeper
|
52
57
|
def self.configured?
|
58
|
+
ActiveSupport::Deprecation.warn "Method `Doorkeeper#configured?` has been deprecated without replacement."
|
53
59
|
@config.present?
|
54
60
|
end
|
55
61
|
|
56
62
|
def self.database_installed?
|
57
|
-
|
63
|
+
ActiveSupport::Deprecation.warn "Method `Doorkeeper#database_installed?` has been deprecated without replacement."
|
64
|
+
[AccessToken, AccessGrant, Application].all?(&:table_exists?)
|
58
65
|
end
|
59
66
|
|
60
67
|
def self.installed?
|
68
|
+
ActiveSupport::Deprecation.warn "Method `Doorkeeper#installed?` has been deprecated without replacement."
|
61
69
|
configured? && database_installed?
|
62
70
|
end
|
63
71
|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'rails/generators/active_record'
|
4
|
+
|
5
|
+
module Doorkeeper
|
6
|
+
class AddClientConfidentialityGenerator < ::Rails::Generators::Base
|
7
|
+
include ::Rails::Generators::Migration
|
8
|
+
source_root File.expand_path('templates', __dir__)
|
9
|
+
desc 'Adds a migration to fix CVE-2018-1000211.'
|
10
|
+
|
11
|
+
def install
|
12
|
+
migration_template(
|
13
|
+
'add_confidential_to_application_migration.rb.erb',
|
14
|
+
'db/migrate/add_confidential_to_doorkeeper_application.rb',
|
15
|
+
migration_version: migration_version
|
16
|
+
)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.next_migration_number(dirname)
|
20
|
+
::ActiveRecord::Generators::Base.next_migration_number(dirname)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def migration_version
|
26
|
+
if ::ActiveRecord::VERSION::MAJOR >= 5
|
27
|
+
"[#{::ActiveRecord::VERSION::MAJOR}.#{::ActiveRecord::VERSION::MINOR}]"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -7,12 +7,21 @@ class Doorkeeper::ApplicationOwnerGenerator < Rails::Generators::Base
|
|
7
7
|
|
8
8
|
def application_owner
|
9
9
|
migration_template(
|
10
|
-
'add_owner_to_application_migration.rb',
|
11
|
-
'db/migrate/add_owner_to_application.rb'
|
10
|
+
'add_owner_to_application_migration.rb.erb',
|
11
|
+
'db/migrate/add_owner_to_application.rb',
|
12
|
+
migration_version: migration_version
|
12
13
|
)
|
13
14
|
end
|
14
15
|
|
15
16
|
def self.next_migration_number(dirname)
|
16
17
|
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
17
18
|
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def migration_version
|
23
|
+
if ActiveRecord::VERSION::MAJOR >= 5
|
24
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
25
|
+
end
|
26
|
+
end
|
18
27
|
end
|
@@ -6,10 +6,22 @@ class Doorkeeper::MigrationGenerator < ::Rails::Generators::Base
|
|
6
6
|
desc 'Installs Doorkeeper migration file.'
|
7
7
|
|
8
8
|
def install
|
9
|
-
migration_template
|
9
|
+
migration_template(
|
10
|
+
'migration.rb.erb',
|
11
|
+
'db/migrate/create_doorkeeper_tables.rb',
|
12
|
+
migration_version: migration_version
|
13
|
+
)
|
10
14
|
end
|
11
15
|
|
12
16
|
def self.next_migration_number(dirname)
|
13
17
|
ActiveRecord::Generators::Base.next_migration_number(dirname)
|
14
18
|
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def migration_version
|
23
|
+
if ActiveRecord::VERSION::MAJOR >= 5
|
24
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
25
|
+
end
|
26
|
+
end
|
15
27
|
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'rails/generators/active_record'
|
2
|
+
|
3
|
+
class Doorkeeper::PreviousRefreshTokenGenerator < Rails::Generators::Base
|
4
|
+
include Rails::Generators::Migration
|
5
|
+
source_root File.expand_path('../templates', __FILE__)
|
6
|
+
desc 'Support revoke refresh token on access token use'
|
7
|
+
|
8
|
+
def self.next_migration_number(path)
|
9
|
+
ActiveRecord::Generators::Base.next_migration_number(path)
|
10
|
+
end
|
11
|
+
|
12
|
+
def previous_refresh_token
|
13
|
+
if no_previous_refresh_token_column?
|
14
|
+
migration_template(
|
15
|
+
'add_previous_refresh_token_to_access_tokens.rb.erb',
|
16
|
+
'db/migrate/add_previous_refresh_token_to_access_tokens.rb'
|
17
|
+
)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def migration_version
|
24
|
+
if ActiveRecord::VERSION::MAJOR >= 5
|
25
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def no_previous_refresh_token_column?
|
30
|
+
!ActiveRecord::Base.connection.column_exists?(
|
31
|
+
:oauth_access_tokens,
|
32
|
+
:previous_refresh_token
|
33
|
+
)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class AddConfidentialToDoorkeeperApplication < ActiveRecord::Migration<%= migration_version %>
|
2
|
+
def change
|
3
|
+
add_column(
|
4
|
+
:oauth_applications,
|
5
|
+
:confidential,
|
6
|
+
:boolean,
|
7
|
+
null: false,
|
8
|
+
default: true # maintaining backwards compatibility: require secrets
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
class AddOwnerToApplication < ActiveRecord::Migration
|
1
|
+
class AddOwnerToApplication < ActiveRecord::Migration<%= migration_version %>
|
2
2
|
def change
|
3
3
|
add_column :oauth_applications, :owner_id, :integer, null: true
|
4
4
|
add_column :oauth_applications, :owner_type, :string, null: true
|
@@ -31,7 +31,12 @@ Doorkeeper.configure do
|
|
31
31
|
|
32
32
|
# Use a custom class for generating the access token.
|
33
33
|
# https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
|
34
|
-
# access_token_generator
|
34
|
+
# access_token_generator '::Doorkeeper::JWT'
|
35
|
+
|
36
|
+
# The controller Doorkeeper::ApplicationController inherits from.
|
37
|
+
# Defaults to ActionController::Base.
|
38
|
+
# https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
|
39
|
+
# base_controller 'ApplicationController'
|
35
40
|
|
36
41
|
# Reuse access token for the same resource owner within an application (disabled by default)
|
37
42
|
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
|
@@ -41,10 +46,10 @@ Doorkeeper.configure do
|
|
41
46
|
# use_refresh_token
|
42
47
|
|
43
48
|
# Provide support for an owner to be assigned to each registered application (disabled by default)
|
44
|
-
# Optional parameter :
|
49
|
+
# Optional parameter confirmation: true (default false) if you want to enforce ownership of
|
45
50
|
# a registered application
|
46
51
|
# Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
|
47
|
-
# enable_application_owner :
|
52
|
+
# enable_application_owner confirmation: false
|
48
53
|
|
49
54
|
# Define access token scopes for your provider
|
50
55
|
# For more information go to
|
@@ -55,13 +60,15 @@ Doorkeeper.configure do
|
|
55
60
|
# Change the way client credentials are retrieved from the request object.
|
56
61
|
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
57
62
|
# falls back to the `:client_id` and `:client_secret` params from the `params` object.
|
58
|
-
# Check out
|
63
|
+
# Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated
|
64
|
+
# for more information on customization
|
59
65
|
# client_credentials :from_basic, :from_params
|
60
66
|
|
61
67
|
# Change the way access token is authenticated from the request object.
|
62
68
|
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
63
69
|
# falls back to the `:access_token` or `:bearer_token` params from the `params` object.
|
64
|
-
# Check out
|
70
|
+
# Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated
|
71
|
+
# for more information on customization
|
65
72
|
# access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
|
66
73
|
|
67
74
|
# Change the native redirect uri for client apps
|
@@ -75,7 +82,21 @@ Doorkeeper.configure do
|
|
75
82
|
# by default in non-development environments). OAuth2 delegates security in
|
76
83
|
# communication to the HTTPS protocol so it is wise to keep this enabled.
|
77
84
|
#
|
85
|
+
# Callable objects such as proc, lambda, block or any object that responds to
|
86
|
+
# #call can be used in order to allow conditional checks (to allow non-SSL
|
87
|
+
# redirects to localhost for example).
|
88
|
+
#
|
78
89
|
# force_ssl_in_redirect_uri !Rails.env.development?
|
90
|
+
#
|
91
|
+
# force_ssl_in_redirect_uri { |uri| uri.host != 'localhost' }
|
92
|
+
|
93
|
+
# Specify what redirect URI's you want to block during creation. Any redirect
|
94
|
+
# URI is whitelisted by default.
|
95
|
+
#
|
96
|
+
# You can use this option in order to forbid URI's with 'javascript' scheme
|
97
|
+
# for example.
|
98
|
+
#
|
99
|
+
# forbid_redirect_uri { |uri| uri.scheme.to_s.downcase == 'javascript' }
|
79
100
|
|
80
101
|
# Specify what grant flows are enabled in array of Strings. The valid
|
81
102
|
# strings and the flows they enable are:
|
@@ -93,7 +114,18 @@ Doorkeeper.configure do
|
|
93
114
|
# http://tools.ietf.org/html/rfc6819#section-4.4.2
|
94
115
|
# http://tools.ietf.org/html/rfc6819#section-4.4.3
|
95
116
|
#
|
96
|
-
# grant_flows %w
|
117
|
+
# grant_flows %w[authorization_code client_credentials]
|
118
|
+
|
119
|
+
# Hook into the strategies' request & response life-cycle in case your
|
120
|
+
# application needs advanced customization or logging:
|
121
|
+
#
|
122
|
+
# before_successful_strategy_response do |request|
|
123
|
+
# puts "BEFORE HOOK FIRED! #{request}"
|
124
|
+
# end
|
125
|
+
#
|
126
|
+
# after_successful_strategy_response do |request, response|
|
127
|
+
# puts "AFTER HOOK FIRED! #{request}, #{response}"
|
128
|
+
# end
|
97
129
|
|
98
130
|
# Under some circumstances you might want to have applications auto-approved,
|
99
131
|
# so that the user skips the authorization step.
|
@@ -0,0 +1,69 @@
|
|
1
|
+
class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
|
2
|
+
def change
|
3
|
+
create_table :oauth_applications do |t|
|
4
|
+
t.string :name, null: false
|
5
|
+
t.string :uid, null: false
|
6
|
+
t.string :secret, null: false
|
7
|
+
t.text :redirect_uri, null: false
|
8
|
+
t.string :scopes, null: false, default: ''
|
9
|
+
t.boolean :confidential, null: false, default: true
|
10
|
+
t.timestamps null: false
|
11
|
+
end
|
12
|
+
|
13
|
+
add_index :oauth_applications, :uid, unique: true
|
14
|
+
|
15
|
+
create_table :oauth_access_grants do |t|
|
16
|
+
t.integer :resource_owner_id, null: false
|
17
|
+
t.references :application, null: false
|
18
|
+
t.string :token, null: false
|
19
|
+
t.integer :expires_in, null: false
|
20
|
+
t.text :redirect_uri, null: false
|
21
|
+
t.datetime :created_at, null: false
|
22
|
+
t.datetime :revoked_at
|
23
|
+
t.string :scopes
|
24
|
+
end
|
25
|
+
|
26
|
+
add_index :oauth_access_grants, :token, unique: true
|
27
|
+
add_foreign_key(
|
28
|
+
:oauth_access_grants,
|
29
|
+
:oauth_applications,
|
30
|
+
column: :application_id
|
31
|
+
)
|
32
|
+
|
33
|
+
create_table :oauth_access_tokens do |t|
|
34
|
+
t.integer :resource_owner_id
|
35
|
+
t.references :application
|
36
|
+
|
37
|
+
# If you use a custom token generator you may need to change this column
|
38
|
+
# from string to text, so that it accepts tokens larger than 255
|
39
|
+
# characters. More info on custom token generators in:
|
40
|
+
# https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
|
41
|
+
#
|
42
|
+
# t.text :token, null: false
|
43
|
+
t.string :token, null: false
|
44
|
+
|
45
|
+
t.string :refresh_token
|
46
|
+
t.integer :expires_in
|
47
|
+
t.datetime :revoked_at
|
48
|
+
t.datetime :created_at, null: false
|
49
|
+
t.string :scopes
|
50
|
+
|
51
|
+
# If there is a previous_refresh_token column,
|
52
|
+
# refresh tokens will be revoked after a related access token is used.
|
53
|
+
# If there is no previous_refresh_token column,
|
54
|
+
# previous tokens are revoked as soon as a new access token is created.
|
55
|
+
# Comment out this line if you'd rather have refresh tokens
|
56
|
+
# instantly revoked.
|
57
|
+
t.string :previous_refresh_token, null: false, default: ""
|
58
|
+
end
|
59
|
+
|
60
|
+
add_index :oauth_access_tokens, :token, unique: true
|
61
|
+
add_index :oauth_access_tokens, :resource_owner_id
|
62
|
+
add_index :oauth_access_tokens, :refresh_token, unique: true
|
63
|
+
add_foreign_key(
|
64
|
+
:oauth_access_tokens,
|
65
|
+
:oauth_applications,
|
66
|
+
column: :application_id
|
67
|
+
)
|
68
|
+
end
|
69
|
+
end
|
@@ -19,13 +19,24 @@ module Doorkeeper
|
|
19
19
|
post :create, doorkeeper_application: {
|
20
20
|
name: 'Example',
|
21
21
|
redirect_uri: 'https://example.com' }
|
22
|
-
end.
|
22
|
+
end.not_to change { Doorkeeper::Application.count }
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
context 'when admin is authenticated' do
|
27
|
+
render_views
|
28
|
+
|
27
29
|
before do
|
28
|
-
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(
|
30
|
+
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'sorts applications by created_at' do
|
34
|
+
first_application = FactoryBot.create(:application)
|
35
|
+
second_application = FactoryBot.create(:application)
|
36
|
+
expect(Doorkeeper::Application).to receive(:ordered_by).and_call_original
|
37
|
+
get :index
|
38
|
+
expect(response.body).to have_selector("tbody tr:first-child#application_#{first_application.id}")
|
39
|
+
expect(response.body).to have_selector("tbody tr:last-child#application_#{second_application.id}")
|
29
40
|
end
|
30
41
|
|
31
42
|
it 'creates application' do
|
@@ -38,7 +49,7 @@ module Doorkeeper
|
|
38
49
|
end
|
39
50
|
|
40
51
|
it 'does not allow mass assignment of uid or secret' do
|
41
|
-
application =
|
52
|
+
application = FactoryBot.create(:application)
|
42
53
|
put :update, id: application.id, doorkeeper_application: {
|
43
54
|
uid: '1A2B3C4D',
|
44
55
|
secret: '1A2B3C4D' }
|
@@ -47,7 +58,7 @@ module Doorkeeper
|
|
47
58
|
end
|
48
59
|
|
49
60
|
it 'updates application' do
|
50
|
-
application =
|
61
|
+
application = FactoryBot.create(:application)
|
51
62
|
put :update, id: application.id, doorkeeper_application: {
|
52
63
|
name: 'Example',
|
53
64
|
redirect_uri: 'https://example.com' }
|