doorkeeper 3.1.0 → 5.6.2
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 +5 -5
- data/CHANGELOG.md +1079 -0
- data/README.md +114 -326
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +7 -6
- data/app/controllers/doorkeeper/application_metal_controller.rb +9 -12
- data/app/controllers/doorkeeper/applications_controller.rb +66 -21
- data/app/controllers/doorkeeper/authorizations_controller.rb +100 -18
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +23 -4
- data/app/controllers/doorkeeper/token_info_controller.rb +16 -4
- data/app/controllers/doorkeeper/tokens_controller.rb +138 -22
- data/app/helpers/doorkeeper/dashboard_helper.rb +15 -9
- data/app/views/doorkeeper/applications/_delete_form.html.erb +4 -3
- data/app/views/doorkeeper/applications/_form.html.erb +33 -21
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +18 -6
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +40 -16
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
- data/app/views/doorkeeper/authorizations/new.html.erb +17 -11
- 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 +16 -14
- data/config/locales/en.yml +37 -9
- data/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/lib/doorkeeper/config/option.rb +82 -0
- data/lib/doorkeeper/config/validations.rb +53 -0
- data/lib/doorkeeper/config.rb +602 -142
- data/lib/doorkeeper/engine.rb +22 -7
- data/lib/doorkeeper/errors.rb +37 -10
- data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
- data/lib/doorkeeper/grant_flow/flow.rb +44 -0
- data/lib/doorkeeper/grant_flow/registry.rb +50 -0
- data/lib/doorkeeper/grant_flow.rb +45 -0
- data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
- data/lib/doorkeeper/grape/helpers.rb +24 -12
- data/lib/doorkeeper/helpers/controller.rb +49 -27
- data/lib/doorkeeper/models/access_grant_mixin.rb +99 -16
- data/lib/doorkeeper/models/access_token_mixin.rb +386 -77
- data/lib/doorkeeper/models/application_mixin.rb +73 -30
- data/lib/doorkeeper/models/concerns/accessible.rb +6 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +20 -6
- data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
- data/lib/doorkeeper/models/concerns/orderable.rb +15 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +4 -2
- data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +13 -2
- data/lib/doorkeeper/models/concerns/scopes.rb +12 -2
- data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +48 -12
- data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +72 -28
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +22 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +64 -14
- data/lib/doorkeeper/oauth/base_request.rb +66 -0
- data/lib/doorkeeper/oauth/base_response.rb +31 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +23 -10
- data/lib/doorkeeper/oauth/client.rb +10 -12
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +48 -4
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +17 -9
- data/lib/doorkeeper/oauth/client_credentials/validator.rb +55 -0
- data/lib/doorkeeper/oauth/client_credentials_request.rb +14 -15
- data/lib/doorkeeper/oauth/code_request.rb +8 -12
- data/lib/doorkeeper/oauth/code_response.rb +31 -19
- data/lib/doorkeeper/oauth/error.rb +5 -3
- data/lib/doorkeeper/oauth/error_response.rb +41 -20
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +11 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +24 -19
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +55 -4
- data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
- data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +31 -5
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +46 -18
- data/lib/doorkeeper/oauth/pre_authorization.rb +135 -26
- data/lib/doorkeeper/oauth/refresh_token_request.rb +67 -30
- data/lib/doorkeeper/oauth/scopes.rb +26 -12
- data/lib/doorkeeper/oauth/token.rb +28 -25
- data/lib/doorkeeper/oauth/token_introspection.rb +202 -0
- data/lib/doorkeeper/oauth/token_request.rb +8 -21
- data/lib/doorkeeper/oauth/token_response.rb +14 -10
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/access_grant.rb +6 -4
- data/lib/doorkeeper/orm/active_record/access_token.rb +5 -17
- data/lib/doorkeeper/orm/active_record/application.rb +6 -20
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +69 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +81 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +214 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +33 -0
- data/lib/doorkeeper/orm/active_record.rb +36 -26
- data/lib/doorkeeper/rails/helpers.rb +14 -15
- data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
- data/lib/doorkeeper/rails/routes/mapper.rb +4 -2
- data/lib/doorkeeper/rails/routes/mapping.rb +10 -8
- data/lib/doorkeeper/rails/routes/registry.rb +45 -0
- data/lib/doorkeeper/rails/routes.rb +45 -28
- 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 +12 -4
- data/lib/doorkeeper/request/client_credentials.rb +3 -3
- data/lib/doorkeeper/request/code.rb +1 -1
- data/lib/doorkeeper/request/password.rb +5 -4
- data/lib/doorkeeper/request/refresh_token.rb +6 -5
- data/lib/doorkeeper/request/strategy.rb +4 -2
- data/lib/doorkeeper/request/token.rb +1 -1
- data/lib/doorkeeper/request.rb +62 -29
- 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 +9 -19
- data/lib/doorkeeper/stale_records_cleaner.rb +24 -0
- data/lib/doorkeeper/validations.rb +5 -2
- data/lib/doorkeeper/version.rb +12 -1
- data/lib/doorkeeper.rb +112 -56
- data/lib/generators/doorkeeper/application_owner_generator.rb +28 -13
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
- data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/lib/generators/doorkeeper/install_generator.rb +19 -9
- data/lib/generators/doorkeeper/migration_generator.rb +27 -10
- data/lib/generators/doorkeeper/pkce_generator.rb +33 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +41 -0
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +9 -0
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
- data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +417 -32
- data/lib/generators/doorkeeper/templates/migration.rb.erb +88 -0
- data/lib/generators/doorkeeper/views_generator.rb +8 -4
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +163 -280
- data/.gitignore +0 -14
- data/.hound.yml +0 -13
- data/.rspec +0 -1
- data/.travis.yml +0 -22
- data/CONTRIBUTING.md +0 -45
- data/Gemfile +0 -10
- data/NEWS.md +0 -525
- data/RELEASING.md +0 -17
- data/Rakefile +0 -20
- data/app/validators/redirect_uri_validator.rb +0 -34
- data/doorkeeper.gemspec +0 -27
- data/lib/doorkeeper/oauth/client/methods.rb +0 -18
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
- data/lib/doorkeeper/oauth/request_concern.rb +0 -48
- data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +0 -7
- data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
- data/lib/generators/doorkeeper/templates/migration.rb +0 -50
- data/spec/controllers/applications_controller_spec.rb +0 -58
- data/spec/controllers/authorizations_controller_spec.rb +0 -203
- data/spec/controllers/protected_resources_controller_spec.rb +0 -271
- data/spec/controllers/token_info_controller_spec.rb +0 -52
- data/spec/controllers/tokens_controller_spec.rb +0 -88
- data/spec/dummy/Rakefile +0 -7
- data/spec/dummy/app/controllers/application_controller.rb +0 -3
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -7
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -12
- data/spec/dummy/app/controllers/home_controller.rb +0 -17
- data/spec/dummy/app/controllers/metal_controller.rb +0 -11
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -11
- data/spec/dummy/app/helpers/application_helper.rb +0 -5
- data/spec/dummy/app/models/user.rb +0 -9
- data/spec/dummy/app/views/home/index.html.erb +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +0 -14
- data/spec/dummy/config/application.rb +0 -57
- data/spec/dummy/config/boot.rb +0 -9
- data/spec/dummy/config/database.yml +0 -15
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -29
- data/spec/dummy/config/environments/production.rb +0 -62
- data/spec/dummy/config/environments/test.rb +0 -55
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
- data/spec/dummy/config/initializers/doorkeeper.rb +0 -96
- data/spec/dummy/config/initializers/secret_token.rb +0 -9
- data/spec/dummy/config/initializers/session_store.rb +0 -8
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
- data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -52
- data/spec/dummy/config.ru +0 -4
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -9
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -5
- data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
- data/spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb +0 -7
- data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
- data/spec/dummy/db/schema.rb +0 -66
- data/spec/dummy/public/404.html +0 -26
- data/spec/dummy/public/422.html +0 -26
- data/spec/dummy/public/500.html +0 -26
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +0 -6
- data/spec/factories.rb +0 -26
- data/spec/generators/application_owner_generator_spec.rb +0 -22
- data/spec/generators/install_generator_spec.rb +0 -31
- data/spec/generators/migration_generator_spec.rb +0 -20
- data/spec/generators/templates/routes.rb +0 -3
- data/spec/generators/views_generator_spec.rb +0 -27
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -24
- data/spec/lib/config_spec.rb +0 -317
- data/spec/lib/doorkeeper_spec.rb +0 -28
- data/spec/lib/models/expirable_spec.rb +0 -51
- data/spec/lib/models/revocable_spec.rb +0 -36
- data/spec/lib/models/scopes_spec.rb +0 -43
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -42
- data/spec/lib/oauth/authorization_code_request_spec.rb +0 -80
- data/spec/lib/oauth/client/credentials_spec.rb +0 -47
- data/spec/lib/oauth/client/methods_spec.rb +0 -54
- data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -44
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -86
- data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -54
- data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
- data/spec/lib/oauth/client_credentials_request_spec.rb +0 -104
- data/spec/lib/oauth/client_spec.rb +0 -39
- data/spec/lib/oauth/code_request_spec.rb +0 -45
- data/spec/lib/oauth/error_response_spec.rb +0 -61
- data/spec/lib/oauth/error_spec.rb +0 -23
- data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -23
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -64
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -20
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -104
- data/spec/lib/oauth/invalid_token_response_spec.rb +0 -28
- data/spec/lib/oauth/password_access_token_request_spec.rb +0 -90
- data/spec/lib/oauth/pre_authorization_spec.rb +0 -155
- data/spec/lib/oauth/refresh_token_request_spec.rb +0 -123
- data/spec/lib/oauth/scopes_spec.rb +0 -123
- data/spec/lib/oauth/token_request_spec.rb +0 -98
- data/spec/lib/oauth/token_response_spec.rb +0 -85
- data/spec/lib/oauth/token_spec.rb +0 -109
- data/spec/lib/request/strategy_spec.rb +0 -53
- data/spec/lib/server_spec.rb +0 -52
- data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
- data/spec/models/doorkeeper/access_token_spec.rb +0 -350
- data/spec/models/doorkeeper/application_spec.rb +0 -187
- data/spec/requests/applications/applications_request_spec.rb +0 -94
- data/spec/requests/applications/authorized_applications_spec.rb +0 -30
- data/spec/requests/endpoints/authorization_spec.rb +0 -72
- data/spec/requests/endpoints/token_spec.rb +0 -64
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -66
- data/spec/requests/flows/authorization_code_spec.rb +0 -156
- data/spec/requests/flows/client_credentials_spec.rb +0 -58
- data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -32
- data/spec/requests/flows/implicit_grant_spec.rb +0 -61
- data/spec/requests/flows/password_spec.rb +0 -94
- data/spec/requests/flows/refresh_token_spec.rb +0 -104
- data/spec/requests/flows/revoke_token_spec.rb +0 -143
- data/spec/requests/flows/skip_authorization_spec.rb +0 -59
- data/spec/requests/protected_resources/metal_spec.rb +0 -14
- data/spec/requests/protected_resources/private_api_spec.rb +0 -81
- data/spec/routing/custom_controller_routes_spec.rb +0 -71
- data/spec/routing/default_routes_spec.rb +0 -35
- data/spec/routing/scoped_routes_spec.rb +0 -31
- data/spec/spec_helper.rb +0 -2
- data/spec/spec_helper_integration.rb +0 -56
- data/spec/support/dependencies/factory_girl.rb +0 -2
- data/spec/support/helpers/access_token_request_helper.rb +0 -11
- data/spec/support/helpers/authorization_request_helper.rb +0 -41
- data/spec/support/helpers/config_helper.rb +0 -9
- data/spec/support/helpers/model_helper.rb +0 -45
- data/spec/support/helpers/request_spec_helper.rb +0 -76
- data/spec/support/helpers/url_helper.rb +0 -55
- data/spec/support/orm/active_record.rb +0 -3
- data/spec/support/shared/controllers_shared_context.rb +0 -60
- data/spec/support/shared/models_shared_examples.rb +0 -52
- data/spec/validators/redirect_uri_validator_spec.rb +0 -78
data/lib/doorkeeper/engine.rb
CHANGED
@@ -1,13 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
class Engine < Rails::Engine
|
3
5
|
initializer "doorkeeper.params.filter" do |app|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
initializer "doorkeeper.locales" do |app|
|
8
|
-
if app.config.i18n.fallbacks.blank?
|
9
|
-
app.config.i18n.fallbacks = [:en]
|
10
|
-
end
|
6
|
+
parameters = %w[client_secret authentication_token access_token refresh_token]
|
7
|
+
parameters << "code" if Doorkeeper.config.grant_flows.include?("authorization_code")
|
8
|
+
app.config.filter_parameters << /^(#{Regexp.union(parameters)})$/
|
11
9
|
end
|
12
10
|
|
13
11
|
initializer "doorkeeper.routes" do
|
@@ -19,5 +17,22 @@ module Doorkeeper
|
|
19
17
|
include Doorkeeper::Rails::Helpers
|
20
18
|
end
|
21
19
|
end
|
20
|
+
|
21
|
+
config.to_prepare do
|
22
|
+
Doorkeeper.setup
|
23
|
+
end
|
24
|
+
|
25
|
+
if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
|
26
|
+
initializer "doorkeeper.assets.precompile" do |app|
|
27
|
+
# Force users to use:
|
28
|
+
# //= link doorkeeper/admin/application.css
|
29
|
+
# in Doorkeeper 5 for Sprockets 4 instead of precompile.
|
30
|
+
# Add note to official docs & Wiki
|
31
|
+
app.config.assets.precompile += %w[
|
32
|
+
doorkeeper/application.css
|
33
|
+
doorkeeper/admin/application.css
|
34
|
+
]
|
35
|
+
end
|
36
|
+
end
|
22
37
|
end
|
23
38
|
end
|
data/lib/doorkeeper/errors.rb
CHANGED
@@ -1,27 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Errors
|
3
5
|
class DoorkeeperError < StandardError
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
end
|
8
|
-
|
9
|
-
class InvalidTokenReuse < DoorkeeperError
|
6
|
+
def type
|
7
|
+
message
|
8
|
+
end
|
10
9
|
end
|
11
10
|
|
12
11
|
class InvalidGrantReuse < DoorkeeperError
|
12
|
+
def type
|
13
|
+
:invalid_grant
|
14
|
+
end
|
13
15
|
end
|
14
16
|
|
15
17
|
class InvalidTokenStrategy < DoorkeeperError
|
18
|
+
def type
|
19
|
+
:unsupported_grant_type
|
20
|
+
end
|
16
21
|
end
|
17
22
|
|
18
|
-
class
|
19
|
-
|
23
|
+
class MissingRequiredParameter < DoorkeeperError
|
24
|
+
attr_reader :missing_param
|
25
|
+
|
26
|
+
def initialize(missing_param)
|
27
|
+
super
|
28
|
+
@missing_param = missing_param
|
29
|
+
end
|
20
30
|
|
21
|
-
|
31
|
+
def type
|
32
|
+
:invalid_request
|
33
|
+
end
|
22
34
|
end
|
23
35
|
|
24
|
-
class
|
36
|
+
class BaseResponseError < DoorkeeperError
|
37
|
+
attr_reader :response
|
38
|
+
|
39
|
+
def initialize(response)
|
40
|
+
@response = response
|
41
|
+
end
|
25
42
|
end
|
43
|
+
|
44
|
+
UnableToGenerateToken = Class.new(DoorkeeperError)
|
45
|
+
TokenGeneratorNotFound = Class.new(DoorkeeperError)
|
46
|
+
NoOrmCleaner = Class.new(DoorkeeperError)
|
47
|
+
|
48
|
+
InvalidToken = Class.new(BaseResponseError)
|
49
|
+
TokenExpired = Class.new(InvalidToken)
|
50
|
+
TokenRevoked = Class.new(InvalidToken)
|
51
|
+
TokenUnknown = Class.new(InvalidToken)
|
52
|
+
TokenForbidden = Class.new(InvalidToken)
|
26
53
|
end
|
27
54
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module GrantFlow
|
5
|
+
class Flow
|
6
|
+
attr_reader :name, :grant_type_matches, :grant_type_strategy,
|
7
|
+
:response_type_matches, :response_type_strategy,
|
8
|
+
:response_mode_matches
|
9
|
+
|
10
|
+
def initialize(name, **options)
|
11
|
+
@name = name
|
12
|
+
@grant_type_matches = options[:grant_type_matches]
|
13
|
+
@grant_type_strategy = options[:grant_type_strategy]
|
14
|
+
@response_type_matches = options[:response_type_matches]
|
15
|
+
@response_type_strategy = options[:response_type_strategy]
|
16
|
+
@response_mode_matches = options[:response_mode_matches]
|
17
|
+
end
|
18
|
+
|
19
|
+
def handles_grant_type?
|
20
|
+
grant_type_matches.present?
|
21
|
+
end
|
22
|
+
|
23
|
+
def handles_response_type?
|
24
|
+
response_type_matches.present?
|
25
|
+
end
|
26
|
+
|
27
|
+
def matches_grant_type?(value)
|
28
|
+
grant_type_matches === value
|
29
|
+
end
|
30
|
+
|
31
|
+
def matches_response_type?(value)
|
32
|
+
response_type_matches === value
|
33
|
+
end
|
34
|
+
|
35
|
+
def default_response_mode
|
36
|
+
response_mode_matches[0]
|
37
|
+
end
|
38
|
+
|
39
|
+
def matches_response_mode?(value)
|
40
|
+
response_mode_matches.include?(value)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module GrantFlow
|
5
|
+
module Registry
|
6
|
+
mattr_accessor :flows
|
7
|
+
self.flows = {}
|
8
|
+
|
9
|
+
mattr_accessor :aliases
|
10
|
+
self.aliases = {}
|
11
|
+
|
12
|
+
# Allows to register custom OAuth grant flow so that Doorkeeper
|
13
|
+
# could recognize and process it.
|
14
|
+
#
|
15
|
+
def register(name_or_flow, **options)
|
16
|
+
unless name_or_flow.is_a?(Doorkeeper::GrantFlow::Flow)
|
17
|
+
name_or_flow = Flow.new(name_or_flow, **options)
|
18
|
+
end
|
19
|
+
|
20
|
+
flow_key = name_or_flow.name.to_sym
|
21
|
+
|
22
|
+
if flows.key?(flow_key)
|
23
|
+
::Kernel.warn <<~WARNING
|
24
|
+
[DOORKEEPER] '#{flow_key}' grant flow already registered and will be overridden
|
25
|
+
in #{caller(1..1).first}
|
26
|
+
WARNING
|
27
|
+
end
|
28
|
+
|
29
|
+
flows[flow_key] = name_or_flow
|
30
|
+
end
|
31
|
+
|
32
|
+
# Allows to register aliases that could be used in `grant_flows`
|
33
|
+
# configuration option. It is possible to have aliases like 1:1 or
|
34
|
+
# 1:N, i.e. "implicit_oidc" => ['token', 'id_token', 'id_token token'].
|
35
|
+
#
|
36
|
+
def register_alias(alias_name, **options)
|
37
|
+
aliases[alias_name.to_sym] = Array.wrap(options.fetch(:as))
|
38
|
+
end
|
39
|
+
|
40
|
+
def expand_alias(alias_name)
|
41
|
+
aliases.fetch(alias_name.to_sym, [])
|
42
|
+
end
|
43
|
+
|
44
|
+
# [NOTE]: make it to use #fetch after removing fallbacks
|
45
|
+
def get(name)
|
46
|
+
flows[name.to_sym]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "doorkeeper/grant_flow/flow"
|
4
|
+
require "doorkeeper/grant_flow/fallback_flow"
|
5
|
+
require "doorkeeper/grant_flow/registry"
|
6
|
+
|
7
|
+
module Doorkeeper
|
8
|
+
module GrantFlow
|
9
|
+
extend Registry
|
10
|
+
|
11
|
+
register(
|
12
|
+
:implicit,
|
13
|
+
response_type_matches: "token",
|
14
|
+
response_mode_matches: %w[fragment form_post],
|
15
|
+
response_type_strategy: Doorkeeper::Request::Token,
|
16
|
+
)
|
17
|
+
|
18
|
+
register(
|
19
|
+
:authorization_code,
|
20
|
+
response_type_matches: "code",
|
21
|
+
response_mode_matches: %w[query fragment form_post],
|
22
|
+
response_type_strategy: Doorkeeper::Request::Code,
|
23
|
+
grant_type_matches: "authorization_code",
|
24
|
+
grant_type_strategy: Doorkeeper::Request::AuthorizationCode,
|
25
|
+
)
|
26
|
+
|
27
|
+
register(
|
28
|
+
:client_credentials,
|
29
|
+
grant_type_matches: "client_credentials",
|
30
|
+
grant_type_strategy: Doorkeeper::Request::ClientCredentials,
|
31
|
+
)
|
32
|
+
|
33
|
+
register(
|
34
|
+
:password,
|
35
|
+
grant_type_matches: "password",
|
36
|
+
grant_type_strategy: Doorkeeper::Request::Password,
|
37
|
+
)
|
38
|
+
|
39
|
+
register(
|
40
|
+
:refresh_token,
|
41
|
+
grant_type_matches: "refresh_token",
|
42
|
+
grant_type_strategy: Doorkeeper::Request::RefreshToken,
|
43
|
+
)
|
44
|
+
end
|
45
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Grape
|
3
5
|
class AuthorizationDecorator < SimpleDelegator
|
@@ -7,10 +9,10 @@ module Doorkeeper
|
|
7
9
|
|
8
10
|
def authorization
|
9
11
|
env = __getobj__.env
|
10
|
-
env[
|
11
|
-
env[
|
12
|
-
env[
|
13
|
-
env[
|
12
|
+
env["HTTP_AUTHORIZATION"] ||
|
13
|
+
env["X-HTTP_AUTHORIZATION"] ||
|
14
|
+
env["X_HTTP_AUTHORIZATION"] ||
|
15
|
+
env["REDIRECT_X_HTTP_AUTHORIZATION"]
|
14
16
|
end
|
15
17
|
end
|
16
18
|
end
|
@@ -1,17 +1,24 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "doorkeeper/grape/authorization_decorator"
|
2
4
|
|
3
5
|
module Doorkeeper
|
4
6
|
module Grape
|
7
|
+
# Doorkeeper helpers for Grape applications.
|
8
|
+
# Provides helpers for endpoints authorization based on defined set of scopes.
|
5
9
|
module Helpers
|
10
|
+
# These helpers are for grape >= 0.10
|
6
11
|
extend ::Grape::API::Helpers
|
7
12
|
include Doorkeeper::Rails::Helpers
|
8
13
|
|
9
14
|
# endpoint specific scopes > parameter scopes > default scopes
|
10
15
|
def doorkeeper_authorize!(*scopes)
|
11
|
-
endpoint_scopes =
|
16
|
+
endpoint_scopes = endpoint.route_setting(:scopes) ||
|
17
|
+
endpoint.options[:route_options][:scopes]
|
18
|
+
|
12
19
|
scopes = if endpoint_scopes
|
13
20
|
Doorkeeper::OAuth::Scopes.from_array(endpoint_scopes)
|
14
|
-
elsif scopes
|
21
|
+
elsif scopes.present?
|
15
22
|
Doorkeeper::OAuth::Scopes.from_array(scopes)
|
16
23
|
end
|
17
24
|
|
@@ -19,28 +26,33 @@ module Doorkeeper
|
|
19
26
|
end
|
20
27
|
|
21
28
|
def doorkeeper_render_error_with(error)
|
22
|
-
status_code =
|
23
|
-
when :unauthorized
|
24
|
-
401
|
25
|
-
when :forbidden
|
26
|
-
403
|
27
|
-
end
|
28
|
-
|
29
|
+
status_code = error_status_codes[error.status]
|
29
30
|
error!({ error: error.description }, status_code, error.headers)
|
30
31
|
end
|
31
32
|
|
32
33
|
private
|
33
34
|
|
35
|
+
def endpoint
|
36
|
+
env["api.endpoint"]
|
37
|
+
end
|
38
|
+
|
34
39
|
def doorkeeper_token
|
35
|
-
@
|
40
|
+
@doorkeeper_token ||= OAuth::Token.authenticate(
|
36
41
|
decorated_request,
|
37
|
-
*Doorkeeper.
|
42
|
+
*Doorkeeper.config.access_token_methods,
|
38
43
|
)
|
39
44
|
end
|
40
45
|
|
41
46
|
def decorated_request
|
42
47
|
AuthorizationDecorator.new(request)
|
43
48
|
end
|
49
|
+
|
50
|
+
def error_status_codes
|
51
|
+
{
|
52
|
+
unauthorized: 401,
|
53
|
+
forbidden: 403,
|
54
|
+
}
|
55
|
+
end
|
44
56
|
end
|
45
57
|
end
|
46
58
|
end
|
@@ -1,66 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Define methods that can be called in any controller that inherits from
|
4
|
+
# Doorkeeper::ApplicationMetalController or Doorkeeper::ApplicationController
|
1
5
|
module Doorkeeper
|
2
6
|
module Helpers
|
7
|
+
# Rails controller helpers.
|
8
|
+
#
|
3
9
|
module Controller
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
6
10
|
private
|
7
11
|
|
12
|
+
# :doc:
|
8
13
|
def authenticate_resource_owner!
|
9
14
|
current_resource_owner
|
10
15
|
end
|
11
16
|
|
17
|
+
# :doc:
|
12
18
|
def current_resource_owner
|
13
|
-
|
19
|
+
return @current_resource_owner if defined?(@current_resource_owner)
|
20
|
+
|
21
|
+
@current_resource_owner ||= begin
|
22
|
+
instance_eval(&Doorkeeper.config.authenticate_resource_owner)
|
23
|
+
end
|
14
24
|
end
|
15
25
|
|
16
26
|
def resource_owner_from_credentials
|
17
|
-
instance_eval(&Doorkeeper.
|
27
|
+
instance_eval(&Doorkeeper.config.resource_owner_from_credentials)
|
18
28
|
end
|
19
29
|
|
30
|
+
# :doc:
|
20
31
|
def authenticate_admin!
|
21
|
-
instance_eval(&Doorkeeper.
|
32
|
+
instance_eval(&Doorkeeper.config.authenticate_admin)
|
22
33
|
end
|
23
34
|
|
24
35
|
def server
|
25
36
|
@server ||= Server.new(self)
|
26
37
|
end
|
27
38
|
|
39
|
+
# :doc:
|
28
40
|
def doorkeeper_token
|
29
|
-
@
|
41
|
+
return @doorkeeper_token if defined?(@doorkeeper_token)
|
42
|
+
|
43
|
+
@doorkeeper_token ||= OAuth::Token.authenticate(request, *config_methods)
|
30
44
|
end
|
31
45
|
|
32
46
|
def config_methods
|
33
|
-
@
|
47
|
+
@config_methods ||= Doorkeeper.config.access_token_methods
|
34
48
|
end
|
35
49
|
|
36
50
|
def get_error_response_from_exception(exception)
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
when Errors::DoorkeeperError
|
49
|
-
exception.message
|
50
|
-
end
|
51
|
-
|
52
|
-
OAuth::ErrorResponse.new name: error_name, state: params[:state]
|
51
|
+
if exception.respond_to?(:response)
|
52
|
+
exception.response
|
53
|
+
elsif exception.type == :invalid_request
|
54
|
+
OAuth::InvalidRequestResponse.new(
|
55
|
+
name: exception.type,
|
56
|
+
state: params[:state],
|
57
|
+
missing_param: exception.missing_param,
|
58
|
+
)
|
59
|
+
else
|
60
|
+
OAuth::ErrorResponse.new(name: exception.type, state: params[:state])
|
61
|
+
end
|
53
62
|
end
|
54
63
|
|
55
64
|
def handle_token_exception(exception)
|
56
|
-
error = get_error_response_from_exception
|
57
|
-
|
65
|
+
error = get_error_response_from_exception(exception)
|
66
|
+
headers.merge!(error.headers)
|
58
67
|
self.response_body = error.body.to_json
|
59
|
-
self.status
|
68
|
+
self.status = error.status
|
60
69
|
end
|
61
70
|
|
62
71
|
def skip_authorization?
|
63
|
-
!!instance_exec(
|
72
|
+
!!instance_exec(
|
73
|
+
[server.current_resource_owner, @pre_auth.client],
|
74
|
+
&Doorkeeper.config.skip_authorization
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def enforce_content_type
|
79
|
+
if (request.put? || request.post? || request.patch?) && !x_www_form_urlencoded?
|
80
|
+
render json: {}, status: :unsupported_media_type
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
def x_www_form_urlencoded?
|
85
|
+
request.media_type == "application/x-www-form-urlencoded"
|
64
86
|
end
|
65
87
|
end
|
66
88
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module AccessGrantMixin
|
3
5
|
extend ActiveSupport::Concern
|
@@ -6,32 +8,113 @@ module Doorkeeper
|
|
6
8
|
include Models::Expirable
|
7
9
|
include Models::Revocable
|
8
10
|
include Models::Accessible
|
11
|
+
include Models::Orderable
|
12
|
+
include Models::SecretStorable
|
9
13
|
include Models::Scopes
|
10
|
-
include
|
14
|
+
include Models::ResourceOwnerable
|
11
15
|
|
12
|
-
|
13
|
-
|
16
|
+
# Never uses PKCE if PKCE migrations were not generated
|
17
|
+
def uses_pkce?
|
18
|
+
self.class.pkce_supported? && code_challenge.present?
|
19
|
+
end
|
14
20
|
|
15
|
-
|
16
|
-
|
21
|
+
module ClassMethods
|
22
|
+
# Searches for Doorkeeper::AccessGrant record with the
|
23
|
+
# specific token value.
|
24
|
+
#
|
25
|
+
# @param token [#to_s] token value (any object that responds to `#to_s`)
|
26
|
+
#
|
27
|
+
# @return [Doorkeeper::AccessGrant, nil]
|
28
|
+
# AccessGrant object or nil if there is no record with such token
|
29
|
+
#
|
30
|
+
def by_token(token)
|
31
|
+
find_by_plaintext_token(:token, token)
|
17
32
|
end
|
18
33
|
|
19
|
-
|
20
|
-
|
34
|
+
# Revokes AccessGrant records that have not been revoked and associated
|
35
|
+
# with the specific Application and Resource Owner.
|
36
|
+
#
|
37
|
+
# @param application_id [Integer]
|
38
|
+
# ID of the Application
|
39
|
+
# @param resource_owner [ActiveRecord::Base, Integer]
|
40
|
+
# instance of the Resource Owner model or it's ID
|
41
|
+
#
|
42
|
+
def revoke_all_for(application_id, resource_owner, clock = Time)
|
43
|
+
by_resource_owner(resource_owner)
|
44
|
+
.where(
|
45
|
+
application_id: application_id,
|
46
|
+
revoked_at: nil,
|
47
|
+
)
|
48
|
+
.update_all(revoked_at: clock.now.utc)
|
49
|
+
end
|
21
50
|
|
22
|
-
|
23
|
-
|
51
|
+
# Implements PKCE code_challenge encoding without base64 padding as described in the spec.
|
52
|
+
# https://datatracker.ietf.org/doc/html/rfc7636#appendix-A
|
53
|
+
# Appendix A. Notes on Implementing Base64url Encoding without Padding
|
54
|
+
#
|
55
|
+
# This appendix describes how to implement a base64url-encoding
|
56
|
+
# function without padding, based upon the standard base64-encoding
|
57
|
+
# function that uses padding.
|
58
|
+
#
|
59
|
+
# To be concrete, example C# code implementing these functions is shown
|
60
|
+
# below. Similar code could be used in other languages.
|
61
|
+
#
|
62
|
+
# static string base64urlencode(byte [] arg)
|
63
|
+
# {
|
64
|
+
# string s = Convert.ToBase64String(arg); // Regular base64 encoder
|
65
|
+
# s = s.Split('=')[0]; // Remove any trailing '='s
|
66
|
+
# s = s.Replace('+', '-'); // 62nd char of encoding
|
67
|
+
# s = s.Replace('/', '_'); // 63rd char of encoding
|
68
|
+
# return s;
|
69
|
+
# }
|
70
|
+
#
|
71
|
+
# An example correspondence between unencoded and encoded values
|
72
|
+
# follows. The octet sequence below encodes into the string below,
|
73
|
+
# which when decoded, reproduces the octet sequence.
|
74
|
+
#
|
75
|
+
# 3 236 255 224 193
|
76
|
+
#
|
77
|
+
# A-z_4ME
|
78
|
+
#
|
79
|
+
# https://ruby-doc.org/stdlib-2.1.3/libdoc/base64/rdoc/Base64.html#method-i-urlsafe_encode64
|
80
|
+
#
|
81
|
+
# urlsafe_encode64(bin)
|
82
|
+
# Returns the Base64-encoded version of bin. This method complies with
|
83
|
+
# "Base 64 Encoding with URL and Filename Safe Alphabet" in RFC 4648.
|
84
|
+
# The alphabet uses '-' instead of '+' and '_' instead of '/'.
|
24
85
|
|
25
|
-
|
26
|
-
|
27
|
-
|
86
|
+
# @param code_verifier [#to_s] a one time use value (any object that responds to `#to_s`)
|
87
|
+
#
|
88
|
+
# @return [#to_s] An encoded code challenge based on the provided verifier
|
89
|
+
# suitable for PKCE validation
|
90
|
+
#
|
91
|
+
def generate_code_challenge(code_verifier)
|
92
|
+
Base64.urlsafe_encode64(Digest::SHA256.digest(code_verifier), padding: false)
|
93
|
+
end
|
94
|
+
|
95
|
+
def pkce_supported?
|
96
|
+
column_names.include?("code_challenge")
|
28
97
|
end
|
29
|
-
end
|
30
98
|
|
31
|
-
|
99
|
+
##
|
100
|
+
# Determines the secret storing transformer
|
101
|
+
# Unless configured otherwise, uses the plain secret strategy
|
102
|
+
#
|
103
|
+
# @return [Doorkeeper::SecretStoring::Base]
|
104
|
+
#
|
105
|
+
def secret_strategy
|
106
|
+
::Doorkeeper.config.token_secret_strategy
|
107
|
+
end
|
32
108
|
|
33
|
-
|
34
|
-
|
109
|
+
##
|
110
|
+
# Determine the fallback storing strategy
|
111
|
+
# Unless configured, there will be no fallback
|
112
|
+
#
|
113
|
+
# @return [Doorkeeper::SecretStoring::Base]
|
114
|
+
#
|
115
|
+
def fallback_secret_strategy
|
116
|
+
::Doorkeeper.config.token_secret_fallback_strategy
|
117
|
+
end
|
35
118
|
end
|
36
119
|
end
|
37
120
|
end
|