doorkeeper 4.4.3 → 5.0.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/.gitignore +1 -0
- data/.gitlab-ci.yml +16 -0
- data/.travis.yml +2 -0
- data/Appraisals +2 -2
- data/Gemfile +1 -1
- data/NEWS.md +61 -8
- data/README.md +92 -9
- data/Rakefile +6 -0
- data/UPGRADE.md +2 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +4 -3
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +42 -22
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +2 -6
- data/app/helpers/doorkeeper/dashboard_helper.rb +7 -7
- data/app/validators/redirect_uri_validator.rb +3 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +25 -24
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +17 -7
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +6 -6
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +10 -1
- data/doorkeeper.gemspec +18 -20
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/gemfiles/rails_master.gemfile +4 -1
- data/lib/doorkeeper/config.rb +75 -39
- data/lib/doorkeeper/engine.rb +4 -0
- data/lib/doorkeeper/errors.rb +2 -5
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +7 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +71 -0
- data/lib/doorkeeper/models/access_token_mixin.rb +39 -22
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +36 -14
- data/lib/doorkeeper/oauth/authorization_code_request.rb +27 -2
- data/lib/doorkeeper/oauth/base_request.rb +20 -9
- data/lib/doorkeeper/oauth/client/credentials.rb +1 -1
- data/lib/doorkeeper/oauth/client.rb +0 -2
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
- data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
- data/lib/doorkeeper/oauth/error_response.rb +11 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +41 -11
- data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -1
- data/lib/doorkeeper/oauth/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/token.rb +5 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +2 -2
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/application.rb +22 -14
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +2 -0
- data/lib/doorkeeper/rails/helpers.rb +2 -4
- data/lib/doorkeeper/rails/routes.rb +14 -6
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +6 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request/authorization_code.rb +0 -2
- data/lib/doorkeeper/request/client_credentials.rb +0 -2
- data/lib/doorkeeper/request/code.rb +0 -2
- data/lib/doorkeeper/request/password.rb +0 -2
- data/lib/doorkeeper/request/refresh_token.rb +0 -2
- data/lib/doorkeeper/request/token.rb +0 -2
- data/lib/doorkeeper/request.rb +28 -35
- data/lib/doorkeeper/version.rb +5 -25
- data/lib/doorkeeper.rb +19 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -9
- data/lib/generators/doorkeeper/migration_generator.rb +23 -18
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +76 -11
- data/lib/generators/doorkeeper/views_generator.rb +3 -1
- data/spec/controllers/application_metal_controller_spec.rb +50 -0
- data/spec/controllers/applications_controller_spec.rb +126 -13
- data/spec/controllers/authorizations_controller_spec.rb +277 -47
- data/spec/controllers/protected_resources_controller_spec.rb +16 -16
- data/spec/controllers/token_info_controller_spec.rb +4 -12
- data/spec/controllers/tokens_controller_spec.rb +13 -15
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/config/environments/test.rb +4 -5
- data/spec/dummy/config/initializers/doorkeeper.rb +10 -5
- data/spec/dummy/config/initializers/new_framework_defaults.rb +4 -0
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
- data/spec/dummy/db/schema.rb +36 -36
- data/spec/generators/application_owner_generator_spec.rb +1 -1
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/migration_generator_spec.rb +1 -1
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +1 -1
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +80 -31
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +0 -2
- data/spec/lib/models/scopes_spec.rb +0 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
- data/spec/lib/oauth/authorization_code_request_spec.rb +9 -2
- data/spec/lib/oauth/base_request_spec.rb +40 -2
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +1 -3
- data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
- data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +4 -2
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +0 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -7
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
- data/spec/lib/oauth/password_access_token_request_spec.rb +37 -2
- data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
- data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
- data/spec/lib/oauth/scopes_spec.rb +0 -3
- data/spec/lib/oauth/token_request_spec.rb +4 -5
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +37 -14
- data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +1 -1
- data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
- data/spec/models/doorkeeper/access_token_spec.rb +66 -22
- data/spec/models/doorkeeper/application_spec.rb +14 -47
- data/spec/requests/applications/applications_request_spec.rb +134 -1
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +1 -1
- data/spec/requests/endpoints/token_spec.rb +7 -5
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_spec.rb +197 -1
- data/spec/requests/flows/client_credentials_spec.rb +46 -6
- data/spec/requests/flows/implicit_grant_errors_spec.rb +1 -1
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +56 -2
- data/spec/requests/flows/refresh_token_spec.rb +2 -2
- data/spec/requests/flows/revoke_token_spec.rb +11 -11
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- 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 +59 -7
- data/spec/routing/default_routes_spec.rb +2 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -74
- data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/request_spec_helper.rb +10 -2
- data/spec/support/helpers/url_helper.rb +7 -3
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/validators/redirect_uri_validator_spec.rb +7 -1
- data/spec/version/version_spec.rb +3 -3
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +37 -33
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
- data/spec/controllers/application_metal_controller.rb +0 -10
@@ -16,6 +16,7 @@ module Doorkeeper
|
|
16
16
|
@client = client
|
17
17
|
@parameters = parameters
|
18
18
|
@original_scopes = parameters[:scope]
|
19
|
+
@grant_type = Doorkeeper::OAuth::PASSWORD
|
19
20
|
end
|
20
21
|
|
21
22
|
private
|
@@ -26,16 +27,18 @@ module Doorkeeper
|
|
26
27
|
end
|
27
28
|
|
28
29
|
def validate_scopes
|
29
|
-
|
30
|
-
|
30
|
+
client_scopes = client.try(:scopes)
|
31
|
+
return true if scopes.blank?
|
32
|
+
|
33
|
+
ScopeChecker.valid?(scopes.to_s, server.scopes, client_scopes)
|
31
34
|
end
|
32
35
|
|
33
36
|
def validate_resource_owner
|
34
|
-
|
37
|
+
!resource_owner.nil?
|
35
38
|
end
|
36
39
|
|
37
40
|
def validate_client
|
38
|
-
!parameters[:client_id] ||
|
41
|
+
!parameters[:client_id] || !client.nil?
|
39
42
|
end
|
40
43
|
end
|
41
44
|
end
|
@@ -7,17 +7,21 @@ module Doorkeeper
|
|
7
7
|
validate :client, error: :invalid_client
|
8
8
|
validate :scopes, error: :invalid_scope
|
9
9
|
validate :redirect_uri, error: :invalid_redirect_uri
|
10
|
+
validate :code_challenge_method, error: :invalid_code_challenge_method
|
10
11
|
|
11
|
-
attr_accessor :server, :client, :response_type, :redirect_uri, :state
|
12
|
+
attr_accessor :server, :client, :response_type, :redirect_uri, :state,
|
13
|
+
:code_challenge, :code_challenge_method
|
12
14
|
attr_writer :scope
|
13
15
|
|
14
16
|
def initialize(server, client, attrs = {})
|
15
|
-
@server
|
16
|
-
@client
|
17
|
-
@response_type
|
18
|
-
@redirect_uri
|
19
|
-
@scope
|
20
|
-
@state
|
17
|
+
@server = server
|
18
|
+
@client = client
|
19
|
+
@response_type = attrs[:response_type]
|
20
|
+
@redirect_uri = attrs[:redirect_uri]
|
21
|
+
@scope = attrs[:scope]
|
22
|
+
@state = attrs[:state]
|
23
|
+
@code_challenge = attrs[:code_challenge]
|
24
|
+
@code_challenge_method = attrs[:code_challenge_method]
|
21
25
|
end
|
22
26
|
|
23
27
|
def authorizable?
|
@@ -29,15 +33,36 @@ module Doorkeeper
|
|
29
33
|
end
|
30
34
|
|
31
35
|
def scope
|
32
|
-
@scope.presence ||
|
36
|
+
@scope.presence || build_scopes
|
33
37
|
end
|
34
38
|
|
35
39
|
def error_response
|
36
40
|
OAuth::ErrorResponse.from_request(self)
|
37
41
|
end
|
38
42
|
|
43
|
+
def as_json(_options)
|
44
|
+
{
|
45
|
+
client_id: client.uid,
|
46
|
+
redirect_uri: redirect_uri,
|
47
|
+
state: state,
|
48
|
+
response_type: response_type,
|
49
|
+
scope: scope,
|
50
|
+
client_name: client.name,
|
51
|
+
status: I18n.t('doorkeeper.pre_authorization.status')
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
39
55
|
private
|
40
56
|
|
57
|
+
def build_scopes
|
58
|
+
client_scopes = client.application.scopes
|
59
|
+
if client_scopes.blank?
|
60
|
+
server.default_scopes.to_s
|
61
|
+
else
|
62
|
+
(server.default_scopes & client_scopes).to_s
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
41
66
|
def validate_response_type
|
42
67
|
server.authorization_response_types.include? response_type
|
43
68
|
end
|
@@ -47,7 +72,8 @@ module Doorkeeper
|
|
47
72
|
end
|
48
73
|
|
49
74
|
def validate_scopes
|
50
|
-
return true
|
75
|
+
return true if scope.blank?
|
76
|
+
|
51
77
|
Helpers::ScopeChecker.valid?(
|
52
78
|
scope,
|
53
79
|
server.scopes,
|
@@ -55,14 +81,18 @@ module Doorkeeper
|
|
55
81
|
)
|
56
82
|
end
|
57
83
|
|
58
|
-
# TODO: test uri should be matched against the client's one
|
59
84
|
def validate_redirect_uri
|
60
85
|
return false if redirect_uri.blank?
|
61
86
|
|
62
87
|
Helpers::URIChecker.valid_for_authorization?(
|
63
|
-
redirect_uri,
|
88
|
+
redirect_uri,
|
89
|
+
client.redirect_uri
|
64
90
|
)
|
65
91
|
end
|
92
|
+
|
93
|
+
def validate_code_challenge_method
|
94
|
+
!code_challenge.present? || (code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
|
95
|
+
end
|
66
96
|
end
|
67
97
|
end
|
68
98
|
end
|
@@ -65,7 +65,12 @@ module Doorkeeper
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def access_token_expires_in
|
68
|
-
Authorization::Token.
|
68
|
+
context = Authorization::Token.build_context(
|
69
|
+
client,
|
70
|
+
Doorkeeper::OAuth::REFRESH_TOKEN,
|
71
|
+
scopes
|
72
|
+
)
|
73
|
+
Authorization::Token.access_token_expires_in(server, context)
|
69
74
|
end
|
70
75
|
|
71
76
|
def validate_token_presence
|
@@ -3,7 +3,7 @@ module Doorkeeper
|
|
3
3
|
class Token
|
4
4
|
class << self
|
5
5
|
def from_request(request, *methods)
|
6
|
-
methods.inject(nil) do |
|
6
|
+
methods.inject(nil) do |_, method|
|
7
7
|
method = self.method(method) if method.is_a?(Symbol)
|
8
8
|
credentials = method.call(request)
|
9
9
|
break credentials unless credentials.blank?
|
@@ -13,7 +13,10 @@ module Doorkeeper
|
|
13
13
|
def authenticate(request, *methods)
|
14
14
|
if (token = from_request(request, *methods))
|
15
15
|
access_token = AccessToken.by_token(token)
|
16
|
-
|
16
|
+
refresh_token_enabled = Doorkeeper.configuration.refresh_token_enabled?
|
17
|
+
if access_token.present? && refresh_token_enabled
|
18
|
+
access_token.revoke_previous_refresh_token!
|
19
|
+
end
|
17
20
|
access_token
|
18
21
|
end
|
19
22
|
end
|
@@ -47,12 +47,12 @@ module Doorkeeper
|
|
47
47
|
|
48
48
|
# Client Authentication
|
49
49
|
def authorized_client
|
50
|
-
@
|
50
|
+
@authorized_client ||= server.credentials && server.client
|
51
51
|
end
|
52
52
|
|
53
53
|
# Bearer Token Authentication
|
54
54
|
def authorized_token
|
55
|
-
@
|
55
|
+
@authorized_token ||=
|
56
56
|
OAuth::Token.authenticate(server.context.request, :from_bearer_authorization)
|
57
57
|
end
|
58
58
|
|
@@ -23,9 +23,11 @@ module Doorkeeper
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def headers
|
26
|
-
{
|
26
|
+
{
|
27
|
+
'Cache-Control' => 'no-store',
|
27
28
|
'Pragma' => 'no-cache',
|
28
|
-
'Content-Type' => 'application/json; charset=utf-8'
|
29
|
+
'Content-Type' => 'application/json; charset=utf-8'
|
30
|
+
}
|
29
31
|
end
|
30
32
|
end
|
31
33
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module OAuth
|
5
|
+
GRANT_TYPES = [
|
6
|
+
AUTHORIZATION_CODE = 'authorization_code'.freeze,
|
7
|
+
IMPLICIT = 'implicit'.freeze,
|
8
|
+
PASSWORD = 'password'.freeze,
|
9
|
+
CLIENT_CREDENTIALS = 'client_credentials'.freeze,
|
10
|
+
REFRESH_TOKEN = 'refresh_token'.freeze
|
11
|
+
].freeze
|
12
|
+
end
|
13
|
+
end
|
@@ -13,6 +13,8 @@ module Doorkeeper
|
|
13
13
|
validates :redirect_uri, redirect_uri: true
|
14
14
|
validates :confidential, inclusion: { in: [true, false] }
|
15
15
|
|
16
|
+
validate :scopes_match_configured, if: :enforce_scopes?
|
17
|
+
|
16
18
|
before_validation :generate_uid, :generate_secret, on: :create
|
17
19
|
|
18
20
|
has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: 'AccessToken'
|
@@ -32,20 +34,15 @@ module Doorkeeper
|
|
32
34
|
where(id: resource_access_tokens.select(:application_id).distinct)
|
33
35
|
end
|
34
36
|
|
35
|
-
#
|
36
|
-
#
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
alias_method :confidential?, :confidential
|
46
|
-
|
47
|
-
def self.supports_confidentiality?
|
48
|
-
column_names.include?('confidential')
|
37
|
+
# Revokes AccessToken and AccessGrant records that have not been revoked and
|
38
|
+
# associated with the specific Application and Resource Owner.
|
39
|
+
#
|
40
|
+
# @param resource_owner [ActiveRecord::Base]
|
41
|
+
# instance of the Resource Owner model
|
42
|
+
#
|
43
|
+
def self.revoke_tokens_and_grants_for(id, resource_owner)
|
44
|
+
AccessToken.revoke_all_for(id, resource_owner)
|
45
|
+
AccessGrant.revoke_all_for(id, resource_owner)
|
49
46
|
end
|
50
47
|
|
51
48
|
private
|
@@ -57,5 +54,16 @@ module Doorkeeper
|
|
57
54
|
def generate_secret
|
58
55
|
self.secret = UniqueToken.generate if secret.blank?
|
59
56
|
end
|
57
|
+
|
58
|
+
def scopes_match_configured
|
59
|
+
if scopes.present? &&
|
60
|
+
!ScopeChecker.valid?(scopes.to_s, Doorkeeper.configuration.scopes)
|
61
|
+
errors.add(:scopes, :not_match_configured)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def enforce_scopes?
|
66
|
+
Doorkeeper.configuration.enforce_configured_scopes?
|
67
|
+
end
|
60
68
|
end
|
61
69
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module Orm
|
5
|
+
module ActiveRecord
|
6
|
+
class StaleRecordsCleaner
|
7
|
+
def initialize(base_scope)
|
8
|
+
@base_scope = base_scope
|
9
|
+
end
|
10
|
+
|
11
|
+
def clean_revoked
|
12
|
+
table = @base_scope.arel_table
|
13
|
+
@base_scope.where.not(revoked_at: nil)
|
14
|
+
.where(table[:revoked_at].lt(Time.current))
|
15
|
+
.delete_all
|
16
|
+
end
|
17
|
+
|
18
|
+
def clean_expired(ttl)
|
19
|
+
table = @base_scope.arel_table
|
20
|
+
@base_scope.where(table[:created_at].lt(Time.current - ttl))
|
21
|
+
.delete_all
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -4,9 +4,7 @@ module Doorkeeper
|
|
4
4
|
def doorkeeper_authorize!(*scopes)
|
5
5
|
@_doorkeeper_scopes = scopes.presence || Doorkeeper.configuration.default_scopes
|
6
6
|
|
7
|
-
unless valid_doorkeeper_token?
|
8
|
-
doorkeeper_render_error
|
9
|
-
end
|
7
|
+
doorkeeper_render_error unless valid_doorkeeper_token?
|
10
8
|
end
|
11
9
|
|
12
10
|
def doorkeeper_unauthorized_render_options(**); end
|
@@ -68,7 +66,7 @@ module Doorkeeper
|
|
68
66
|
end
|
69
67
|
|
70
68
|
def doorkeeper_token
|
71
|
-
@
|
69
|
+
@doorkeeper_token ||= OAuth::Token.authenticate(
|
72
70
|
request,
|
73
71
|
*Doorkeeper.configuration.access_token_methods
|
74
72
|
)
|
@@ -4,6 +4,10 @@ require 'doorkeeper/rails/routes/mapper'
|
|
4
4
|
module Doorkeeper
|
5
5
|
module Rails
|
6
6
|
class Routes # :nodoc:
|
7
|
+
mattr_reader :mapping do
|
8
|
+
{}
|
9
|
+
end
|
10
|
+
|
7
11
|
module Helper
|
8
12
|
def use_doorkeeper(options = {}, &block)
|
9
13
|
Doorkeeper::Rails::Routes.new(self, &block).generate_routes!(options)
|
@@ -19,6 +23,10 @@ module Doorkeeper
|
|
19
23
|
def initialize(routes, &block)
|
20
24
|
@routes = routes
|
21
25
|
@mapping = Mapper.new.map(&block)
|
26
|
+
|
27
|
+
if Doorkeeper.configuration.api_only
|
28
|
+
@mapping.skips.push(:applications, :authorized_applications)
|
29
|
+
end
|
22
30
|
end
|
23
31
|
|
24
32
|
def generate_routes!(options)
|
@@ -36,7 +44,11 @@ module Doorkeeper
|
|
36
44
|
private
|
37
45
|
|
38
46
|
def map_route(name, method)
|
39
|
-
|
47
|
+
return if @mapping.skipped?(name)
|
48
|
+
|
49
|
+
send(method, @mapping[name])
|
50
|
+
|
51
|
+
mapping[name] = @mapping[name]
|
40
52
|
end
|
41
53
|
|
42
54
|
def authorization_routes(mapping)
|
@@ -47,7 +59,7 @@ module Doorkeeper
|
|
47
59
|
as: mapping[:as],
|
48
60
|
controller: mapping[:controllers]
|
49
61
|
) do
|
50
|
-
routes.get
|
62
|
+
routes.get '/native', action: :show, on: :member
|
51
63
|
routes.get '/', action: :new, on: :member
|
52
64
|
end
|
53
65
|
end
|
@@ -85,10 +97,6 @@ module Doorkeeper
|
|
85
97
|
def authorized_applications_routes(mapping)
|
86
98
|
routes.resources :authorized_applications, only: %i[index destroy], controller: mapping[:controllers]
|
87
99
|
end
|
88
|
-
|
89
|
-
def native_authorization_code_route
|
90
|
-
Doorkeeper.configuration.native_authorization_code_route
|
91
|
-
end
|
92
100
|
end
|
93
101
|
end
|
94
102
|
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
namespace :doorkeeper do
|
4
|
+
namespace :db do
|
5
|
+
desc 'Removes stale data from doorkeeper related database tables'
|
6
|
+
task cleanup: [
|
7
|
+
'doorkeeper:db:cleanup:revoked_tokens',
|
8
|
+
'doorkeeper:db:cleanup:expired_tokens',
|
9
|
+
'doorkeeper:db:cleanup:revoked_grants',
|
10
|
+
'doorkeeper:db:cleanup:expired_grants'
|
11
|
+
]
|
12
|
+
|
13
|
+
namespace :cleanup do
|
14
|
+
desc 'Removes stale access tokens'
|
15
|
+
task revoked_tokens: 'doorkeeper:setup' do
|
16
|
+
cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessToken)
|
17
|
+
cleaner.clean_revoked
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Removes expired (TTL passed) access tokens'
|
21
|
+
task expired_tokens: 'doorkeeper:setup' do
|
22
|
+
expirable_tokens = Doorkeeper::AccessToken.where(refresh_token: nil)
|
23
|
+
cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(expirable_tokens)
|
24
|
+
cleaner.clean_expired(Doorkeeper.configuration.access_token_expires_in)
|
25
|
+
end
|
26
|
+
|
27
|
+
desc 'Removes stale access grants'
|
28
|
+
task revoked_grants: 'doorkeeper:setup' do
|
29
|
+
cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
|
30
|
+
cleaner.clean_revoked
|
31
|
+
end
|
32
|
+
|
33
|
+
desc 'Removes expired (TTL passed) access grants'
|
34
|
+
task expired_grants: 'doorkeeper:setup' do
|
35
|
+
cleaner = Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner.new(Doorkeeper::AccessGrant)
|
36
|
+
cleaner.clean_expired(Doorkeeper.configuration.authorization_code_expires_in)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/doorkeeper/request.rb
CHANGED
@@ -1,46 +1,39 @@
|
|
1
|
-
require 'doorkeeper/request/authorization_code'
|
2
|
-
require 'doorkeeper/request/client_credentials'
|
3
|
-
require 'doorkeeper/request/code'
|
4
|
-
require 'doorkeeper/request/password'
|
5
|
-
require 'doorkeeper/request/refresh_token'
|
6
|
-
require 'doorkeeper/request/token'
|
7
|
-
|
8
1
|
module Doorkeeper
|
9
2
|
module Request
|
10
|
-
|
3
|
+
class << self
|
4
|
+
def authorization_strategy(response_type)
|
5
|
+
get_strategy(response_type, authorization_response_types)
|
6
|
+
rescue NameError
|
7
|
+
raise Errors::InvalidAuthorizationStrategy
|
8
|
+
end
|
11
9
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
def token_strategy(grant_type)
|
11
|
+
get_strategy(grant_type, token_grant_types)
|
12
|
+
rescue NameError
|
13
|
+
raise Errors::InvalidTokenStrategy
|
14
|
+
end
|
17
15
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
raise Errors::InvalidTokenStrategy
|
22
|
-
end
|
16
|
+
def get_strategy(grant_or_request_type, available)
|
17
|
+
raise Errors::MissingRequestStrategy if grant_or_request_type.blank?
|
18
|
+
raise NameError unless available.include?(grant_or_request_type.to_s)
|
23
19
|
|
24
|
-
|
25
|
-
|
26
|
-
fail NameError unless available.include?(grant_or_request_type.to_s)
|
27
|
-
strategy_class(grant_or_request_type)
|
28
|
-
end
|
20
|
+
build_strategy_class(grant_or_request_type)
|
21
|
+
end
|
29
22
|
|
30
|
-
|
31
|
-
Doorkeeper.configuration.authorization_response_types
|
32
|
-
end
|
33
|
-
private_class_method :authorization_response_types
|
23
|
+
private
|
34
24
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
25
|
+
def authorization_response_types
|
26
|
+
Doorkeeper.configuration.authorization_response_types
|
27
|
+
end
|
28
|
+
|
29
|
+
def token_grant_types
|
30
|
+
Doorkeeper.configuration.token_grant_types
|
31
|
+
end
|
39
32
|
|
40
|
-
|
41
|
-
|
42
|
-
|
33
|
+
def build_strategy_class(grant_or_request_type)
|
34
|
+
strategy_class_name = grant_or_request_type.to_s.tr(' ', '_').camelize
|
35
|
+
"Doorkeeper::Request::#{strategy_class_name}".constantize
|
36
|
+
end
|
43
37
|
end
|
44
|
-
private_class_method :strategy_class
|
45
38
|
end
|
46
39
|
end
|
data/lib/doorkeeper/version.rb
CHANGED
@@ -1,36 +1,16 @@
|
|
1
1
|
module Doorkeeper
|
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
2
|
def self.gem_version
|
24
3
|
Gem::Version.new VERSION::STRING
|
25
4
|
end
|
26
5
|
|
27
6
|
module VERSION
|
28
7
|
# Semantic versioning
|
29
|
-
MAJOR =
|
30
|
-
MINOR =
|
31
|
-
TINY =
|
8
|
+
MAJOR = 5
|
9
|
+
MINOR = 0
|
10
|
+
TINY = 0
|
11
|
+
PRE = nil
|
32
12
|
|
33
13
|
# Full version number
|
34
|
-
STRING = [MAJOR, MINOR, TINY].compact.join('.')
|
14
|
+
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
|
35
15
|
end
|
36
16
|
end
|