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
@@ -1,21 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Models
|
3
5
|
module Expirable
|
6
|
+
# Indicates whether the object is expired (`#expires_in` present and
|
7
|
+
# expiration time has come).
|
8
|
+
#
|
9
|
+
# @return [Boolean] true if object expired and false in other case
|
4
10
|
def expired?
|
5
|
-
expires_in && Time.now >
|
11
|
+
!!(expires_in && Time.now.utc > expires_at)
|
6
12
|
end
|
7
13
|
|
14
|
+
# Calculates expiration time in seconds.
|
15
|
+
#
|
16
|
+
# @return [Integer, nil] number of seconds if object has expiration time
|
17
|
+
# or nil if object never expires.
|
8
18
|
def expires_in_seconds
|
9
19
|
return nil if expires_in.nil?
|
10
|
-
|
20
|
+
|
21
|
+
expires = expires_at - Time.now.utc
|
11
22
|
expires_sec = expires.seconds.round(0)
|
12
23
|
expires_sec > 0 ? expires_sec : 0
|
13
24
|
end
|
14
25
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
26
|
+
# Expiration time (date time of creation + TTL).
|
27
|
+
#
|
28
|
+
# @return [Time, nil] expiration time in UTC
|
29
|
+
# or nil if the object never expires.
|
30
|
+
#
|
31
|
+
def expires_at
|
32
|
+
expires_in && created_at + expires_in.seconds
|
19
33
|
end
|
20
34
|
end
|
21
35
|
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module Models
|
5
|
+
module ExpirationTimeSqlMath
|
6
|
+
extend ::ActiveSupport::Concern
|
7
|
+
|
8
|
+
class ExpirationTimeSqlGenerator
|
9
|
+
attr_reader :model
|
10
|
+
|
11
|
+
delegate :table_name, to: :@model
|
12
|
+
|
13
|
+
def initialize(model)
|
14
|
+
@model = model
|
15
|
+
end
|
16
|
+
|
17
|
+
def generate_sql
|
18
|
+
raise "`generate_sql` should be overridden for a #{self.class.name}!"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class MySqlExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
|
23
|
+
def generate_sql
|
24
|
+
Arel.sql("DATE_ADD(#{table_name}.created_at, INTERVAL #{table_name}.expires_in SECOND)")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class SqlLiteExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
|
29
|
+
def generate_sql
|
30
|
+
Arel.sql("DATETIME(#{table_name}.created_at, '+' || #{table_name}.expires_in || ' SECONDS')")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class SqlServerExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
|
35
|
+
def generate_sql
|
36
|
+
Arel.sql("DATEADD(second, #{table_name}.expires_in, #{table_name}.created_at) AT TIME ZONE 'UTC'")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class OracleExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
|
41
|
+
def generate_sql
|
42
|
+
Arel.sql("#{table_name}.created_at + INTERVAL to_char(#{table_name}.expires_in) second")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
class PostgresExpirationTimeSqlGenerator < ExpirationTimeSqlGenerator
|
47
|
+
def generate_sql
|
48
|
+
Arel.sql("#{table_name}.created_at + #{table_name}.expires_in * INTERVAL '1 SECOND'")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
ADAPTERS_MAPPING = {
|
53
|
+
"sqlite" => SqlLiteExpirationTimeSqlGenerator,
|
54
|
+
"sqlite3" => SqlLiteExpirationTimeSqlGenerator,
|
55
|
+
"postgis" => PostgresExpirationTimeSqlGenerator,
|
56
|
+
"postgresql" => PostgresExpirationTimeSqlGenerator,
|
57
|
+
"mysql" => MySqlExpirationTimeSqlGenerator,
|
58
|
+
"mysql2" => MySqlExpirationTimeSqlGenerator,
|
59
|
+
"trilogy" => MySqlExpirationTimeSqlGenerator,
|
60
|
+
"sqlserver" => SqlServerExpirationTimeSqlGenerator,
|
61
|
+
"oracleenhanced" => OracleExpirationTimeSqlGenerator,
|
62
|
+
}.freeze
|
63
|
+
|
64
|
+
module ClassMethods
|
65
|
+
def supports_expiration_time_math?
|
66
|
+
ADAPTERS_MAPPING.key?(adapter_name.downcase) ||
|
67
|
+
respond_to?(:custom_expiration_time_sql)
|
68
|
+
end
|
69
|
+
|
70
|
+
def expiration_time_sql
|
71
|
+
if respond_to?(:custom_expiration_time_sql)
|
72
|
+
custom_expiration_time_sql
|
73
|
+
else
|
74
|
+
expiration_time_sql_expression
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def expiration_time_sql_expression
|
79
|
+
ADAPTERS_MAPPING.fetch(adapter_name.downcase).new(self).generate_sql
|
80
|
+
end
|
81
|
+
|
82
|
+
def adapter_name
|
83
|
+
ActiveRecord::Base.connection.adapter_name
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
@@ -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,15 +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
|
-
belongs_to :owner, polymorphic: true
|
9
|
+
belongs_to :owner, polymorphic: true, optional: true
|
8
10
|
validates :owner, presence: true, if: :validate_owner?
|
9
11
|
end
|
10
12
|
|
11
13
|
def validate_owner?
|
12
|
-
Doorkeeper.
|
14
|
+
Doorkeeper.config.confirm_application_owner?
|
13
15
|
end
|
14
16
|
end
|
15
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,12 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
module Models
|
3
5
|
module Revocable
|
6
|
+
# Revokes the object (updates `:revoked_at` attribute setting its value
|
7
|
+
# to the specific time).
|
8
|
+
#
|
9
|
+
# @param clock [Time] time object
|
10
|
+
#
|
4
11
|
def revoke(clock = Time)
|
5
|
-
update_attribute
|
12
|
+
update_attribute(:revoked_at, clock.now.utc)
|
6
13
|
end
|
7
14
|
|
15
|
+
# Indicates whether the object has been revoked.
|
16
|
+
#
|
17
|
+
# @return [Boolean] true if revoked, false in other case
|
18
|
+
#
|
8
19
|
def revoked?
|
9
|
-
!!(revoked_at && revoked_at <= Time.now)
|
20
|
+
!!(revoked_at && revoked_at <= Time.now.utc)
|
10
21
|
end
|
11
22
|
end
|
12
23
|
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,98 @@
|
|
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
|
-
false
|
59
|
+
resource_owner,
|
27
60
|
)
|
61
|
+
|
62
|
+
@token = Doorkeeper.config.access_token_model.find_or_create_for(
|
63
|
+
application: application,
|
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,
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def application
|
72
|
+
return unless pre_auth.client
|
73
|
+
|
74
|
+
pre_auth.client.is_a?(Doorkeeper.config.application_model) ? pre_auth.client : pre_auth.client.application
|
28
75
|
end
|
29
76
|
|
30
|
-
def
|
77
|
+
def oob_redirect
|
31
78
|
{
|
32
|
-
controller:
|
79
|
+
controller: controller,
|
33
80
|
action: :show,
|
34
|
-
access_token: token.
|
81
|
+
access_token: token.plaintext_token,
|
35
82
|
}
|
36
83
|
end
|
37
84
|
|
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)
|
85
|
+
def access_token?
|
86
|
+
true
|
48
87
|
end
|
49
88
|
|
50
|
-
|
51
|
-
|
89
|
+
private
|
90
|
+
|
91
|
+
def controller
|
92
|
+
@controller ||= begin
|
93
|
+
mapping = Doorkeeper::Rails::Routes.mapping[:token_info] || {}
|
94
|
+
mapping[:controllers] || "doorkeeper/token_info"
|
95
|
+
end
|
52
96
|
end
|
53
97
|
end
|
54
98
|
end
|
@@ -1,27 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "rack/utils"
|
4
|
+
|
1
5
|
module Doorkeeper
|
2
6
|
module OAuth
|
3
7
|
module Authorization
|
4
|
-
|
5
|
-
|
8
|
+
class URIBuilder
|
9
|
+
class << self
|
10
|
+
def uri_with_query(url, parameters = {})
|
11
|
+
uri = URI.parse(url)
|
12
|
+
original_query = Rack::Utils.parse_query(uri.query)
|
13
|
+
uri.query = build_query(original_query.merge(parameters))
|
14
|
+
uri.to_s
|
15
|
+
end
|
6
16
|
|
7
|
-
|
17
|
+
def uri_with_fragment(url, parameters = {})
|
18
|
+
uri = URI.parse(url)
|
19
|
+
uri.fragment = build_query(parameters)
|
20
|
+
uri.to_s
|
21
|
+
end
|
8
22
|
|
9
|
-
|
10
|
-
uri = URI.parse(url)
|
11
|
-
original_query = parse_query(uri.query)
|
12
|
-
uri.query = build_query(original_query.merge(parameters))
|
13
|
-
uri.to_s
|
14
|
-
end
|
15
|
-
|
16
|
-
def uri_with_fragment(url, parameters = {})
|
17
|
-
uri = URI.parse(url)
|
18
|
-
uri.fragment = build_query(parameters)
|
19
|
-
uri.to_s
|
20
|
-
end
|
23
|
+
private
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
+
def build_query(parameters = {})
|
26
|
+
parameters.reject! { |_, value| value.blank? }
|
27
|
+
Rack::Utils.build_query(parameters)
|
28
|
+
end
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|