doorkeeper 5.1.0 → 5.5.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/{NEWS.md → CHANGELOG.md} +242 -25
- data/README.md +21 -11
- data/app/controllers/doorkeeper/application_controller.rb +3 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +8 -7
- data/app/controllers/doorkeeper/authorizations_controller.rb +56 -19
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +6 -6
- data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +93 -25
- data/app/views/doorkeeper/applications/_form.html.erb +1 -7
- data/app/views/doorkeeper/applications/show.html.erb +35 -14
- data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
- data/config/locales/en.yml +13 -3
- data/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/lib/doorkeeper/config/option.rb +20 -2
- data/lib/doorkeeper/config/validations.rb +53 -0
- data/lib/doorkeeper/config.rb +295 -121
- data/lib/doorkeeper/engine.rb +1 -1
- data/lib/doorkeeper/errors.rb +13 -18
- 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/helpers.rb +7 -3
- data/lib/doorkeeper/helpers/controller.rb +36 -11
- data/lib/doorkeeper/models/access_grant_mixin.rb +22 -18
- data/lib/doorkeeper/models/access_token_mixin.rb +194 -51
- data/lib/doorkeeper/models/application_mixin.rb +8 -7
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
- data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
- data/lib/doorkeeper/oauth/authorization/code.rb +25 -14
- data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
- data/lib/doorkeeper/oauth/authorization/token.rb +24 -19
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
- data/lib/doorkeeper/oauth/authorization_code_request.rb +40 -21
- data/lib/doorkeeper/oauth/base_request.rb +21 -23
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
- data/lib/doorkeeper/oauth/client.rb +8 -9
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +45 -5
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
- data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +13 -3
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
- data/lib/doorkeeper/oauth/code_request.rb +6 -12
- data/lib/doorkeeper/oauth/code_response.rb +24 -14
- data/lib/doorkeeper/oauth/error.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +10 -11
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -5
- 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 +7 -4
- data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +34 -11
- data/lib/doorkeeper/oauth/pre_authorization.rb +111 -42
- data/lib/doorkeeper/oauth/refresh_token_request.rb +45 -33
- data/lib/doorkeeper/oauth/token.rb +6 -7
- data/lib/doorkeeper/oauth/token_introspection.rb +24 -18
- data/lib/doorkeeper/oauth/token_request.rb +6 -20
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
- data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
- data/lib/doorkeeper/orm/active_record/application.rb +5 -83
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +68 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +59 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +198 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
- data/lib/doorkeeper/orm/active_record.rb +20 -6
- data/lib/doorkeeper/rails/helpers.rb +4 -4
- data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
- data/lib/doorkeeper/rails/routes/registry.rb +45 -0
- data/lib/doorkeeper/rails/routes.rb +17 -25
- data/lib/doorkeeper/rake/db.rake +6 -6
- data/lib/doorkeeper/rake/setup.rake +5 -0
- data/lib/doorkeeper/request/authorization_code.rb +5 -3
- data/lib/doorkeeper/request/client_credentials.rb +2 -2
- data/lib/doorkeeper/request/password.rb +3 -2
- data/lib/doorkeeper/request/refresh_token.rb +5 -4
- data/lib/doorkeeper/request/strategy.rb +2 -2
- data/lib/doorkeeper/request.rb +49 -17
- data/lib/doorkeeper/server.rb +7 -11
- data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
- data/lib/doorkeeper/version.rb +2 -6
- data/lib/doorkeeper.rb +114 -79
- data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
- data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/lib/generators/doorkeeper/migration_generator.rb +1 -1
- data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
- data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +205 -43
- data/lib/generators/doorkeeper/templates/migration.rb.erb +18 -6
- metadata +45 -312
- data/.coveralls.yml +0 -1
- data/.github/ISSUE_TEMPLATE.md +0 -25
- data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
- data/.gitignore +0 -20
- data/.gitlab-ci.yml +0 -16
- data/.hound.yml +0 -3
- data/.rspec +0 -1
- data/.rubocop.yml +0 -50
- data/.travis.yml +0 -35
- data/Appraisals +0 -40
- data/CODE_OF_CONDUCT.md +0 -46
- data/CONTRIBUTING.md +0 -47
- data/Dangerfile +0 -67
- data/Gemfile +0 -24
- data/RELEASING.md +0 -10
- data/Rakefile +0 -28
- data/SECURITY.md +0 -15
- data/UPGRADE.md +0 -2
- data/app/validators/redirect_uri_validator.rb +0 -50
- data/bin/console +0 -16
- data/doorkeeper.gemspec +0 -34
- data/gemfiles/rails_5_0.gemfile +0 -17
- data/gemfiles/rails_5_1.gemfile +0 -17
- data/gemfiles/rails_5_2.gemfile +0 -17
- data/gemfiles/rails_6_0.gemfile +0 -17
- data/gemfiles/rails_master.gemfile +0 -17
- data/spec/controllers/application_metal_controller_spec.rb +0 -64
- data/spec/controllers/applications_controller_spec.rb +0 -180
- data/spec/controllers/authorizations_controller_spec.rb +0 -527
- data/spec/controllers/protected_resources_controller_spec.rb +0 -353
- data/spec/controllers/token_info_controller_spec.rb +0 -50
- data/spec/controllers/tokens_controller_spec.rb +0 -330
- data/spec/dummy/Rakefile +0 -9
- data/spec/dummy/app/assets/config/manifest.js +0 -2
- data/spec/dummy/app/controllers/application_controller.rb +0 -5
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
- data/spec/dummy/app/controllers/home_controller.rb +0 -18
- data/spec/dummy/app/controllers/metal_controller.rb +0 -13
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
- data/spec/dummy/app/helpers/application_helper.rb +0 -7
- data/spec/dummy/app/models/user.rb +0 -7
- 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 -47
- data/spec/dummy/config/boot.rb +0 -7
- data/spec/dummy/config/database.yml +0 -15
- data/spec/dummy/config/environment.rb +0 -5
- data/spec/dummy/config/environments/development.rb +0 -31
- data/spec/dummy/config/environments/production.rb +0 -64
- data/spec/dummy/config/environments/test.rb +0 -45
- data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
- data/spec/dummy/config/initializers/doorkeeper.rb +0 -121
- data/spec/dummy/config/initializers/secret_token.rb +0 -10
- data/spec/dummy/config/initializers/session_store.rb +0 -10
- data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
- data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
- data/spec/dummy/config/routes.rb +0 -13
- data/spec/dummy/config.ru +0 -6
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
- data/spec/dummy/db/schema.rb +0 -68
- 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 -9
- data/spec/factories.rb +0 -30
- data/spec/generators/application_owner_generator_spec.rb +0 -28
- data/spec/generators/confidential_applications_generator_spec.rb +0 -29
- data/spec/generators/install_generator_spec.rb +0 -36
- data/spec/generators/migration_generator_spec.rb +0 -28
- data/spec/generators/pkce_generator_spec.rb +0 -28
- data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
- data/spec/generators/templates/routes.rb +0 -4
- data/spec/generators/views_generator_spec.rb +0 -29
- data/spec/grape/grape_integration_spec.rb +0 -137
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
- data/spec/lib/config_spec.rb +0 -697
- data/spec/lib/doorkeeper_spec.rb +0 -27
- data/spec/lib/models/expirable_spec.rb +0 -61
- data/spec/lib/models/reusable_spec.rb +0 -40
- data/spec/lib/models/revocable_spec.rb +0 -59
- data/spec/lib/models/scopes_spec.rb +0 -53
- data/spec/lib/models/secret_storable_spec.rb +0 -135
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
- data/spec/lib/oauth/authorization_code_request_spec.rb +0 -156
- data/spec/lib/oauth/base_request_spec.rb +0 -205
- data/spec/lib/oauth/base_response_spec.rb +0 -47
- data/spec/lib/oauth/client/credentials_spec.rb +0 -90
- data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -94
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
- data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
- data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
- data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
- data/spec/lib/oauth/client_spec.rb +0 -38
- data/spec/lib/oauth/code_request_spec.rb +0 -47
- data/spec/lib/oauth/code_response_spec.rb +0 -36
- data/spec/lib/oauth/error_response_spec.rb +0 -66
- data/spec/lib/oauth/error_spec.rb +0 -23
- data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -247
- data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
- data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
- data/spec/lib/oauth/pre_authorization_spec.rb +0 -215
- data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
- data/spec/lib/oauth/scopes_spec.rb +0 -148
- data/spec/lib/oauth/token_request_spec.rb +0 -150
- data/spec/lib/oauth/token_response_spec.rb +0 -86
- data/spec/lib/oauth/token_spec.rb +0 -158
- data/spec/lib/request/strategy_spec.rb +0 -54
- data/spec/lib/secret_storing/base_spec.rb +0 -60
- data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
- data/spec/lib/secret_storing/plain_spec.rb +0 -44
- data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
- data/spec/lib/server_spec.rb +0 -61
- data/spec/lib/stale_records_cleaner_spec.rb +0 -89
- data/spec/models/doorkeeper/access_grant_spec.rb +0 -144
- data/spec/models/doorkeeper/access_token_spec.rb +0 -591
- data/spec/models/doorkeeper/application_spec.rb +0 -367
- data/spec/requests/applications/applications_request_spec.rb +0 -259
- data/spec/requests/applications/authorized_applications_spec.rb +0 -32
- data/spec/requests/endpoints/authorization_spec.rb +0 -73
- data/spec/requests/endpoints/token_spec.rb +0 -75
- data/spec/requests/flows/authorization_code_errors_spec.rb +0 -78
- data/spec/requests/flows/authorization_code_spec.rb +0 -447
- data/spec/requests/flows/client_credentials_spec.rb +0 -128
- data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -34
- data/spec/requests/flows/implicit_grant_spec.rb +0 -90
- data/spec/requests/flows/password_spec.rb +0 -259
- data/spec/requests/flows/refresh_token_spec.rb +0 -233
- data/spec/requests/flows/revoke_token_spec.rb +0 -143
- data/spec/requests/flows/skip_authorization_spec.rb +0 -66
- data/spec/requests/protected_resources/metal_spec.rb +0 -16
- data/spec/requests/protected_resources/private_api_spec.rb +0 -83
- data/spec/routing/custom_controller_routes_spec.rb +0 -133
- data/spec/routing/default_routes_spec.rb +0 -41
- data/spec/routing/scoped_routes_spec.rb +0 -47
- data/spec/spec_helper.rb +0 -57
- data/spec/spec_helper_integration.rb +0 -4
- data/spec/support/dependencies/factory_bot.rb +0 -4
- data/spec/support/doorkeeper_rspec.rb +0 -22
- data/spec/support/helpers/access_token_request_helper.rb +0 -13
- data/spec/support/helpers/authorization_request_helper.rb +0 -43
- data/spec/support/helpers/config_helper.rb +0 -11
- data/spec/support/helpers/model_helper.rb +0 -78
- data/spec/support/helpers/request_spec_helper.rb +0 -98
- data/spec/support/helpers/url_helper.rb +0 -62
- data/spec/support/http_method_shim.rb +0 -29
- data/spec/support/orm/active_record.rb +0 -5
- data/spec/support/shared/controllers_shared_context.rb +0 -123
- data/spec/support/shared/hashing_shared_context.rb +0 -36
- data/spec/support/shared/models_shared_examples.rb +0 -54
- data/spec/validators/redirect_uri_validator_spec.rb +0 -158
- data/spec/version/version_spec.rb +0 -17
@@ -11,28 +11,28 @@ module Doorkeeper
|
|
11
11
|
validate :client_match, error: :invalid_grant
|
12
12
|
validate :scope, error: :invalid_scope
|
13
13
|
|
14
|
-
|
15
|
-
|
14
|
+
attr_reader :access_token, :client, :credentials, :refresh_token
|
15
|
+
attr_reader :missing_param
|
16
16
|
|
17
17
|
def initialize(server, refresh_token, credentials, parameters = {})
|
18
|
-
@server
|
19
|
-
@refresh_token
|
20
|
-
@credentials
|
18
|
+
@server = server
|
19
|
+
@refresh_token = refresh_token
|
20
|
+
@credentials = credentials
|
21
21
|
@original_scopes = parameters[:scope] || parameters[:scopes]
|
22
22
|
@refresh_token_parameter = parameters[:refresh_token]
|
23
|
-
|
24
|
-
if credentials
|
25
|
-
@client = Application.by_uid_and_secret credentials.uid,
|
26
|
-
credentials.secret
|
27
|
-
end
|
23
|
+
@client = load_client(credentials) if credentials
|
28
24
|
end
|
29
25
|
|
30
26
|
private
|
31
27
|
|
28
|
+
def load_client(credentials)
|
29
|
+
server_config.application_model.by_uid_and_secret(credentials.uid, credentials.secret)
|
30
|
+
end
|
31
|
+
|
32
32
|
def before_successful_response
|
33
33
|
refresh_token.transaction do
|
34
34
|
refresh_token.lock!
|
35
|
-
raise Errors::
|
35
|
+
raise Errors::InvalidGrantReuse if refresh_token.revoked?
|
36
36
|
|
37
37
|
refresh_token.revoke unless refresh_token_revoked_on_use?
|
38
38
|
create_access_token
|
@@ -41,7 +41,7 @@ module Doorkeeper
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def refresh_token_revoked_on_use?
|
44
|
-
|
44
|
+
server_config.access_token_model.refresh_token_revoked_on_use?
|
45
45
|
end
|
46
46
|
|
47
47
|
def default_scopes
|
@@ -49,34 +49,46 @@ module Doorkeeper
|
|
49
49
|
end
|
50
50
|
|
51
51
|
def create_access_token
|
52
|
-
|
53
|
-
end
|
52
|
+
attributes = {}
|
54
53
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
expires_in: access_token_expires_in,
|
61
|
-
use_refresh_token: true,
|
62
|
-
}.tap do |attributes|
|
63
|
-
if refresh_token_revoked_on_use?
|
64
|
-
attributes[:previous_refresh_token] = refresh_token.refresh_token
|
54
|
+
resource_owner =
|
55
|
+
if Doorkeeper.config.polymorphic_resource_owner?
|
56
|
+
refresh_token.resource_owner
|
57
|
+
else
|
58
|
+
refresh_token.resource_owner_id
|
65
59
|
end
|
60
|
+
|
61
|
+
if refresh_token_revoked_on_use?
|
62
|
+
attributes[:previous_refresh_token] = refresh_token.refresh_token
|
66
63
|
end
|
67
|
-
end
|
68
64
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
65
|
+
# RFC6749
|
66
|
+
# 1.5. Refresh Token
|
67
|
+
#
|
68
|
+
# Refresh tokens are issued to the client by the authorization server and are
|
69
|
+
# used to obtain a new access token when the current access token
|
70
|
+
# becomes invalid or expires, or to obtain additional access tokens
|
71
|
+
# with identical or narrower scope (access tokens may have a shorter
|
72
|
+
# lifetime and fewer permissions than authorized by the resource
|
73
|
+
# owner).
|
74
|
+
#
|
75
|
+
# Here we assume that TTL of the token received after refreshing should be
|
76
|
+
# the same as that of the original token.
|
77
|
+
#
|
78
|
+
@access_token = server_config.access_token_model.create_for(
|
79
|
+
application: refresh_token.application,
|
80
|
+
resource_owner: resource_owner,
|
81
|
+
scopes: scopes,
|
82
|
+
expires_in: refresh_token.expires_in,
|
83
|
+
use_refresh_token: true,
|
84
|
+
**attributes,
|
74
85
|
)
|
75
|
-
Authorization::Token.access_token_expires_in(server, context)
|
76
86
|
end
|
77
87
|
|
78
88
|
def validate_token_presence
|
79
|
-
refresh_token.
|
89
|
+
@missing_param = :refresh_token if refresh_token.blank? && @refresh_token_parameter.blank?
|
90
|
+
|
91
|
+
@missing_param.nil?
|
80
92
|
end
|
81
93
|
|
82
94
|
def validate_token
|
@@ -101,7 +113,7 @@ module Doorkeeper
|
|
101
113
|
if @original_scopes.present?
|
102
114
|
ScopeChecker.valid?(
|
103
115
|
scope_str: @original_scopes,
|
104
|
-
server_scopes: refresh_token.scopes
|
116
|
+
server_scopes: refresh_token.scopes,
|
105
117
|
)
|
106
118
|
else
|
107
119
|
true
|
@@ -8,15 +8,14 @@ module Doorkeeper
|
|
8
8
|
methods.inject(nil) do |_, method|
|
9
9
|
method = self.method(method) if method.is_a?(Symbol)
|
10
10
|
credentials = method.call(request)
|
11
|
-
break credentials
|
11
|
+
break credentials if credentials.present?
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
def authenticate(request, *methods)
|
16
16
|
if (token = from_request(request, *methods))
|
17
|
-
access_token =
|
18
|
-
|
19
|
-
if access_token.present? && refresh_token_enabled
|
17
|
+
access_token = Doorkeeper.config.access_token_model.by_token(token)
|
18
|
+
if access_token.present? && Doorkeeper.config.refresh_token_enabled?
|
20
19
|
access_token.revoke_previous_refresh_token!
|
21
20
|
end
|
22
21
|
access_token
|
@@ -33,13 +32,13 @@ module Doorkeeper
|
|
33
32
|
|
34
33
|
def from_bearer_authorization(request)
|
35
34
|
pattern = /^Bearer /i
|
36
|
-
header
|
35
|
+
header = request.authorization
|
37
36
|
token_from_header(header, pattern) if match?(header, pattern)
|
38
37
|
end
|
39
38
|
|
40
39
|
def from_basic_authorization(request)
|
41
40
|
pattern = /^Basic /i
|
42
|
-
header
|
41
|
+
header = request.authorization
|
43
42
|
token_from_basic_header(header, pattern) if match?(header, pattern)
|
44
43
|
end
|
45
44
|
|
@@ -55,7 +54,7 @@ module Doorkeeper
|
|
55
54
|
end
|
56
55
|
|
57
56
|
def token_from_header(header, pattern)
|
58
|
-
header.gsub
|
57
|
+
header.gsub(pattern, "")
|
59
58
|
end
|
60
59
|
|
61
60
|
def match?(header, pattern)
|
@@ -6,9 +6,6 @@ module Doorkeeper
|
|
6
6
|
#
|
7
7
|
# @see https://tools.ietf.org/html/rfc7662
|
8
8
|
class TokenIntrospection
|
9
|
-
attr_reader :server, :token
|
10
|
-
attr_reader :error
|
11
|
-
|
12
9
|
def initialize(server, token)
|
13
10
|
@server = server
|
14
11
|
@token = token
|
@@ -25,6 +22,8 @@ module Doorkeeper
|
|
25
22
|
|
26
23
|
if @error == :invalid_token
|
27
24
|
OAuth::InvalidTokenResponse.from_access_token(authorized_token)
|
25
|
+
elsif @error == :invalid_request
|
26
|
+
OAuth::InvalidRequestResponse.from_request(self)
|
28
27
|
else
|
29
28
|
OAuth::ErrorResponse.new(name: @error)
|
30
29
|
end
|
@@ -36,6 +35,9 @@ module Doorkeeper
|
|
36
35
|
|
37
36
|
private
|
38
37
|
|
38
|
+
attr_reader :server, :token
|
39
|
+
attr_reader :error, :invalid_request_reason
|
40
|
+
|
39
41
|
# If the protected resource uses OAuth 2.0 client credentials to
|
40
42
|
# authenticate to the introspection endpoint and its credentials are
|
41
43
|
# invalid, the authorization server responds with an HTTP 401
|
@@ -67,9 +69,10 @@ module Doorkeeper
|
|
67
69
|
# HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
|
68
70
|
# Usage [RFC6750].
|
69
71
|
#
|
70
|
-
@error = :invalid_token
|
72
|
+
@error = :invalid_token unless valid_authorized_token?
|
71
73
|
else
|
72
74
|
@error = :invalid_request
|
75
|
+
@invalid_request_reason = :request_not_authorized
|
73
76
|
end
|
74
77
|
end
|
75
78
|
|
@@ -80,8 +83,7 @@ module Doorkeeper
|
|
80
83
|
|
81
84
|
# Bearer Token Authentication
|
82
85
|
def authorized_token
|
83
|
-
@authorized_token ||=
|
84
|
-
OAuth::Token.authenticate(server.context.request, :from_bearer_authorization)
|
86
|
+
@authorized_token ||= Doorkeeper.authenticate(server.context.request)
|
85
87
|
end
|
86
88
|
|
87
89
|
# 2.2. Introspection Response
|
@@ -92,7 +94,7 @@ module Doorkeeper
|
|
92
94
|
client_id: @token.try(:application).try(:uid),
|
93
95
|
token_type: @token.token_type,
|
94
96
|
exp: @token.expires_at.to_i,
|
95
|
-
iat: @token.created_at.to_i
|
97
|
+
iat: @token.created_at.to_i,
|
96
98
|
)
|
97
99
|
end
|
98
100
|
|
@@ -150,7 +152,7 @@ module Doorkeeper
|
|
150
152
|
#
|
151
153
|
def active?
|
152
154
|
if authorized_client
|
153
|
-
valid_token? &&
|
155
|
+
valid_token? && token_introspection_allowed?(auth_client: authorized_client.application)
|
154
156
|
else
|
155
157
|
valid_token?
|
156
158
|
end
|
@@ -161,19 +163,23 @@ module Doorkeeper
|
|
161
163
|
@token&.accessible?
|
162
164
|
end
|
163
165
|
|
166
|
+
def valid_authorized_token?
|
167
|
+
!authorized_token_matches_introspected? &&
|
168
|
+
authorized_token.accessible? &&
|
169
|
+
token_introspection_allowed?(auth_token: authorized_token)
|
170
|
+
end
|
171
|
+
|
164
172
|
# RFC7662 Section 2.1
|
165
173
|
def authorized_token_matches_introspected?
|
166
174
|
authorized_token.token == @token&.token
|
167
175
|
end
|
168
176
|
|
169
|
-
#
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
true
|
176
|
-
end
|
177
|
+
# Config constraints for introspection in Doorkeeper.config.allow_token_introspection
|
178
|
+
def token_introspection_allowed?(auth_client: nil, auth_token: nil)
|
179
|
+
allow_introspection = Doorkeeper.config.allow_token_introspection
|
180
|
+
return allow_introspection unless allow_introspection.respond_to?(:call)
|
181
|
+
|
182
|
+
allow_introspection.call(@token, auth_client, auth_token)
|
177
183
|
end
|
178
184
|
|
179
185
|
# Allows to customize introspection response.
|
@@ -183,9 +189,9 @@ module Doorkeeper
|
|
183
189
|
# @see https://tools.ietf.org/html/rfc7662#section-2.2
|
184
190
|
#
|
185
191
|
def customize_response(response)
|
186
|
-
customized_response = Doorkeeper.
|
192
|
+
customized_response = Doorkeeper.config.custom_introspection_response.call(
|
187
193
|
token,
|
188
|
-
server.context
|
194
|
+
server.context,
|
189
195
|
)
|
190
196
|
return response if customized_response.blank?
|
191
197
|
|
@@ -3,36 +3,22 @@
|
|
3
3
|
module Doorkeeper
|
4
4
|
module OAuth
|
5
5
|
class TokenRequest
|
6
|
-
|
6
|
+
attr_reader :pre_auth, :resource_owner
|
7
7
|
|
8
8
|
def initialize(pre_auth, resource_owner)
|
9
|
-
@pre_auth
|
9
|
+
@pre_auth = pre_auth
|
10
10
|
@resource_owner = resource_owner
|
11
11
|
end
|
12
12
|
|
13
13
|
def authorize
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
@response = CodeResponse.new pre_auth,
|
18
|
-
auth,
|
19
|
-
response_on_fragment: true
|
20
|
-
else
|
21
|
-
@response = error_response
|
22
|
-
end
|
14
|
+
auth = Authorization::Token.new(pre_auth, resource_owner)
|
15
|
+
auth.issue_token!
|
16
|
+
CodeResponse.new(pre_auth, auth, response_on_fragment: true)
|
23
17
|
end
|
24
18
|
|
25
19
|
def deny
|
26
20
|
pre_auth.error = :access_denied
|
27
|
-
error_response
|
28
|
-
end
|
29
|
-
|
30
|
-
private
|
31
|
-
|
32
|
-
def error_response
|
33
|
-
ErrorResponse.from_request pre_auth,
|
34
|
-
redirect_uri: pre_auth.redirect_uri,
|
35
|
-
response_on_fragment: true
|
21
|
+
pre_auth.error_response
|
36
22
|
end
|
37
23
|
end
|
38
24
|
end
|
@@ -1,48 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class AccessGrant < ActiveRecord::Base
|
5
|
-
self.table_name = "#{table_name_prefix}oauth_access_grants#{table_name_suffix}"
|
6
|
-
|
7
|
-
include AccessGrantMixin
|
8
|
-
|
9
|
-
belongs_to :application, class_name: "Doorkeeper::Application",
|
10
|
-
optional: true, inverse_of: :access_grants
|
11
|
-
|
12
|
-
validates :resource_owner_id,
|
13
|
-
:application_id,
|
14
|
-
:token,
|
15
|
-
:expires_in,
|
16
|
-
:redirect_uri,
|
17
|
-
presence: true
|
18
|
-
|
19
|
-
validates :token, uniqueness: true
|
3
|
+
require "doorkeeper/orm/active_record/mixins/access_grant"
|
20
4
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
# The stored refresh_token may be mapped and not available in cleartext.
|
25
|
-
#
|
26
|
-
# Some strategies allow restoring stored secrets (e.g. symmetric encryption)
|
27
|
-
# while hashing strategies do not, so you cannot rely on this value
|
28
|
-
# returning a present value for persisted tokens.
|
29
|
-
def plaintext_token
|
30
|
-
if secret_strategy.allows_restoring_secrets?
|
31
|
-
secret_strategy.restore_secret(self, :token)
|
32
|
-
else
|
33
|
-
@raw_token
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
# Generates token value with UniqueToken class.
|
40
|
-
#
|
41
|
-
# @return [String] token value
|
42
|
-
#
|
43
|
-
def generate_token
|
44
|
-
@raw_token = UniqueToken.generate
|
45
|
-
secret_strategy.store_secret(self, :token, @raw_token)
|
46
|
-
end
|
5
|
+
module Doorkeeper
|
6
|
+
class AccessGrant < ::ActiveRecord::Base
|
7
|
+
include Doorkeeper::Orm::ActiveRecord::Mixins::AccessGrant
|
47
8
|
end
|
48
9
|
end
|
@@ -1,40 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
class AccessToken < ActiveRecord::Base
|
5
|
-
self.table_name = "#{table_name_prefix}oauth_access_tokens#{table_name_suffix}"
|
6
|
-
|
7
|
-
include AccessTokenMixin
|
8
|
-
|
9
|
-
belongs_to :application, class_name: "Doorkeeper::Application",
|
10
|
-
inverse_of: :access_tokens, optional: true
|
11
|
-
|
12
|
-
validates :token, presence: true, uniqueness: true
|
13
|
-
validates :refresh_token, uniqueness: true, if: :use_refresh_token?
|
3
|
+
require "doorkeeper/orm/active_record/mixins/access_token"
|
14
4
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
before_validation :generate_token, on: :create
|
20
|
-
before_validation :generate_refresh_token,
|
21
|
-
on: :create, if: :use_refresh_token?
|
22
|
-
|
23
|
-
# Searches for not revoked Access Tokens associated with the
|
24
|
-
# specific Resource Owner.
|
25
|
-
#
|
26
|
-
# @param resource_owner [ActiveRecord::Base]
|
27
|
-
# Resource Owner model instance
|
28
|
-
#
|
29
|
-
# @return [ActiveRecord::Relation]
|
30
|
-
# active Access Tokens for Resource Owner
|
31
|
-
#
|
32
|
-
def self.active_for(resource_owner)
|
33
|
-
where(resource_owner_id: resource_owner.id, revoked_at: nil)
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.refresh_token_revoked_on_use?
|
37
|
-
column_names.include?("previous_refresh_token")
|
38
|
-
end
|
5
|
+
module Doorkeeper
|
6
|
+
class AccessToken < ::ActiveRecord::Base
|
7
|
+
include Doorkeeper::Orm::ActiveRecord::Mixins::AccessToken
|
39
8
|
end
|
40
9
|
end
|
@@ -1,88 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}"
|
6
|
-
|
7
|
-
include ApplicationMixin
|
8
|
-
|
9
|
-
has_many :access_grants, dependent: :delete_all, class_name: "Doorkeeper::AccessGrant"
|
10
|
-
has_many :access_tokens, dependent: :delete_all, class_name: "Doorkeeper::AccessToken"
|
11
|
-
|
12
|
-
validates :name, :secret, :uid, presence: true
|
13
|
-
validates :uid, uniqueness: true
|
14
|
-
validates :redirect_uri, redirect_uri: true
|
15
|
-
validates :confidential, inclusion: { in: [true, false] }
|
16
|
-
|
17
|
-
validate :scopes_match_configured, if: :enforce_scopes?
|
18
|
-
|
19
|
-
before_validation :generate_uid, :generate_secret, on: :create
|
20
|
-
|
21
|
-
has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: "AccessToken"
|
22
|
-
has_many :authorized_applications, through: :authorized_tokens, source: :application
|
23
|
-
|
24
|
-
# Returns Applications associated with active (not revoked) Access Tokens
|
25
|
-
# that are owned by the specific Resource Owner.
|
26
|
-
#
|
27
|
-
# @param resource_owner [ActiveRecord::Base]
|
28
|
-
# Resource Owner model instance
|
29
|
-
#
|
30
|
-
# @return [ActiveRecord::Relation]
|
31
|
-
# Applications authorized for the Resource Owner
|
32
|
-
#
|
33
|
-
def self.authorized_for(resource_owner)
|
34
|
-
resource_access_tokens = AccessToken.active_for(resource_owner)
|
35
|
-
where(id: resource_access_tokens.select(:application_id).distinct)
|
36
|
-
end
|
3
|
+
require "doorkeeper/orm/active_record/redirect_uri_validator"
|
4
|
+
require "doorkeeper/orm/active_record/mixins/application"
|
37
5
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
# @param resource_owner [ActiveRecord::Base]
|
42
|
-
# instance of the Resource Owner model
|
43
|
-
#
|
44
|
-
def self.revoke_tokens_and_grants_for(id, resource_owner)
|
45
|
-
AccessToken.revoke_all_for(id, resource_owner)
|
46
|
-
AccessGrant.revoke_all_for(id, resource_owner)
|
47
|
-
end
|
48
|
-
|
49
|
-
# We keep a volatile copy of the raw secret for initial communication
|
50
|
-
# The stored refresh_token may be mapped and not available in cleartext.
|
51
|
-
#
|
52
|
-
# Some strategies allow restoring stored secrets (e.g. symmetric encryption)
|
53
|
-
# while hashing strategies do not, so you cannot rely on this value
|
54
|
-
# returning a present value for persisted tokens.
|
55
|
-
def plaintext_secret
|
56
|
-
if secret_strategy.allows_restoring_secrets?
|
57
|
-
secret_strategy.restore_secret(self, :secret)
|
58
|
-
else
|
59
|
-
@raw_secret
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def generate_uid
|
66
|
-
self.uid = UniqueToken.generate if uid.blank?
|
67
|
-
end
|
68
|
-
|
69
|
-
def generate_secret
|
70
|
-
return unless secret.blank?
|
71
|
-
|
72
|
-
@raw_secret = UniqueToken.generate
|
73
|
-
secret_strategy.store_secret(self, :secret, @raw_secret)
|
74
|
-
end
|
75
|
-
|
76
|
-
def scopes_match_configured
|
77
|
-
if scopes.present? &&
|
78
|
-
!ScopeChecker.valid?(scope_str: scopes.to_s,
|
79
|
-
server_scopes: Doorkeeper.configuration.scopes)
|
80
|
-
errors.add(:scopes, :not_match_configured)
|
81
|
-
end
|
82
|
-
end
|
83
|
-
|
84
|
-
def enforce_scopes?
|
85
|
-
Doorkeeper.configuration.enforce_configured_scopes?
|
86
|
-
end
|
6
|
+
module Doorkeeper
|
7
|
+
class Application < ::ActiveRecord::Base
|
8
|
+
include ::Doorkeeper::Orm::ActiveRecord::Mixins::Application
|
87
9
|
end
|
88
10
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper::Orm::ActiveRecord::Mixins
|
4
|
+
module AccessGrant
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
self.table_name = compute_doorkeeper_table_name
|
9
|
+
|
10
|
+
include ::Doorkeeper::AccessGrantMixin
|
11
|
+
|
12
|
+
belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
|
13
|
+
optional: true,
|
14
|
+
inverse_of: :access_grants
|
15
|
+
|
16
|
+
if Doorkeeper.config.polymorphic_resource_owner?
|
17
|
+
belongs_to :resource_owner, polymorphic: true, optional: false
|
18
|
+
else
|
19
|
+
validates :resource_owner_id, presence: true
|
20
|
+
end
|
21
|
+
|
22
|
+
validates :application_id,
|
23
|
+
:token,
|
24
|
+
:expires_in,
|
25
|
+
:redirect_uri,
|
26
|
+
presence: true
|
27
|
+
|
28
|
+
validates :token, uniqueness: { case_sensitive: true }
|
29
|
+
|
30
|
+
before_validation :generate_token, on: :create
|
31
|
+
|
32
|
+
# We keep a volatile copy of the raw token for initial communication
|
33
|
+
# The stored refresh_token may be mapped and not available in cleartext.
|
34
|
+
#
|
35
|
+
# Some strategies allow restoring stored secrets (e.g. symmetric encryption)
|
36
|
+
# while hashing strategies do not, so you cannot rely on this value
|
37
|
+
# returning a present value for persisted tokens.
|
38
|
+
def plaintext_token
|
39
|
+
if secret_strategy.allows_restoring_secrets?
|
40
|
+
secret_strategy.restore_secret(self, :token)
|
41
|
+
else
|
42
|
+
@raw_token
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
# Generates token value with UniqueToken class.
|
49
|
+
#
|
50
|
+
# @return [String] token value
|
51
|
+
#
|
52
|
+
def generate_token
|
53
|
+
@raw_token = Doorkeeper::OAuth::Helpers::UniqueToken.generate
|
54
|
+
secret_strategy.store_secret(self, :token, @raw_token)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
module ClassMethods
|
59
|
+
private
|
60
|
+
|
61
|
+
def compute_doorkeeper_table_name
|
62
|
+
table_name = "oauth_access_grant"
|
63
|
+
table_name = table_name.pluralize if pluralize_table_names
|
64
|
+
"#{table_name_prefix}#{table_name}#{table_name_suffix}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper::Orm::ActiveRecord::Mixins
|
4
|
+
module AccessToken
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
self.table_name = compute_doorkeeper_table_name
|
9
|
+
|
10
|
+
include ::Doorkeeper::AccessTokenMixin
|
11
|
+
|
12
|
+
belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
|
13
|
+
inverse_of: :access_tokens,
|
14
|
+
optional: true
|
15
|
+
|
16
|
+
if Doorkeeper.config.polymorphic_resource_owner?
|
17
|
+
belongs_to :resource_owner, polymorphic: true, optional: true
|
18
|
+
end
|
19
|
+
|
20
|
+
validates :token, presence: true, uniqueness: { case_sensitive: true }
|
21
|
+
validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
|
22
|
+
|
23
|
+
# @attr_writer [Boolean, nil] use_refresh_token
|
24
|
+
# indicates the possibility of using refresh token
|
25
|
+
attr_writer :use_refresh_token
|
26
|
+
|
27
|
+
before_validation :generate_token, on: :create
|
28
|
+
before_validation :generate_refresh_token,
|
29
|
+
on: :create, if: :use_refresh_token?
|
30
|
+
end
|
31
|
+
|
32
|
+
module ClassMethods
|
33
|
+
# Searches for not revoked Access Tokens associated with the
|
34
|
+
# specific Resource Owner.
|
35
|
+
#
|
36
|
+
# @param resource_owner [ActiveRecord::Base]
|
37
|
+
# Resource Owner model instance
|
38
|
+
#
|
39
|
+
# @return [ActiveRecord::Relation]
|
40
|
+
# active Access Tokens for Resource Owner
|
41
|
+
#
|
42
|
+
def active_for(resource_owner)
|
43
|
+
by_resource_owner(resource_owner).where(revoked_at: nil)
|
44
|
+
end
|
45
|
+
|
46
|
+
def refresh_token_revoked_on_use?
|
47
|
+
column_names.include?("previous_refresh_token")
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def compute_doorkeeper_table_name
|
53
|
+
table_name = "oauth_access_token"
|
54
|
+
table_name = table_name.pluralize if pluralize_table_names
|
55
|
+
"#{table_name_prefix}#{table_name}#{table_name_suffix}"
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|