doorkeeper 5.0.0 → 5.1.0
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.
- checksums.yaml +5 -5
- data/.hound.yml +2 -1
- data/.rubocop.yml +37 -4
- data/.travis.yml +16 -21
- data/Appraisals +29 -7
- data/Dangerfile +67 -0
- data/Gemfile +19 -5
- data/NEWS.md +107 -10
- data/README.md +75 -470
- data/Rakefile +10 -8
- data/app/controllers/doorkeeper/application_controller.rb +3 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -13
- data/app/controllers/doorkeeper/applications_controller.rb +21 -7
- data/app/controllers/doorkeeper/authorizations_controller.rb +3 -3
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -0
- data/app/controllers/doorkeeper/token_info_controller.rb +4 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +13 -11
- data/app/helpers/doorkeeper/dashboard_helper.rb +3 -1
- data/app/validators/redirect_uri_validator.rb +7 -2
- data/app/views/doorkeeper/applications/_form.html.erb +6 -0
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
- data/bin/console +16 -0
- data/config/locales/en.yml +1 -0
- data/doorkeeper.gemspec +28 -24
- data/gemfiles/rails_5_0.gemfile +9 -4
- data/gemfiles/rails_5_1.gemfile +9 -4
- data/gemfiles/rails_5_2.gemfile +10 -5
- data/gemfiles/rails_6_0.gemfile +17 -0
- data/gemfiles/rails_master.gemfile +9 -9
- data/lib/doorkeeper/config/option.rb +64 -0
- data/lib/doorkeeper/config.rb +197 -76
- data/lib/doorkeeper/engine.rb +3 -1
- data/lib/doorkeeper/errors.rb +17 -0
- data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
- data/lib/doorkeeper/grape/helpers.rb +5 -3
- data/lib/doorkeeper/helpers/controller.rb +5 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +25 -6
- data/lib/doorkeeper/models/access_token_mixin.rb +68 -22
- data/lib/doorkeeper/models/application_mixin.rb +45 -1
- data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +6 -2
- data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +3 -6
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +4 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +7 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +4 -2
- data/lib/doorkeeper/oauth/authorization/context.rb +2 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +14 -7
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +3 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +8 -4
- data/lib/doorkeeper/oauth/base_request.rb +2 -0
- data/lib/doorkeeper/oauth/base_response.rb +2 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -0
- data/lib/doorkeeper/oauth/client.rb +3 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +7 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +3 -1
- data/lib/doorkeeper/oauth/code_request.rb +2 -0
- data/lib/doorkeeper/oauth/code_response.rb +4 -2
- data/lib/doorkeeper/oauth/error.rb +2 -0
- data/lib/doorkeeper/oauth/error_response.rb +20 -6
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +10 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +25 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +15 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +42 -3
- data/lib/doorkeeper/oauth/invalid_token_response.rb +22 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +13 -5
- data/lib/doorkeeper/oauth/refresh_token_request.rb +15 -4
- data/lib/doorkeeper/oauth/scopes.rb +7 -3
- data/lib/doorkeeper/oauth/token.rb +4 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +76 -8
- data/lib/doorkeeper/oauth/token_request.rb +2 -0
- data/lib/doorkeeper/oauth/token_response.rb +11 -9
- data/lib/doorkeeper/oauth.rb +5 -5
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
- data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
- data/lib/doorkeeper/orm/active_record/application.rb +26 -7
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
- data/lib/doorkeeper/orm/active_record.rb +8 -6
- data/lib/doorkeeper/rails/helpers.rb +5 -1
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
- data/lib/doorkeeper/rails/routes/mapping.rb +9 -7
- data/lib/doorkeeper/rails/routes.rb +19 -12
- data/lib/doorkeeper/rake/db.rake +17 -17
- data/lib/doorkeeper/rake.rb +1 -1
- data/lib/doorkeeper/request/authorization_code.rb +2 -0
- data/lib/doorkeeper/request/client_credentials.rb +2 -0
- data/lib/doorkeeper/request/code.rb +2 -0
- data/lib/doorkeeper/request/password.rb +2 -0
- data/lib/doorkeeper/request/refresh_token.rb +2 -0
- data/lib/doorkeeper/request/strategy.rb +2 -0
- data/lib/doorkeeper/request/token.rb +2 -0
- data/lib/doorkeeper/request.rb +3 -1
- data/lib/doorkeeper/secret_storing/base.rb +64 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
- data/lib/doorkeeper/server.rb +2 -0
- data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
- data/lib/doorkeeper/validations.rb +2 -0
- data/lib/doorkeeper/version.rb +4 -2
- data/lib/doorkeeper.rb +69 -59
- data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
- data/lib/generators/doorkeeper/install_generator.rb +11 -9
- data/lib/generators/doorkeeper/migration_generator.rb +9 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
- data/lib/generators/doorkeeper/templates/initializer.rb +138 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +17 -10
- data/lib/generators/doorkeeper/views_generator.rb +6 -4
- data/spec/controllers/application_metal_controller_spec.rb +24 -10
- data/spec/controllers/applications_controller_spec.rb +76 -78
- data/spec/controllers/authorizations_controller_spec.rb +189 -142
- data/spec/controllers/protected_resources_controller_spec.rb +111 -67
- data/spec/controllers/token_info_controller_spec.rb +14 -12
- data/spec/controllers/tokens_controller_spec.rb +170 -112
- data/spec/dummy/Rakefile +3 -1
- data/spec/dummy/app/controllers/application_controller.rb +3 -1
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +3 -1
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/controllers/home_controller.rb +6 -5
- data/spec/dummy/app/controllers/metal_controller.rb +2 -0
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/config/application.rb +26 -2
- data/spec/dummy/config/boot.rb +2 -4
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/development.rb +2 -0
- data/spec/dummy/config/environments/production.rb +2 -0
- data/spec/dummy/config/environments/test.rb +4 -2
- data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +7 -3
- data/spec/dummy/config/initializers/secret_token.rb +3 -1
- data/spec/dummy/config/initializers/session_store.rb +3 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
- data/spec/dummy/config.ru +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +20 -13
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/script/rails +7 -4
- data/spec/factories.rb +11 -9
- data/spec/generators/application_owner_generator_spec.rb +13 -26
- data/spec/generators/confidential_applications_generator_spec.rb +12 -28
- data/spec/generators/install_generator_spec.rb +19 -14
- data/spec/generators/migration_generator_spec.rb +13 -26
- data/spec/generators/pkce_generator_spec.rb +11 -26
- data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
- data/spec/generators/templates/routes.rb +2 -1
- data/spec/generators/views_generator_spec.rb +14 -12
- data/spec/grape/grape_integration_spec.rb +35 -33
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
- data/spec/lib/config_spec.rb +290 -104
- data/spec/lib/doorkeeper_spec.rb +8 -6
- data/spec/lib/models/expirable_spec.rb +22 -8
- data/spec/lib/models/reusable_spec.rb +40 -0
- data/spec/lib/models/revocable_spec.rb +8 -6
- data/spec/lib/models/scopes_spec.rb +27 -13
- data/spec/lib/models/secret_storable_spec.rb +135 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
- data/spec/lib/oauth/authorization_code_request_spec.rb +43 -17
- data/spec/lib/oauth/base_request_spec.rb +24 -12
- data/spec/lib/oauth/base_response_spec.rb +3 -1
- data/spec/lib/oauth/client/credentials_spec.rb +26 -24
- data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -20
- data/spec/lib/oauth/client_credentials/validation_spec.rb +21 -15
- data/spec/lib/oauth/client_credentials_integration_spec.rb +8 -6
- data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
- data/spec/lib/oauth/client_spec.rb +15 -13
- data/spec/lib/oauth/code_request_spec.rb +10 -8
- data/spec/lib/oauth/code_response_spec.rb +9 -7
- data/spec/lib/oauth/error_response_spec.rb +19 -11
- data/spec/lib/oauth/error_spec.rb +4 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
- data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +124 -93
- data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +95 -34
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
- data/spec/lib/oauth/refresh_token_request_spec.rb +46 -39
- data/spec/lib/oauth/scopes_spec.rb +63 -61
- data/spec/lib/oauth/token_request_spec.rb +80 -25
- data/spec/lib/oauth/token_response_spec.rb +40 -38
- data/spec/lib/oauth/token_spec.rb +64 -45
- data/spec/lib/request/strategy_spec.rb +3 -1
- data/spec/lib/secret_storing/base_spec.rb +60 -0
- data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
- data/spec/lib/secret_storing/plain_spec.rb +44 -0
- data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
- data/spec/lib/server_spec.rb +20 -18
- data/spec/lib/{orm/active_record/stale_records_cleaner_spec.rb → stale_records_cleaner_spec.rb} +28 -18
- data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
- data/spec/models/doorkeeper/access_token_spec.rb +212 -83
- data/spec/models/doorkeeper/application_spec.rb +146 -49
- data/spec/requests/applications/applications_request_spec.rb +100 -68
- data/spec/requests/applications/authorized_applications_spec.rb +20 -18
- data/spec/requests/endpoints/authorization_spec.rb +27 -25
- data/spec/requests/endpoints/token_spec.rb +38 -36
- data/spec/requests/flows/authorization_code_errors_spec.rb +27 -25
- data/spec/requests/flows/authorization_code_spec.rb +260 -158
- data/spec/requests/flows/client_credentials_spec.rb +54 -52
- data/spec/requests/flows/implicit_grant_errors_spec.rb +11 -9
- data/spec/requests/flows/implicit_grant_spec.rb +27 -25
- data/spec/requests/flows/password_spec.rb +64 -56
- data/spec/requests/flows/refresh_token_spec.rb +91 -32
- data/spec/requests/flows/revoke_token_spec.rb +49 -63
- data/spec/requests/flows/skip_authorization_spec.rb +23 -21
- data/spec/requests/protected_resources/metal_spec.rb +7 -5
- data/spec/requests/protected_resources/private_api_spec.rb +37 -35
- data/spec/routing/custom_controller_routes_spec.rb +71 -65
- data/spec/routing/default_routes_spec.rb +22 -20
- data/spec/routing/scoped_routes_spec.rb +20 -18
- data/spec/spec_helper.rb +15 -13
- data/spec/spec_helper_integration.rb +3 -1
- data/spec/support/dependencies/factory_bot.rb +3 -1
- data/spec/support/doorkeeper_rspec.rb +5 -2
- data/spec/support/helpers/access_token_request_helper.rb +3 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -2
- data/spec/support/helpers/config_helper.rb +2 -0
- data/spec/support/helpers/model_helper.rb +11 -5
- data/spec/support/helpers/request_spec_helper.rb +5 -3
- data/spec/support/helpers/url_helper.rb +20 -18
- data/spec/support/http_method_shim.rb +4 -9
- data/spec/support/orm/active_record.rb +3 -1
- data/spec/support/shared/controllers_shared_context.rb +68 -10
- data/spec/support/shared/hashing_shared_context.rb +36 -0
- data/spec/support/shared/models_shared_examples.rb +12 -10
- data/spec/validators/redirect_uri_validator_spec.rb +76 -47
- data/spec/version/version_spec.rb +7 -5
- metadata +70 -21
- data/gemfiles/rails_4_2.gemfile +0 -13
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -10
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class ClientCredentialsRequest < BaseRequest
|
|
@@ -28,13 +30,14 @@ module Doorkeeper
|
|
|
28
30
|
application_scopes = if @client.present?
|
|
29
31
|
@client.application.scopes
|
|
30
32
|
else
|
|
31
|
-
|
|
33
|
+
""
|
|
32
34
|
end
|
|
33
35
|
|
|
34
36
|
ScopeChecker.valid?(
|
|
35
|
-
@request.scopes.to_s,
|
|
36
|
-
@server.scopes,
|
|
37
|
-
application_scopes
|
|
37
|
+
scope_str: @request.scopes.to_s,
|
|
38
|
+
server_scopes: @server.scopes,
|
|
39
|
+
app_scopes: application_scopes,
|
|
40
|
+
grant_type: Doorkeeper::OAuth::CLIENT_CREDENTIALS
|
|
38
41
|
)
|
|
39
42
|
end
|
|
40
43
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class ClientCredentialsRequest < BaseRequest
|
|
@@ -5,7 +7,7 @@ module Doorkeeper
|
|
|
5
7
|
attr_reader :response
|
|
6
8
|
attr_writer :issuer
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
alias error_response response
|
|
9
11
|
|
|
10
12
|
delegate :error, to: :issuer
|
|
11
13
|
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class CodeResponse < BaseResponse
|
|
@@ -21,7 +23,7 @@ module Doorkeeper
|
|
|
21
23
|
elsif response_on_fragment
|
|
22
24
|
Authorization::URIBuilder.uri_with_fragment(
|
|
23
25
|
pre_auth.redirect_uri,
|
|
24
|
-
access_token: auth.token.
|
|
26
|
+
access_token: auth.token.plaintext_token,
|
|
25
27
|
token_type: auth.token.token_type,
|
|
26
28
|
expires_in: auth.token.expires_in_seconds,
|
|
27
29
|
state: pre_auth.state
|
|
@@ -29,7 +31,7 @@ module Doorkeeper
|
|
|
29
31
|
else
|
|
30
32
|
Authorization::URIBuilder.uri_with_query(
|
|
31
33
|
pre_auth.redirect_uri,
|
|
32
|
-
code: auth.token.
|
|
34
|
+
code: auth.token.plaintext_token,
|
|
33
35
|
state: pre_auth.state
|
|
34
36
|
)
|
|
35
37
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class ErrorResponse < BaseResponse
|
|
@@ -25,12 +27,16 @@ module Doorkeeper
|
|
|
25
27
|
{
|
|
26
28
|
error: name,
|
|
27
29
|
error_description: description,
|
|
28
|
-
state: state
|
|
30
|
+
state: state,
|
|
29
31
|
}.reject { |_, v| v.blank? }
|
|
30
32
|
end
|
|
31
33
|
|
|
32
34
|
def status
|
|
33
|
-
:
|
|
35
|
+
if name == :invalid_client
|
|
36
|
+
:unauthorized
|
|
37
|
+
else
|
|
38
|
+
:bad_request
|
|
39
|
+
end
|
|
34
40
|
end
|
|
35
41
|
|
|
36
42
|
def redirectable?
|
|
@@ -48,13 +54,17 @@ module Doorkeeper
|
|
|
48
54
|
|
|
49
55
|
def headers
|
|
50
56
|
{
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
57
|
+
"Cache-Control" => "no-store",
|
|
58
|
+
"Pragma" => "no-cache",
|
|
59
|
+
"Content-Type" => "application/json; charset=utf-8",
|
|
60
|
+
"WWW-Authenticate" => authenticate_info,
|
|
55
61
|
}
|
|
56
62
|
end
|
|
57
63
|
|
|
64
|
+
def raise_exception!
|
|
65
|
+
raise exception_class.new(self), description
|
|
66
|
+
end
|
|
67
|
+
|
|
58
68
|
protected
|
|
59
69
|
|
|
60
70
|
delegate :realm, to: :configuration
|
|
@@ -63,6 +73,10 @@ module Doorkeeper
|
|
|
63
73
|
Doorkeeper.configuration
|
|
64
74
|
end
|
|
65
75
|
|
|
76
|
+
def exception_class
|
|
77
|
+
raise NotImplementedError, "error response must define #exception_class"
|
|
78
|
+
end
|
|
79
|
+
|
|
66
80
|
private
|
|
67
81
|
|
|
68
82
|
def authenticate_info
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class ForbiddenTokenResponse < ErrorResponse
|
|
@@ -16,13 +18,18 @@ module Doorkeeper
|
|
|
16
18
|
|
|
17
19
|
def headers
|
|
18
20
|
headers = super
|
|
19
|
-
headers.delete
|
|
21
|
+
headers.delete "WWW-Authenticate"
|
|
20
22
|
headers
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def description
|
|
24
|
-
|
|
25
|
-
|
|
26
|
+
@description ||= @scopes.map { |s| I18n.t(s, scope: %i[doorkeeper scopes]) }.join("\n")
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
protected
|
|
30
|
+
|
|
31
|
+
def exception_class
|
|
32
|
+
Doorkeeper::Errors::TokenForbidden
|
|
26
33
|
end
|
|
27
34
|
end
|
|
28
35
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
module Helpers
|
|
@@ -5,31 +7,46 @@ module Doorkeeper
|
|
|
5
7
|
class Validator
|
|
6
8
|
attr_reader :parsed_scopes, :scope_str
|
|
7
9
|
|
|
8
|
-
def initialize(scope_str, server_scopes,
|
|
10
|
+
def initialize(scope_str, server_scopes, app_scopes, grant_type)
|
|
9
11
|
@parsed_scopes = OAuth::Scopes.from_string(scope_str)
|
|
10
12
|
@scope_str = scope_str
|
|
11
|
-
@valid_scopes = valid_scopes(server_scopes,
|
|
13
|
+
@valid_scopes = valid_scopes(server_scopes, app_scopes)
|
|
14
|
+
|
|
15
|
+
if grant_type
|
|
16
|
+
@scopes_by_grant_type = Doorkeeper.configuration.scopes_by_grant_type[grant_type.to_sym]
|
|
17
|
+
end
|
|
12
18
|
end
|
|
13
19
|
|
|
14
20
|
def valid?
|
|
15
21
|
scope_str.present? &&
|
|
16
22
|
scope_str !~ /[\n\r\t]/ &&
|
|
17
|
-
@valid_scopes.has_scopes?(parsed_scopes)
|
|
23
|
+
@valid_scopes.has_scopes?(parsed_scopes) &&
|
|
24
|
+
permitted_to_grant_type?
|
|
18
25
|
end
|
|
19
26
|
|
|
20
27
|
private
|
|
21
28
|
|
|
22
|
-
def valid_scopes(server_scopes,
|
|
23
|
-
if
|
|
24
|
-
|
|
29
|
+
def valid_scopes(server_scopes, app_scopes)
|
|
30
|
+
if app_scopes.present?
|
|
31
|
+
app_scopes
|
|
25
32
|
else
|
|
26
33
|
server_scopes
|
|
27
34
|
end
|
|
28
35
|
end
|
|
36
|
+
|
|
37
|
+
def permitted_to_grant_type?
|
|
38
|
+
return true unless @scopes_by_grant_type
|
|
39
|
+
|
|
40
|
+
OAuth::Scopes.from_array(@scopes_by_grant_type)
|
|
41
|
+
.has_scopes?(parsed_scopes)
|
|
42
|
+
end
|
|
29
43
|
end
|
|
30
44
|
|
|
31
|
-
def self.valid?(scope_str
|
|
32
|
-
Validator.new(scope_str,
|
|
45
|
+
def self.valid?(scope_str:, server_scopes:, app_scopes: nil, grant_type: nil)
|
|
46
|
+
Validator.new(scope_str,
|
|
47
|
+
server_scopes,
|
|
48
|
+
app_scopes,
|
|
49
|
+
grant_type).valid?
|
|
33
50
|
end
|
|
34
51
|
end
|
|
35
52
|
end
|
|
@@ -1,12 +1,26 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
module Helpers
|
|
4
6
|
module UniqueToken
|
|
5
7
|
def self.generate(options = {})
|
|
6
|
-
|
|
8
|
+
# Access Token value must be 1*VSCHAR or
|
|
9
|
+
# 1*( ALPHA / DIGIT / "-" / "." / "_" / "~" / "+" / "/" ) *"="
|
|
10
|
+
#
|
|
11
|
+
# @see https://tools.ietf.org/html/rfc6749#appendix-A.12
|
|
12
|
+
# @see https://tools.ietf.org/html/rfc6750#section-2.1
|
|
13
|
+
#
|
|
14
|
+
generator_method = options.delete(:generator) || SecureRandom.method(self.generator_method)
|
|
7
15
|
token_size = options.delete(:size) || 32
|
|
8
16
|
generator_method.call(token_size)
|
|
9
17
|
end
|
|
18
|
+
|
|
19
|
+
# Generator method for default generator class (SecureRandom)
|
|
20
|
+
#
|
|
21
|
+
def self.generator_method
|
|
22
|
+
Doorkeeper.configuration.default_generator_method
|
|
23
|
+
end
|
|
10
24
|
end
|
|
11
25
|
end
|
|
12
26
|
end
|
|
@@ -1,9 +1,32 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "ipaddr"
|
|
4
|
+
|
|
1
5
|
module Doorkeeper
|
|
6
|
+
module IPAddrLoopback
|
|
7
|
+
def loopback?
|
|
8
|
+
case @family
|
|
9
|
+
when Socket::AF_INET
|
|
10
|
+
@addr & 0xff000000 == 0x7f000000
|
|
11
|
+
when Socket::AF_INET6
|
|
12
|
+
@addr == 1
|
|
13
|
+
else
|
|
14
|
+
raise AddressFamilyError, "unsupported address family"
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
# For backward compatibility with old rubies
|
|
20
|
+
if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0")
|
|
21
|
+
IPAddr.send(:include, Doorkeeper::IPAddrLoopback)
|
|
22
|
+
end
|
|
23
|
+
|
|
2
24
|
module OAuth
|
|
3
25
|
module Helpers
|
|
4
26
|
module URIChecker
|
|
5
27
|
def self.valid?(url)
|
|
6
28
|
return true if native_uri?(url)
|
|
29
|
+
|
|
7
30
|
uri = as_uri(url)
|
|
8
31
|
uri.fragment.nil? && !uri.host.nil? && !uri.scheme.nil?
|
|
9
32
|
rescue URI::InvalidURIError
|
|
@@ -14,16 +37,31 @@ module Doorkeeper
|
|
|
14
37
|
url = as_uri(url)
|
|
15
38
|
client_url = as_uri(client_url)
|
|
16
39
|
|
|
17
|
-
|
|
40
|
+
unless client_url.query.nil?
|
|
18
41
|
return false unless query_matches?(url.query, client_url.query)
|
|
42
|
+
|
|
19
43
|
# Clear out queries so rest of URI can be tested. This allows query
|
|
20
44
|
# params to be in the request but order not mattering.
|
|
21
45
|
client_url.query = nil
|
|
22
46
|
end
|
|
47
|
+
|
|
48
|
+
# RFC8252, Paragraph 7.3
|
|
49
|
+
# @see https://tools.ietf.org/html/rfc8252#section-7.3
|
|
50
|
+
if loopback_uri?(url) && loopback_uri?(client_url)
|
|
51
|
+
url.port = nil
|
|
52
|
+
client_url.port = nil
|
|
53
|
+
end
|
|
54
|
+
|
|
23
55
|
url.query = nil
|
|
24
56
|
url == client_url
|
|
25
57
|
end
|
|
26
58
|
|
|
59
|
+
def self.loopback_uri?(uri)
|
|
60
|
+
IPAddr.new(uri.host).loopback?
|
|
61
|
+
rescue IPAddr::Error
|
|
62
|
+
false
|
|
63
|
+
end
|
|
64
|
+
|
|
27
65
|
def self.valid_for_authorization?(url, client_url)
|
|
28
66
|
valid?(url) && client_url.split.any? { |other_url| matches?(url, other_url) }
|
|
29
67
|
end
|
|
@@ -33,10 +71,11 @@ module Doorkeeper
|
|
|
33
71
|
end
|
|
34
72
|
|
|
35
73
|
def self.query_matches?(query, client_query)
|
|
36
|
-
return true if client_query.
|
|
74
|
+
return true if client_query.blank? && query.blank?
|
|
37
75
|
return false if client_query.nil? || query.nil?
|
|
76
|
+
|
|
38
77
|
# Will return true independent of query order
|
|
39
|
-
client_query.split(
|
|
78
|
+
client_query.split("&").sort == query.split("&").sort
|
|
40
79
|
end
|
|
41
80
|
|
|
42
81
|
def self.native_uri?(url)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class InvalidTokenResponse < ErrorResponse
|
|
@@ -20,10 +22,30 @@ module Doorkeeper
|
|
|
20
22
|
@reason = attributes[:reason] || :unknown
|
|
21
23
|
end
|
|
22
24
|
|
|
25
|
+
def status
|
|
26
|
+
:unauthorized
|
|
27
|
+
end
|
|
28
|
+
|
|
23
29
|
def description
|
|
24
30
|
scope = { scope: %i[doorkeeper errors messages invalid_token] }
|
|
25
31
|
@description ||= I18n.translate @reason, scope
|
|
26
32
|
end
|
|
33
|
+
|
|
34
|
+
protected
|
|
35
|
+
|
|
36
|
+
def exception_class
|
|
37
|
+
errors_mapping.fetch(reason)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
private
|
|
41
|
+
|
|
42
|
+
def errors_mapping
|
|
43
|
+
{
|
|
44
|
+
expired: Doorkeeper::Errors::TokenExpired,
|
|
45
|
+
revoked: Doorkeeper::Errors::TokenRevoked,
|
|
46
|
+
unknown: Doorkeeper::Errors::TokenUnknown,
|
|
47
|
+
}
|
|
48
|
+
end
|
|
27
49
|
end
|
|
28
50
|
end
|
|
29
51
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class PasswordAccessTokenRequest < BaseRequest
|
|
@@ -30,7 +32,12 @@ module Doorkeeper
|
|
|
30
32
|
client_scopes = client.try(:scopes)
|
|
31
33
|
return true if scopes.blank?
|
|
32
34
|
|
|
33
|
-
ScopeChecker.valid?(
|
|
35
|
+
ScopeChecker.valid?(
|
|
36
|
+
scope_str: scopes.to_s,
|
|
37
|
+
server_scopes: server.scopes,
|
|
38
|
+
app_scopes: client_scopes,
|
|
39
|
+
grant_type: grant_type
|
|
40
|
+
)
|
|
34
41
|
end
|
|
35
42
|
|
|
36
43
|
def validate_resource_owner
|
|
@@ -38,7 +45,7 @@ module Doorkeeper
|
|
|
38
45
|
end
|
|
39
46
|
|
|
40
47
|
def validate_client
|
|
41
|
-
!parameters[:client_id] ||
|
|
48
|
+
!parameters[:client_id] || client.present?
|
|
42
49
|
end
|
|
43
50
|
end
|
|
44
51
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class PreAuthorization
|
|
@@ -48,7 +50,7 @@ module Doorkeeper
|
|
|
48
50
|
response_type: response_type,
|
|
49
51
|
scope: scope,
|
|
50
52
|
client_name: client.name,
|
|
51
|
-
status: I18n.t(
|
|
53
|
+
status: I18n.t("doorkeeper.pre_authorization.status"),
|
|
52
54
|
}
|
|
53
55
|
end
|
|
54
56
|
|
|
@@ -75,12 +77,17 @@ module Doorkeeper
|
|
|
75
77
|
return true if scope.blank?
|
|
76
78
|
|
|
77
79
|
Helpers::ScopeChecker.valid?(
|
|
78
|
-
scope,
|
|
79
|
-
server.scopes,
|
|
80
|
-
client.application.scopes
|
|
80
|
+
scope_str: scope,
|
|
81
|
+
server_scopes: server.scopes,
|
|
82
|
+
app_scopes: client.application.scopes,
|
|
83
|
+
grant_type: grant_type
|
|
81
84
|
)
|
|
82
85
|
end
|
|
83
86
|
|
|
87
|
+
def grant_type
|
|
88
|
+
response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
|
|
89
|
+
end
|
|
90
|
+
|
|
84
91
|
def validate_redirect_uri
|
|
85
92
|
return false if redirect_uri.blank?
|
|
86
93
|
|
|
@@ -91,7 +98,8 @@ module Doorkeeper
|
|
|
91
98
|
end
|
|
92
99
|
|
|
93
100
|
def validate_code_challenge_method
|
|
94
|
-
|
|
101
|
+
code_challenge.blank? ||
|
|
102
|
+
(code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
|
|
95
103
|
end
|
|
96
104
|
end
|
|
97
105
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class RefreshTokenRequest < BaseRequest
|
|
@@ -56,7 +58,7 @@ module Doorkeeper
|
|
|
56
58
|
resource_owner_id: refresh_token.resource_owner_id,
|
|
57
59
|
scopes: scopes.to_s,
|
|
58
60
|
expires_in: access_token_expires_in,
|
|
59
|
-
use_refresh_token: true
|
|
61
|
+
use_refresh_token: true,
|
|
60
62
|
}.tap do |attributes|
|
|
61
63
|
if refresh_token_revoked_on_use?
|
|
62
64
|
attributes[:previous_refresh_token] = refresh_token.refresh_token
|
|
@@ -82,16 +84,25 @@ module Doorkeeper
|
|
|
82
84
|
end
|
|
83
85
|
|
|
84
86
|
def validate_client
|
|
85
|
-
|
|
87
|
+
return true if credentials.blank?
|
|
88
|
+
|
|
89
|
+
client.present?
|
|
86
90
|
end
|
|
87
91
|
|
|
92
|
+
# @see https://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-1.5
|
|
93
|
+
#
|
|
88
94
|
def validate_client_match
|
|
89
|
-
|
|
95
|
+
return true if refresh_token.application_id.blank?
|
|
96
|
+
|
|
97
|
+
client && refresh_token.application_id == client.id
|
|
90
98
|
end
|
|
91
99
|
|
|
92
100
|
def validate_scope
|
|
93
101
|
if @original_scopes.present?
|
|
94
|
-
ScopeChecker.valid?(
|
|
102
|
+
ScopeChecker.valid?(
|
|
103
|
+
scope_str: @original_scopes,
|
|
104
|
+
server_scopes: refresh_token.scopes
|
|
105
|
+
)
|
|
95
106
|
else
|
|
96
107
|
true
|
|
97
108
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class Scopes
|
|
@@ -5,7 +7,7 @@ module Doorkeeper
|
|
|
5
7
|
include Comparable
|
|
6
8
|
|
|
7
9
|
def self.from_string(string)
|
|
8
|
-
string ||=
|
|
10
|
+
string ||= ""
|
|
9
11
|
new.tap do |scope|
|
|
10
12
|
scope.add(*string.split)
|
|
11
13
|
end
|
|
@@ -37,13 +39,15 @@ module Doorkeeper
|
|
|
37
39
|
end
|
|
38
40
|
|
|
39
41
|
def to_s
|
|
40
|
-
@scopes.join(
|
|
42
|
+
@scopes.join(" ")
|
|
41
43
|
end
|
|
42
44
|
|
|
43
|
-
def
|
|
45
|
+
def scopes?(scopes)
|
|
44
46
|
scopes.all? { |scope| exists?(scope) }
|
|
45
47
|
end
|
|
46
48
|
|
|
49
|
+
alias has_scopes? scopes?
|
|
50
|
+
|
|
47
51
|
def +(other)
|
|
48
52
|
self.class.from_array(all + to_array(other))
|
|
49
53
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module Doorkeeper
|
|
2
4
|
module OAuth
|
|
3
5
|
class Token
|
|
@@ -53,11 +55,11 @@ module Doorkeeper
|
|
|
53
55
|
end
|
|
54
56
|
|
|
55
57
|
def token_from_header(header, pattern)
|
|
56
|
-
header.gsub pattern,
|
|
58
|
+
header.gsub pattern, ""
|
|
57
59
|
end
|
|
58
60
|
|
|
59
61
|
def match?(header, pattern)
|
|
60
|
-
header
|
|
62
|
+
header&.match(pattern)
|
|
61
63
|
end
|
|
62
64
|
end
|
|
63
65
|
end
|