doorkeeper 4.2.6 → 5.5.4
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 +1049 -0
- data/README.md +110 -353
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +6 -7
- data/app/controllers/doorkeeper/application_metal_controller.rb +7 -11
- data/app/controllers/doorkeeper/applications_controller.rb +65 -16
- data/app/controllers/doorkeeper/authorizations_controller.rb +97 -17
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +22 -3
- data/app/controllers/doorkeeper/token_info_controller.rb +16 -4
- data/app/controllers/doorkeeper/tokens_controller.rb +115 -38
- data/app/helpers/doorkeeper/dashboard_helper.rb +10 -6
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- 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 +6 -0
- 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 +34 -7
- 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 +514 -167
- data/lib/doorkeeper/engine.rb +11 -5
- data/lib/doorkeeper/errors.rb +25 -16
- 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 +23 -12
- data/lib/doorkeeper/helpers/controller.rb +51 -14
- data/lib/doorkeeper/models/access_grant_mixin.rb +94 -27
- data/lib/doorkeeper/models/access_token_mixin.rb +284 -96
- data/lib/doorkeeper/models/application_mixin.rb +58 -27
- data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +12 -6
- data/lib/doorkeeper/models/concerns/orderable.rb +15 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +4 -7
- 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 +3 -27
- 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 +66 -28
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +7 -5
- data/lib/doorkeeper/oauth/authorization_code_request.rb +63 -10
- data/lib/doorkeeper/oauth/base_request.rb +35 -19
- data/lib/doorkeeper/oauth/base_response.rb +2 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +9 -7
- data/lib/doorkeeper/oauth/client.rb +10 -11
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +47 -4
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +16 -9
- data/lib/doorkeeper/oauth/client_credentials/validator.rb +56 -0
- data/lib/doorkeeper/oauth/client_credentials_request.rb +10 -11
- data/lib/doorkeeper/oauth/code_request.rb +8 -12
- data/lib/doorkeeper/oauth/code_response.rb +27 -15
- data/lib/doorkeeper/oauth/error.rb +5 -3
- data/lib/doorkeeper/oauth/error_response.rb +35 -15
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +11 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -18
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +53 -3
- 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 +29 -5
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +44 -10
- data/lib/doorkeeper/oauth/pre_authorization.rb +135 -26
- data/lib/doorkeeper/oauth/refresh_token_request.rb +60 -31
- data/lib/doorkeeper/oauth/scopes.rb +26 -12
- data/lib/doorkeeper/oauth/token.rb +13 -9
- data/lib/doorkeeper/oauth/token_introspection.rb +202 -0
- data/lib/doorkeeper/oauth/token_request.rb +8 -20
- 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 -42
- 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 +60 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +199 -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 +37 -8
- data/lib/doorkeeper/rails/helpers.rb +14 -13
- 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 +9 -7
- data/lib/doorkeeper/rails/routes/registry.rb +45 -0
- data/lib/doorkeeper/rails/routes.rb +41 -28
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +11 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request/authorization_code.rb +6 -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 -14
- 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 -11
- 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 +111 -62
- 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 +31 -19
- 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/{spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb → lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb} +3 -1
- 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 +412 -33
- 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 +114 -276
- data/.coveralls.yml +0 -1
- data/.gitignore +0 -19
- data/.hound.yml +0 -13
- data/.rspec +0 -1
- data/.travis.yml +0 -26
- data/Appraisals +0 -14
- data/CONTRIBUTING.md +0 -47
- data/Gemfile +0 -10
- data/NEWS.md +0 -606
- data/RELEASING.md +0 -10
- data/Rakefile +0 -20
- data/app/validators/redirect_uri_validator.rb +0 -34
- data/doorkeeper.gemspec +0 -29
- data/gemfiles/rails_4_2.gemfile +0 -11
- data/gemfiles/rails_5_0.gemfile +0 -12
- data/gemfiles/rails_5_1.gemfile +0 -13
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +0 -7
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb +0 -11
- data/lib/generators/doorkeeper/templates/migration.rb +0 -68
- data/spec/controllers/application_metal_controller.rb +0 -10
- data/spec/controllers/applications_controller_spec.rb +0 -58
- data/spec/controllers/authorizations_controller_spec.rb +0 -218
- data/spec/controllers/protected_resources_controller_spec.rb +0 -300
- 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 -5
- 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 -23
- 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 -44
- data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +0 -6
- 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/20151223192035_create_doorkeeper_tables.rb +0 -60
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -7
- data/spec/dummy/db/schema.rb +0 -67
- 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 -28
- 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 -334
- data/spec/lib/doorkeeper_spec.rb +0 -150
- data/spec/lib/models/expirable_spec.rb +0 -50
- data/spec/lib/models/revocable_spec.rb +0 -59
- data/spec/lib/models/scopes_spec.rb +0 -43
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -41
- data/spec/lib/oauth/authorization_code_request_spec.rb +0 -80
- data/spec/lib/oauth/base_request_spec.rb +0 -160
- data/spec/lib/oauth/base_response_spec.rb +0 -45
- data/spec/lib/oauth/client/credentials_spec.rb +0 -88
- 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/code_response_spec.rb +0 -34
- 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 -56
- 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 -154
- data/spec/lib/oauth/scopes_spec.rb +0 -122
- 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 -116
- data/spec/lib/request/strategy_spec.rb +0 -53
- data/spec/lib/server_spec.rb +0 -49
- data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
- data/spec/models/doorkeeper/access_token_spec.rb +0 -394
- data/spec/models/doorkeeper/application_spec.rb +0 -179
- 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 -71
- data/spec/requests/endpoints/token_spec.rb +0 -64
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -76
- data/spec/requests/flows/authorization_code_spec.rb +0 -148
- 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 -115
- data/spec/requests/flows/refresh_token_spec.rb +0 -174
- data/spec/requests/flows/revoke_token_spec.rb +0 -157
- 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 -4
- data/spec/spec_helper_integration.rb +0 -63
- 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 -67
- data/spec/support/helpers/request_spec_helper.rb +0 -84
- data/spec/support/helpers/url_helper.rb +0 -55
- data/spec/support/http_method_shim.rb +0 -38
- data/spec/support/orm/active_record.rb +0 -3
- data/spec/support/shared/controllers_shared_context.rb +0 -69
- data/spec/support/shared/models_shared_examples.rb +0 -52
- data/spec/validators/redirect_uri_validator_spec.rb +0 -78
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module Models
|
5
|
+
module Orderable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def ordered_by(attribute, direction = :asc)
|
10
|
+
order(attribute => direction)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -1,20 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Models
|
3
5
|
module Ownership
|
4
6
|
extend ActiveSupport::Concern
|
5
7
|
|
6
8
|
included do
|
7
|
-
|
8
|
-
if defined?(ActiveRecord::Base) && ActiveRecord::VERSION::MAJOR >= 5
|
9
|
-
belongs_to_options[:optional] = true
|
10
|
-
end
|
11
|
-
|
12
|
-
belongs_to :owner, belongs_to_options
|
9
|
+
belongs_to :owner, polymorphic: true, optional: true
|
13
10
|
validates :owner, presence: true, if: :validate_owner?
|
14
11
|
end
|
15
12
|
|
16
13
|
def validate_owner?
|
17
|
-
Doorkeeper.
|
14
|
+
Doorkeeper.config.confirm_application_owner?
|
18
15
|
end
|
19
16
|
end
|
20
17
|
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module Models
|
5
|
+
module ResourceOwnerable
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
# Searches for record by Resource Owner considering Doorkeeper
|
10
|
+
# configuration for resource owner association.
|
11
|
+
#
|
12
|
+
# @param resource_owner [ActiveRecord::Base, Integer]
|
13
|
+
# resource owner
|
14
|
+
#
|
15
|
+
# @return [Doorkeeper::AccessGrant, Doorkeeper::AccessToken]
|
16
|
+
# collection of records
|
17
|
+
#
|
18
|
+
def by_resource_owner(resource_owner)
|
19
|
+
if Doorkeeper.configuration.polymorphic_resource_owner?
|
20
|
+
where(resource_owner: resource_owner)
|
21
|
+
else
|
22
|
+
where(resource_owner_id: resource_owner_id_for(resource_owner))
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
# Backward compatible way to retrieve resource owner itself (if
|
29
|
+
# polymorphic association enabled) or just it's ID.
|
30
|
+
#
|
31
|
+
# @param resource_owner [ActiveRecord::Base, Integer]
|
32
|
+
# resource owner
|
33
|
+
#
|
34
|
+
# @return [ActiveRecord::Base, Integer]
|
35
|
+
# instance of Resource Owner or it's ID
|
36
|
+
#
|
37
|
+
def resource_owner_id_for(resource_owner)
|
38
|
+
if resource_owner.respond_to?(:to_key)
|
39
|
+
resource_owner.id
|
40
|
+
else
|
41
|
+
resource_owner
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module Models
|
5
|
+
module Reusable
|
6
|
+
# Indicates whether the object is reusable (i.e. It is not expired and
|
7
|
+
# has not crossed reuse_limit).
|
8
|
+
#
|
9
|
+
# @return [Boolean] true if can be reused and false in other case
|
10
|
+
def reusable?
|
11
|
+
return false if expired?
|
12
|
+
return true unless expires_in
|
13
|
+
|
14
|
+
threshold_limit = 100 - Doorkeeper.config.token_reuse_limit
|
15
|
+
expires_in_seconds >= threshold_limit * expires_in / 100
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Models
|
3
5
|
module Revocable
|
@@ -7,7 +9,7 @@ module Doorkeeper
|
|
7
9
|
# @param clock [Time] time object
|
8
10
|
#
|
9
11
|
def revoke(clock = Time)
|
10
|
-
update_attribute
|
12
|
+
update_attribute(:revoked_at, clock.now.utc)
|
11
13
|
end
|
12
14
|
|
13
15
|
# Indicates whether the object has been revoked.
|
@@ -17,32 +19,6 @@ module Doorkeeper
|
|
17
19
|
def revoked?
|
18
20
|
!!(revoked_at && revoked_at <= Time.now.utc)
|
19
21
|
end
|
20
|
-
|
21
|
-
# Revokes token with `:refresh_token` equal to `:previous_refresh_token`
|
22
|
-
# and clears `:previous_refresh_token` attribute.
|
23
|
-
#
|
24
|
-
def revoke_previous_refresh_token!
|
25
|
-
return unless refresh_token_revoked_on_use?
|
26
|
-
old_refresh_token.revoke if old_refresh_token
|
27
|
-
update_attribute :previous_refresh_token, ""
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
# Searches for Access Token record with `:refresh_token` equal to
|
33
|
-
# `:previous_refresh_token` value.
|
34
|
-
#
|
35
|
-
# @return [Doorkeeper::AccessToken, nil]
|
36
|
-
# Access Token record or nil if nothing found
|
37
|
-
#
|
38
|
-
def old_refresh_token
|
39
|
-
@old_refresh_token ||=
|
40
|
-
AccessToken.by_refresh_token(previous_refresh_token)
|
41
|
-
end
|
42
|
-
|
43
|
-
def refresh_token_revoked_on_use?
|
44
|
-
AccessToken.refresh_token_revoked_on_use?
|
45
|
-
end
|
46
22
|
end
|
47
23
|
end
|
48
24
|
end
|
@@ -1,8 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Models
|
3
5
|
module Scopes
|
4
6
|
def scopes
|
5
|
-
OAuth::Scopes.from_string(
|
7
|
+
OAuth::Scopes.from_string(scopes_string)
|
8
|
+
end
|
9
|
+
|
10
|
+
def scopes=(value)
|
11
|
+
if value.is_a?(Array)
|
12
|
+
super(Doorkeeper::OAuth::Scopes.from_array(value).to_s)
|
13
|
+
else
|
14
|
+
super(Doorkeeper::OAuth::Scopes.from_string(value.to_s).to_s)
|
15
|
+
end
|
6
16
|
end
|
7
17
|
|
8
18
|
def scopes_string
|
@@ -10,7 +20,7 @@ module Doorkeeper
|
|
10
20
|
end
|
11
21
|
|
12
22
|
def includes_scope?(*required_scopes)
|
13
|
-
required_scopes.blank? || required_scopes.any? { |
|
23
|
+
required_scopes.blank? || required_scopes.any? { |scope| scopes.exists?(scope.to_s) }
|
14
24
|
end
|
15
25
|
end
|
16
26
|
end
|
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module Models
|
5
|
+
##
|
6
|
+
# Storable finder to provide lookups for input plaintext values which are
|
7
|
+
# mapped to their stored versions (e.g., hashing, encryption) before lookup.
|
8
|
+
module SecretStorable
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
delegate :secret_strategy,
|
12
|
+
:fallback_secret_strategy,
|
13
|
+
to: :class
|
14
|
+
|
15
|
+
# :nodoc
|
16
|
+
module ClassMethods
|
17
|
+
# Compare the given plaintext with the secret
|
18
|
+
#
|
19
|
+
# @param input [String]
|
20
|
+
# The plain input to compare.
|
21
|
+
#
|
22
|
+
# @param secret [String]
|
23
|
+
# The secret value to compare with.
|
24
|
+
#
|
25
|
+
# @return [Boolean]
|
26
|
+
# Whether input matches secret as per the secret strategy
|
27
|
+
#
|
28
|
+
delegate :secret_matches?, to: :secret_strategy
|
29
|
+
|
30
|
+
# Returns an instance of the Doorkeeper::AccessToken with
|
31
|
+
# specific token value.
|
32
|
+
#
|
33
|
+
# @param attr [Symbol]
|
34
|
+
# The token attribute we're looking with.
|
35
|
+
#
|
36
|
+
# @param token [#to_s]
|
37
|
+
# token value (any object that responds to `#to_s`)
|
38
|
+
#
|
39
|
+
# @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
|
40
|
+
# if there is no record with such token
|
41
|
+
#
|
42
|
+
def find_by_plaintext_token(attr, token)
|
43
|
+
token = token.to_s
|
44
|
+
|
45
|
+
find_by(attr => secret_strategy.transform_secret(token)) ||
|
46
|
+
find_by_fallback_token(attr, token)
|
47
|
+
end
|
48
|
+
|
49
|
+
# Allow looking up previously plain tokens as a fallback
|
50
|
+
# IFF a fallback strategy has been defined
|
51
|
+
#
|
52
|
+
# @param attr [Symbol]
|
53
|
+
# The token attribute we're looking with.
|
54
|
+
#
|
55
|
+
# @param plain_secret [#to_s]
|
56
|
+
# plain secret value (any object that responds to `#to_s`)
|
57
|
+
#
|
58
|
+
# @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
|
59
|
+
# if there is no record with such token
|
60
|
+
#
|
61
|
+
def find_by_fallback_token(attr, plain_secret)
|
62
|
+
return nil unless fallback_secret_strategy
|
63
|
+
|
64
|
+
# Use the previous strategy to look up
|
65
|
+
stored_token = fallback_secret_strategy.transform_secret(plain_secret)
|
66
|
+
find_by(attr => stored_token).tap do |resource|
|
67
|
+
return nil unless resource
|
68
|
+
|
69
|
+
upgrade_fallback_value resource, attr, plain_secret
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Allow implementations in ORMs to replace a plain
|
74
|
+
# value falling back to to avoid it remaining as plain text.
|
75
|
+
#
|
76
|
+
# @param instance
|
77
|
+
# An instance of this model with a plain value token.
|
78
|
+
#
|
79
|
+
# @param attr
|
80
|
+
# The secret attribute name to upgrade.
|
81
|
+
#
|
82
|
+
# @param plain_secret
|
83
|
+
# The plain secret to upgrade.
|
84
|
+
#
|
85
|
+
def upgrade_fallback_value(instance, attr, plain_secret)
|
86
|
+
upgraded = secret_strategy.store_secret(instance, attr, plain_secret)
|
87
|
+
instance.update(attr => upgraded)
|
88
|
+
end
|
89
|
+
|
90
|
+
##
|
91
|
+
# Determines the secret storing transformer
|
92
|
+
# Unless configured otherwise, uses the plain secret strategy
|
93
|
+
def secret_strategy
|
94
|
+
::Doorkeeper::SecretStoring::Plain
|
95
|
+
end
|
96
|
+
|
97
|
+
##
|
98
|
+
# Determine the fallback storing strategy
|
99
|
+
# Unless configured, there will be no fallback
|
100
|
+
def fallback_secret_strategy
|
101
|
+
nil
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -1,30 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OAuth
|
3
5
|
module Authorization
|
4
6
|
class Code
|
5
|
-
|
7
|
+
attr_reader :pre_auth, :resource_owner, :token
|
6
8
|
|
7
9
|
def initialize(pre_auth, resource_owner)
|
8
|
-
@pre_auth
|
10
|
+
@pre_auth = pre_auth
|
9
11
|
@resource_owner = resource_owner
|
10
12
|
end
|
11
13
|
|
12
|
-
def issue_token
|
13
|
-
@token
|
14
|
+
def issue_token!
|
15
|
+
return @token if defined?(@token)
|
16
|
+
|
17
|
+
@token = Doorkeeper.config.access_grant_model.create!(access_grant_attributes)
|
18
|
+
end
|
19
|
+
|
20
|
+
def oob_redirect
|
21
|
+
{ action: :show, code: token.plaintext_token }
|
22
|
+
end
|
23
|
+
|
24
|
+
def access_grant?
|
25
|
+
true
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def authorization_code_expires_in
|
31
|
+
Doorkeeper.config.authorization_code_expires_in
|
32
|
+
end
|
33
|
+
|
34
|
+
def access_grant_attributes
|
35
|
+
attributes = {
|
14
36
|
application_id: pre_auth.client.id,
|
15
|
-
|
16
|
-
expires_in: configuration.authorization_code_expires_in,
|
37
|
+
expires_in: authorization_code_expires_in,
|
17
38
|
redirect_uri: pre_auth.redirect_uri,
|
18
|
-
scopes: pre_auth.scopes.to_s
|
19
|
-
|
39
|
+
scopes: pre_auth.scopes.to_s,
|
40
|
+
}
|
41
|
+
|
42
|
+
if Doorkeeper.config.polymorphic_resource_owner?
|
43
|
+
attributes[:resource_owner] = resource_owner
|
44
|
+
else
|
45
|
+
attributes[:resource_owner_id] = resource_owner.id
|
46
|
+
end
|
47
|
+
|
48
|
+
pkce_attributes.merge(attributes)
|
20
49
|
end
|
21
50
|
|
22
|
-
def
|
23
|
-
{
|
51
|
+
def pkce_attributes
|
52
|
+
return {} unless pkce_supported?
|
53
|
+
|
54
|
+
{
|
55
|
+
code_challenge: pre_auth.code_challenge,
|
56
|
+
code_challenge_method: pre_auth.code_challenge_method,
|
57
|
+
}
|
24
58
|
end
|
25
59
|
|
26
|
-
|
27
|
-
|
60
|
+
# Ensures firstly, if migration with additional PKCE columns was
|
61
|
+
# generated and migrated
|
62
|
+
def pkce_supported?
|
63
|
+
Doorkeeper.config.access_grant_model.pkce_supported?
|
28
64
|
end
|
29
65
|
end
|
30
66
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module OAuth
|
5
|
+
module Authorization
|
6
|
+
class Context
|
7
|
+
attr_reader :client, :grant_type, :resource_owner, :scopes
|
8
|
+
|
9
|
+
def initialize(**attributes)
|
10
|
+
attributes.each do |name, value|
|
11
|
+
instance_variable_set(:"@#{name}", value) if respond_to?(name)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -1,54 +1,92 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OAuth
|
3
5
|
module Authorization
|
4
6
|
class Token
|
5
|
-
|
7
|
+
attr_reader :pre_auth, :resource_owner, :token
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def build_context(pre_auth_or_oauth_client, grant_type, scopes, resource_owner)
|
11
|
+
oauth_client = if pre_auth_or_oauth_client.respond_to?(:application)
|
12
|
+
pre_auth_or_oauth_client.application
|
13
|
+
elsif pre_auth_or_oauth_client.respond_to?(:client)
|
14
|
+
pre_auth_or_oauth_client.client
|
15
|
+
else
|
16
|
+
pre_auth_or_oauth_client
|
17
|
+
end
|
18
|
+
|
19
|
+
Doorkeeper::OAuth::Authorization::Context.new(
|
20
|
+
client: oauth_client,
|
21
|
+
grant_type: grant_type,
|
22
|
+
scopes: scopes,
|
23
|
+
resource_owner: resource_owner,
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
def access_token_expires_in(configuration, context)
|
28
|
+
if configuration.option_defined?(:custom_access_token_expires_in)
|
29
|
+
expiration = configuration.custom_access_token_expires_in.call(context)
|
30
|
+
return nil if expiration == Float::INFINITY
|
31
|
+
|
32
|
+
expiration || configuration.access_token_expires_in
|
33
|
+
else
|
34
|
+
configuration.access_token_expires_in
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def refresh_token_enabled?(server, context)
|
39
|
+
if server.refresh_token_enabled?.respond_to?(:call)
|
40
|
+
server.refresh_token_enabled?.call(context)
|
41
|
+
else
|
42
|
+
!!server.refresh_token_enabled?
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
6
46
|
|
7
47
|
def initialize(pre_auth, resource_owner)
|
8
48
|
@pre_auth = pre_auth
|
9
49
|
@resource_owner = resource_owner
|
10
50
|
end
|
11
51
|
|
12
|
-
def
|
13
|
-
|
14
|
-
expiration
|
15
|
-
else
|
16
|
-
server.access_token_expires_in
|
17
|
-
end
|
18
|
-
end
|
52
|
+
def issue_token!
|
53
|
+
return @token if defined?(@token)
|
19
54
|
|
20
|
-
|
21
|
-
@token ||= AccessToken.find_or_create_for(
|
55
|
+
context = self.class.build_context(
|
22
56
|
pre_auth.client,
|
23
|
-
|
57
|
+
Doorkeeper::OAuth::IMPLICIT,
|
24
58
|
pre_auth.scopes,
|
25
|
-
|
26
|
-
|
59
|
+
resource_owner,
|
60
|
+
)
|
61
|
+
|
62
|
+
@token = Doorkeeper.config.access_token_model.find_or_create_for(
|
63
|
+
application: pre_auth.client,
|
64
|
+
resource_owner: resource_owner,
|
65
|
+
scopes: pre_auth.scopes,
|
66
|
+
expires_in: self.class.access_token_expires_in(Doorkeeper.config, context),
|
67
|
+
use_refresh_token: false,
|
27
68
|
)
|
28
69
|
end
|
29
70
|
|
30
|
-
def
|
71
|
+
def oob_redirect
|
31
72
|
{
|
32
|
-
controller:
|
73
|
+
controller: controller,
|
33
74
|
action: :show,
|
34
|
-
access_token: token.
|
75
|
+
access_token: token.plaintext_token,
|
35
76
|
}
|
36
77
|
end
|
37
78
|
|
38
|
-
|
39
|
-
|
40
|
-
def self.custom_expiration(server, pre_auth_or_oauth_client)
|
41
|
-
oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
|
42
|
-
pre_auth_or_oauth_client.client
|
43
|
-
else
|
44
|
-
pre_auth_or_oauth_client
|
45
|
-
end
|
46
|
-
|
47
|
-
server.custom_access_token_expires_in.call(oauth_client)
|
79
|
+
def access_token?
|
80
|
+
true
|
48
81
|
end
|
49
82
|
|
50
|
-
|
51
|
-
|
83
|
+
private
|
84
|
+
|
85
|
+
def controller
|
86
|
+
@controller ||= begin
|
87
|
+
mapping = Doorkeeper::Rails::Routes.mapping[:token_info] || {}
|
88
|
+
mapping[:controllers] || "doorkeeper/token_info"
|
89
|
+
end
|
52
90
|
end
|
53
91
|
end
|
54
92
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rack/utils"
|
2
4
|
|
3
5
|
module Doorkeeper
|
4
6
|
module OAuth
|
@@ -6,9 +8,9 @@ module Doorkeeper
|
|
6
8
|
class URIBuilder
|
7
9
|
class << self
|
8
10
|
def uri_with_query(url, parameters = {})
|
9
|
-
uri
|
11
|
+
uri = URI.parse(url)
|
10
12
|
original_query = Rack::Utils.parse_query(uri.query)
|
11
|
-
uri.query
|
13
|
+
uri.query = build_query(original_query.merge(parameters))
|
12
14
|
uri.to_s
|
13
15
|
end
|
14
16
|
|
@@ -21,8 +23,8 @@ module Doorkeeper
|
|
21
23
|
private
|
22
24
|
|
23
25
|
def build_query(parameters = {})
|
24
|
-
parameters
|
25
|
-
Rack::Utils.build_query
|
26
|
+
parameters.reject! { |_, value| value.blank? }
|
27
|
+
Rack::Utils.build_query(parameters)
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
@@ -1,18 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module OAuth
|
3
5
|
class AuthorizationCodeRequest < BaseRequest
|
4
|
-
validate :
|
6
|
+
validate :params, error: :invalid_request
|
5
7
|
validate :client, error: :invalid_client
|
6
8
|
validate :grant, error: :invalid_grant
|
9
|
+
# @see https://datatracker.ietf.org/doc/html/rfc6749#section-5.2
|
7
10
|
validate :redirect_uri, error: :invalid_grant
|
11
|
+
validate :code_verifier, error: :invalid_grant
|
8
12
|
|
9
|
-
|
13
|
+
attr_reader :grant, :client, :redirect_uri, :access_token, :code_verifier,
|
14
|
+
:invalid_request_reason, :missing_param
|
10
15
|
|
11
16
|
def initialize(server, grant, client, parameters = {})
|
12
17
|
@server = server
|
13
18
|
@client = client
|
14
19
|
@grant = grant
|
20
|
+
@grant_type = Doorkeeper::OAuth::AUTHORIZATION_CODE
|
15
21
|
@redirect_uri = parameters[:redirect_uri]
|
22
|
+
@code_verifier = parameters[:code_verifier]
|
16
23
|
end
|
17
24
|
|
18
25
|
private
|
@@ -23,28 +30,74 @@ module Doorkeeper
|
|
23
30
|
raise Errors::InvalidGrantReuse if grant.revoked?
|
24
31
|
|
25
32
|
grant.revoke
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
33
|
+
|
34
|
+
find_or_create_access_token(
|
35
|
+
grant.application,
|
36
|
+
resource_owner,
|
37
|
+
grant.scopes,
|
38
|
+
server,
|
39
|
+
)
|
40
|
+
end
|
41
|
+
|
42
|
+
super
|
43
|
+
end
|
44
|
+
|
45
|
+
def resource_owner
|
46
|
+
if Doorkeeper.config.polymorphic_resource_owner?
|
47
|
+
grant.resource_owner
|
48
|
+
else
|
49
|
+
grant.resource_owner_id
|
30
50
|
end
|
31
51
|
end
|
32
52
|
|
33
|
-
def
|
34
|
-
|
53
|
+
def pkce_supported?
|
54
|
+
Doorkeeper.config.access_grant_model.pkce_supported?
|
55
|
+
end
|
56
|
+
|
57
|
+
def validate_params
|
58
|
+
@missing_param = if grant&.uses_pkce? && code_verifier.blank?
|
59
|
+
:code_verifier
|
60
|
+
elsif redirect_uri.blank?
|
61
|
+
:redirect_uri
|
62
|
+
end
|
63
|
+
|
64
|
+
@missing_param.nil?
|
35
65
|
end
|
36
66
|
|
37
67
|
def validate_client
|
38
|
-
|
68
|
+
client.present?
|
39
69
|
end
|
40
70
|
|
41
71
|
def validate_grant
|
42
72
|
return false unless grant && grant.application_id == client.id
|
73
|
+
|
43
74
|
grant.accessible?
|
44
75
|
end
|
45
76
|
|
46
77
|
def validate_redirect_uri
|
47
|
-
|
78
|
+
Helpers::URIChecker.valid_for_authorization?(
|
79
|
+
redirect_uri,
|
80
|
+
grant.redirect_uri,
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
# if either side (server or client) request PKCE, check the verifier
|
85
|
+
# against the DB - if PKCE is supported
|
86
|
+
def validate_code_verifier
|
87
|
+
return true unless pkce_supported?
|
88
|
+
return grant.code_challenge.blank? if code_verifier.blank?
|
89
|
+
|
90
|
+
if grant.code_challenge_method == "S256"
|
91
|
+
grant.code_challenge == generate_code_challenge(code_verifier)
|
92
|
+
elsif grant.code_challenge_method == "plain"
|
93
|
+
grant.code_challenge == code_verifier
|
94
|
+
else
|
95
|
+
false
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def generate_code_challenge(code_verifier)
|
100
|
+
server_config.access_grant_model.generate_code_challenge(code_verifier)
|
48
101
|
end
|
49
102
|
end
|
50
103
|
end
|