doorkeeper 5.2.0 → 5.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Appraisals +2 -2
- data/CHANGELOG.md +40 -2
- data/Gemfile +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
- data/app/controllers/doorkeeper/applications_controller.rb +0 -1
- data/app/controllers/doorkeeper/authorizations_controller.rb +2 -2
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
- data/config/locales/en.yml +1 -1
- data/gemfiles/rails_5_0.gemfile +2 -2
- data/gemfiles/rails_5_1.gemfile +2 -2
- data/gemfiles/rails_5_2.gemfile +2 -2
- data/gemfiles/rails_6_0.gemfile +2 -2
- data/gemfiles/rails_master.gemfile +2 -2
- data/lib/doorkeeper/config.rb +71 -38
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +12 -8
- data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
- data/lib/doorkeeper/models/access_token_mixin.rb +56 -18
- data/lib/doorkeeper/models/application_mixin.rb +3 -3
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
- data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +0 -27
- data/lib/doorkeeper/oauth/authorization/code.rb +4 -4
- data/lib/doorkeeper/oauth/authorization/token.rb +9 -6
- data/lib/doorkeeper/oauth/authorization_code_request.rb +13 -6
- data/lib/doorkeeper/oauth/base_request.rb +8 -4
- data/lib/doorkeeper/oauth/client.rb +7 -8
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +16 -9
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
- data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +4 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +5 -5
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +7 -5
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -1
- data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -3
- data/lib/doorkeeper/oauth/pre_authorization.rb +12 -7
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -5
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +6 -6
- 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 -89
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +53 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +47 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +128 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +3 -3
- data/lib/doorkeeper/orm/active_record.rb +3 -4
- data/lib/doorkeeper/rails/helpers.rb +4 -4
- data/lib/doorkeeper/rails/routes.rb +5 -7
- data/lib/doorkeeper/rake/db.rake +3 -3
- data/lib/doorkeeper/request/authorization_code.rb +3 -3
- data/lib/doorkeeper/request/client_credentials.rb +2 -2
- data/lib/doorkeeper/request/password.rb +2 -2
- data/lib/doorkeeper/request/refresh_token.rb +3 -3
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/server.rb +1 -1
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/doorkeeper.rb +2 -3
- data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
- 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 +2 -2
- data/lib/generators/doorkeeper/templates/initializer.rb +39 -0
- data/spec/controllers/application_metal_controller_spec.rb +1 -1
- data/spec/controllers/applications_controller_spec.rb +3 -2
- data/spec/controllers/authorizations_controller_spec.rb +20 -18
- data/spec/controllers/protected_resources_controller_spec.rb +25 -17
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +1 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -3
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +1 -1
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +1 -1
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/previous_refresh_token_generator_spec.rb +2 -2
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +62 -7
- data/spec/lib/doorkeeper_spec.rb +1 -1
- data/spec/lib/models/revocable_spec.rb +3 -3
- data/spec/lib/oauth/authorization_code_request_spec.rb +127 -123
- data/spec/lib/oauth/base_request_spec.rb +160 -158
- data/spec/lib/oauth/base_response_spec.rb +27 -29
- data/spec/lib/oauth/client/credentials_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials/creator_spec.rb +42 -5
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +12 -12
- data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials_integration_spec.rb +16 -18
- data/spec/lib/oauth/client_credentials_request_spec.rb +78 -80
- data/spec/lib/oauth/client_spec.rb +26 -26
- data/spec/lib/oauth/code_request_spec.rb +34 -34
- data/spec/lib/oauth/code_response_spec.rb +21 -25
- data/spec/lib/oauth/error_response_spec.rb +42 -44
- data/spec/lib/oauth/error_spec.rb +12 -14
- data/spec/lib/oauth/forbidden_token_response_spec.rb +11 -13
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +30 -18
- data/spec/lib/oauth/invalid_request_response_spec.rb +48 -50
- data/spec/lib/oauth/invalid_token_response_spec.rb +32 -34
- data/spec/lib/oauth/password_access_token_request_spec.rb +145 -147
- data/spec/lib/oauth/pre_authorization_spec.rb +159 -161
- data/spec/lib/oauth/refresh_token_request_spec.rb +138 -139
- data/spec/lib/oauth/scopes_spec.rb +104 -106
- data/spec/lib/oauth/token_request_spec.rb +115 -111
- data/spec/lib/oauth/token_response_spec.rb +71 -73
- data/spec/lib/oauth/token_spec.rb +121 -123
- data/spec/models/doorkeeper/access_grant_spec.rb +21 -4
- data/spec/models/doorkeeper/access_token_spec.rb +42 -11
- data/spec/models/doorkeeper/application_spec.rb +114 -77
- data/spec/requests/applications/applications_request_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +5 -3
- data/spec/requests/flows/authorization_code_spec.rb +34 -22
- data/spec/requests/flows/client_credentials_spec.rb +1 -1
- data/spec/requests/flows/password_spec.rb +32 -12
- data/spec/requests/flows/refresh_token_spec.rb +19 -19
- data/spec/requests/flows/revoke_token_spec.rb +18 -12
- data/spec/spec_helper.rb +1 -4
- data/spec/support/shared/controllers_shared_context.rb +33 -23
- data/spec/validators/redirect_uri_validator_spec.rb +1 -1
- metadata +6 -5
- data/spec/support/http_method_shim.rb +0 -29
|
@@ -11,8 +11,8 @@ module Doorkeeper
|
|
|
11
11
|
state: request.try(:state),
|
|
12
12
|
redirect_uri: request.try(:redirect_uri),
|
|
13
13
|
missing_param: request.try(:missing_param),
|
|
14
|
-
reason: request.try(:invalid_request_reason)
|
|
15
|
-
)
|
|
14
|
+
reason: request.try(:invalid_request_reason),
|
|
15
|
+
),
|
|
16
16
|
)
|
|
17
17
|
end
|
|
18
18
|
|
|
@@ -31,7 +31,7 @@ module Doorkeeper
|
|
|
31
31
|
reason,
|
|
32
32
|
scope: %i[doorkeeper errors messages invalid_request],
|
|
33
33
|
default: :unknown,
|
|
34
|
-
value: @missing_param
|
|
34
|
+
value: @missing_param,
|
|
35
35
|
)
|
|
36
36
|
end
|
|
37
37
|
|
|
@@ -27,8 +27,11 @@ module Doorkeeper
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def description
|
|
30
|
-
|
|
31
|
-
|
|
30
|
+
@description ||=
|
|
31
|
+
I18n.translate(
|
|
32
|
+
@reason,
|
|
33
|
+
scope: %i[doorkeeper errors messages invalid_token],
|
|
34
|
+
)
|
|
32
35
|
end
|
|
33
36
|
|
|
34
37
|
protected
|
|
@@ -37,12 +37,12 @@ module Doorkeeper
|
|
|
37
37
|
scope_str: scopes.to_s,
|
|
38
38
|
server_scopes: server.scopes,
|
|
39
39
|
app_scopes: client_scopes,
|
|
40
|
-
grant_type: grant_type
|
|
40
|
+
grant_type: grant_type,
|
|
41
41
|
)
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def validate_resource_owner
|
|
45
|
-
|
|
45
|
+
resource_owner.present?
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def validate_client
|
|
@@ -50,7 +50,7 @@ module Doorkeeper
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def validate_client_supports_grant_flow
|
|
53
|
-
|
|
53
|
+
server_config.allow_grant_flow_for_client?(grant_type, client)
|
|
54
54
|
end
|
|
55
55
|
end
|
|
56
56
|
end
|
|
@@ -33,7 +33,7 @@ module Doorkeeper
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def validate_client_supports_grant_flow
|
|
36
|
-
Doorkeeper.
|
|
36
|
+
Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def scopes
|
|
@@ -45,12 +45,13 @@ module Doorkeeper
|
|
|
45
45
|
end
|
|
46
46
|
|
|
47
47
|
def error_response
|
|
48
|
-
is_implicit_flow = response_type == "token"
|
|
49
|
-
|
|
50
48
|
if error == :invalid_request
|
|
51
|
-
OAuth::InvalidRequestResponse.from_request(
|
|
49
|
+
OAuth::InvalidRequestResponse.from_request(
|
|
50
|
+
self,
|
|
51
|
+
response_on_fragment: response_on_fragment?,
|
|
52
|
+
)
|
|
52
53
|
else
|
|
53
|
-
OAuth::ErrorResponse.from_request(self, response_on_fragment:
|
|
54
|
+
OAuth::ErrorResponse.from_request(self, response_on_fragment: response_on_fragment?)
|
|
54
55
|
end
|
|
55
56
|
end
|
|
56
57
|
|
|
@@ -87,7 +88,7 @@ module Doorkeeper
|
|
|
87
88
|
|
|
88
89
|
Helpers::URIChecker.valid_for_authorization?(
|
|
89
90
|
redirect_uri,
|
|
90
|
-
client.redirect_uri
|
|
91
|
+
client.redirect_uri,
|
|
91
92
|
)
|
|
92
93
|
end
|
|
93
94
|
|
|
@@ -110,7 +111,7 @@ module Doorkeeper
|
|
|
110
111
|
scope_str: scope,
|
|
111
112
|
server_scopes: server.scopes,
|
|
112
113
|
app_scopes: client.scopes,
|
|
113
|
-
grant_type: grant_type
|
|
114
|
+
grant_type: grant_type,
|
|
114
115
|
)
|
|
115
116
|
end
|
|
116
117
|
|
|
@@ -123,6 +124,10 @@ module Doorkeeper
|
|
|
123
124
|
(code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
|
|
124
125
|
end
|
|
125
126
|
|
|
127
|
+
def response_on_fragment?
|
|
128
|
+
response_type == "token"
|
|
129
|
+
end
|
|
130
|
+
|
|
126
131
|
def pre_auth_hash
|
|
127
132
|
{
|
|
128
133
|
client_id: client.uid,
|
|
@@ -27,7 +27,7 @@ module Doorkeeper
|
|
|
27
27
|
private
|
|
28
28
|
|
|
29
29
|
def load_client(credentials)
|
|
30
|
-
|
|
30
|
+
server_config.application_model.by_uid_and_secret(credentials.uid, credentials.secret)
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
def before_successful_response
|
|
@@ -42,7 +42,7 @@ module Doorkeeper
|
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
def refresh_token_revoked_on_use?
|
|
45
|
-
|
|
45
|
+
server_config.access_token_model.refresh_token_revoked_on_use?
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def default_scopes
|
|
@@ -50,7 +50,7 @@ module Doorkeeper
|
|
|
50
50
|
end
|
|
51
51
|
|
|
52
52
|
def create_access_token
|
|
53
|
-
@access_token =
|
|
53
|
+
@access_token = server_config.access_token_model.create!(access_token_attributes)
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def access_token_attributes
|
|
@@ -71,7 +71,7 @@ module Doorkeeper
|
|
|
71
71
|
context = Authorization::Token.build_context(
|
|
72
72
|
client,
|
|
73
73
|
Doorkeeper::OAuth::REFRESH_TOKEN,
|
|
74
|
-
scopes
|
|
74
|
+
scopes,
|
|
75
75
|
)
|
|
76
76
|
Authorization::Token.access_token_expires_in(server, context)
|
|
77
77
|
end
|
|
@@ -104,7 +104,7 @@ module Doorkeeper
|
|
|
104
104
|
if @original_scopes.present?
|
|
105
105
|
ScopeChecker.valid?(
|
|
106
106
|
scope_str: @original_scopes,
|
|
107
|
-
server_scopes: refresh_token.scopes
|
|
107
|
+
server_scopes: refresh_token.scopes,
|
|
108
108
|
)
|
|
109
109
|
else
|
|
110
110
|
true
|
|
@@ -14,8 +14,8 @@ module Doorkeeper
|
|
|
14
14
|
|
|
15
15
|
def authenticate(request, *methods)
|
|
16
16
|
if (token = from_request(request, *methods))
|
|
17
|
-
access_token =
|
|
18
|
-
refresh_token_enabled = Doorkeeper.
|
|
17
|
+
access_token = Doorkeeper.config.access_token_model.by_token(token)
|
|
18
|
+
refresh_token_enabled = Doorkeeper.config.refresh_token_enabled?
|
|
19
19
|
if access_token.present? && refresh_token_enabled
|
|
20
20
|
access_token.revoke_previous_refresh_token!
|
|
21
21
|
end
|
|
@@ -94,7 +94,7 @@ module Doorkeeper
|
|
|
94
94
|
client_id: @token.try(:application).try(:uid),
|
|
95
95
|
token_type: @token.token_type,
|
|
96
96
|
exp: @token.expires_at.to_i,
|
|
97
|
-
iat: @token.created_at.to_i
|
|
97
|
+
iat: @token.created_at.to_i,
|
|
98
98
|
)
|
|
99
99
|
end
|
|
100
100
|
|
|
@@ -174,15 +174,15 @@ module Doorkeeper
|
|
|
174
174
|
authorized_token.token == @token&.token
|
|
175
175
|
end
|
|
176
176
|
|
|
177
|
-
#
|
|
177
|
+
# Config constraints for introspection in Doorkeeper.config.allow_token_introspection
|
|
178
178
|
def token_introspection_allowed?(auth_client: nil, auth_token: nil)
|
|
179
|
-
allow_introspection = Doorkeeper.
|
|
179
|
+
allow_introspection = Doorkeeper.config.allow_token_introspection
|
|
180
180
|
return allow_introspection unless allow_introspection.respond_to?(:call)
|
|
181
181
|
|
|
182
182
|
allow_introspection.call(
|
|
183
183
|
@token,
|
|
184
184
|
auth_client,
|
|
185
|
-
auth_token
|
|
185
|
+
auth_token,
|
|
186
186
|
)
|
|
187
187
|
end
|
|
188
188
|
|
|
@@ -193,9 +193,9 @@ module Doorkeeper
|
|
|
193
193
|
# @see https://tools.ietf.org/html/rfc7662#section-2.2
|
|
194
194
|
#
|
|
195
195
|
def customize_response(response)
|
|
196
|
-
customized_response = Doorkeeper.
|
|
196
|
+
customized_response = Doorkeeper.config.custom_introspection_response.call(
|
|
197
197
|
token,
|
|
198
|
-
server.context
|
|
198
|
+
server.context,
|
|
199
199
|
)
|
|
200
200
|
return response if customized_response.blank?
|
|
201
201
|
|
|
@@ -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: { case_sensitive: 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: { case_sensitive: true }
|
|
13
|
-
validates :refresh_token, uniqueness: { case_sensitive: 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,94 +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: { case_sensitive: true }
|
|
14
|
-
validates :redirect_uri, "doorkeeper/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
|
|
37
|
-
|
|
38
|
-
# Revokes AccessToken and AccessGrant records that have not been revoked and
|
|
39
|
-
# associated with the specific Application and Resource Owner.
|
|
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
|
|
3
|
+
require "doorkeeper/orm/active_record/redirect_uri_validator"
|
|
4
|
+
require "doorkeeper/orm/active_record/mixins/application"
|
|
48
5
|
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
def to_json(options)
|
|
64
|
-
serializable_hash(except: :secret)
|
|
65
|
-
.merge(secret: plaintext_secret)
|
|
66
|
-
.to_json(options)
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
private
|
|
70
|
-
|
|
71
|
-
def generate_uid
|
|
72
|
-
self.uid = UniqueToken.generate if uid.blank?
|
|
73
|
-
end
|
|
74
|
-
|
|
75
|
-
def generate_secret
|
|
76
|
-
return unless secret.blank?
|
|
77
|
-
|
|
78
|
-
@raw_secret = UniqueToken.generate
|
|
79
|
-
secret_strategy.store_secret(self, :secret, @raw_secret)
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
def scopes_match_configured
|
|
83
|
-
if scopes.present? &&
|
|
84
|
-
!ScopeChecker.valid?(scope_str: scopes.to_s,
|
|
85
|
-
server_scopes: Doorkeeper.configuration.scopes)
|
|
86
|
-
errors.add(:scopes, :not_match_configured)
|
|
87
|
-
end
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
def enforce_scopes?
|
|
91
|
-
Doorkeeper.configuration.enforce_configured_scopes?
|
|
92
|
-
end
|
|
6
|
+
module Doorkeeper
|
|
7
|
+
class Application < ::ActiveRecord::Base
|
|
8
|
+
include ::Doorkeeper::Orm::ActiveRecord::Mixins::Application
|
|
93
9
|
end
|
|
94
10
|
end
|
|
@@ -0,0 +1,53 @@
|
|
|
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 = "#{table_name_prefix}oauth_access_grants#{table_name_suffix}"
|
|
9
|
+
|
|
10
|
+
include ::Doorkeeper::AccessGrantMixin
|
|
11
|
+
|
|
12
|
+
belongs_to :application, class_name: Doorkeeper.config.application_class,
|
|
13
|
+
optional: true,
|
|
14
|
+
inverse_of: :access_grants
|
|
15
|
+
|
|
16
|
+
validates :resource_owner_id,
|
|
17
|
+
:application_id,
|
|
18
|
+
:token,
|
|
19
|
+
:expires_in,
|
|
20
|
+
:redirect_uri,
|
|
21
|
+
presence: true
|
|
22
|
+
|
|
23
|
+
validates :token, uniqueness: { case_sensitive: true }
|
|
24
|
+
|
|
25
|
+
before_validation :generate_token, on: :create
|
|
26
|
+
|
|
27
|
+
# We keep a volatile copy of the raw token for initial communication
|
|
28
|
+
# The stored refresh_token may be mapped and not available in cleartext.
|
|
29
|
+
#
|
|
30
|
+
# Some strategies allow restoring stored secrets (e.g. symmetric encryption)
|
|
31
|
+
# while hashing strategies do not, so you cannot rely on this value
|
|
32
|
+
# returning a present value for persisted tokens.
|
|
33
|
+
def plaintext_token
|
|
34
|
+
if secret_strategy.allows_restoring_secrets?
|
|
35
|
+
secret_strategy.restore_secret(self, :token)
|
|
36
|
+
else
|
|
37
|
+
@raw_token
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
# Generates token value with UniqueToken class.
|
|
44
|
+
#
|
|
45
|
+
# @return [String] token value
|
|
46
|
+
#
|
|
47
|
+
def generate_token
|
|
48
|
+
@raw_token = Doorkeeper::OAuth::Helpers::UniqueToken.generate
|
|
49
|
+
secret_strategy.store_secret(self, :token, @raw_token)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
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 = "#{table_name_prefix}oauth_access_tokens#{table_name_suffix}"
|
|
9
|
+
|
|
10
|
+
include ::Doorkeeper::AccessTokenMixin
|
|
11
|
+
|
|
12
|
+
belongs_to :application, class_name: Doorkeeper.config.application_class,
|
|
13
|
+
inverse_of: :access_tokens,
|
|
14
|
+
optional: true
|
|
15
|
+
|
|
16
|
+
validates :token, presence: true, uniqueness: { case_sensitive: true }
|
|
17
|
+
validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
|
|
18
|
+
|
|
19
|
+
# @attr_writer [Boolean, nil] use_refresh_token
|
|
20
|
+
# indicates the possibility of using refresh token
|
|
21
|
+
attr_writer :use_refresh_token
|
|
22
|
+
|
|
23
|
+
before_validation :generate_token, on: :create
|
|
24
|
+
before_validation :generate_refresh_token,
|
|
25
|
+
on: :create, if: :use_refresh_token?
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class_methods do
|
|
29
|
+
# Searches for not revoked Access Tokens associated with the
|
|
30
|
+
# specific Resource Owner.
|
|
31
|
+
#
|
|
32
|
+
# @param resource_owner [ActiveRecord::Base]
|
|
33
|
+
# Resource Owner model instance
|
|
34
|
+
#
|
|
35
|
+
# @return [ActiveRecord::Relation]
|
|
36
|
+
# active Access Tokens for Resource Owner
|
|
37
|
+
#
|
|
38
|
+
def active_for(resource_owner)
|
|
39
|
+
where(resource_owner_id: resource_owner.id, revoked_at: nil)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def refresh_token_revoked_on_use?
|
|
43
|
+
column_names.include?("previous_refresh_token")
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
4
|
+
module Application
|
|
5
|
+
extend ActiveSupport::Concern
|
|
6
|
+
|
|
7
|
+
included do
|
|
8
|
+
self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}"
|
|
9
|
+
|
|
10
|
+
include ::Doorkeeper::ApplicationMixin
|
|
11
|
+
|
|
12
|
+
has_many :access_grants,
|
|
13
|
+
foreign_key: :application_id,
|
|
14
|
+
dependent: :delete_all,
|
|
15
|
+
class_name: Doorkeeper.config.access_grant_class
|
|
16
|
+
|
|
17
|
+
has_many :access_tokens,
|
|
18
|
+
foreign_key: :application_id,
|
|
19
|
+
dependent: :delete_all,
|
|
20
|
+
class_name: Doorkeeper.config.access_token_class
|
|
21
|
+
|
|
22
|
+
validates :name, :secret, :uid, presence: true
|
|
23
|
+
validates :uid, uniqueness: { case_sensitive: true }
|
|
24
|
+
validates :redirect_uri, "doorkeeper/redirect_uri": true
|
|
25
|
+
validates :confidential, inclusion: { in: [true, false] }
|
|
26
|
+
|
|
27
|
+
validate :scopes_match_configured, if: :enforce_scopes?
|
|
28
|
+
|
|
29
|
+
before_validation :generate_uid, :generate_secret, on: :create
|
|
30
|
+
|
|
31
|
+
has_many :authorized_tokens,
|
|
32
|
+
-> { where(revoked_at: nil) },
|
|
33
|
+
foreign_key: :application_id,
|
|
34
|
+
class_name: Doorkeeper.config.access_token_class
|
|
35
|
+
|
|
36
|
+
has_many :authorized_applications,
|
|
37
|
+
through: :authorized_tokens,
|
|
38
|
+
source: :application
|
|
39
|
+
|
|
40
|
+
# Generates a new secret for this application, intended to be used
|
|
41
|
+
# for rotating the secret or in case of compromise.
|
|
42
|
+
#
|
|
43
|
+
# @return [String] new transformed secret value
|
|
44
|
+
#
|
|
45
|
+
def renew_secret
|
|
46
|
+
@raw_secret = Doorkeeper::OAuth::Helpers::UniqueToken.generate
|
|
47
|
+
secret_strategy.store_secret(self, :secret, @raw_secret)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# We keep a volatile copy of the raw secret for initial communication
|
|
51
|
+
# The stored refresh_token may be mapped and not available in cleartext.
|
|
52
|
+
#
|
|
53
|
+
# Some strategies allow restoring stored secrets (e.g. symmetric encryption)
|
|
54
|
+
# while hashing strategies do not, so you cannot rely on this value
|
|
55
|
+
# returning a present value for persisted tokens.
|
|
56
|
+
def plaintext_secret
|
|
57
|
+
if secret_strategy.allows_restoring_secrets?
|
|
58
|
+
secret_strategy.restore_secret(self, :secret)
|
|
59
|
+
else
|
|
60
|
+
@raw_secret
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# This is the right way how we want to override ActiveRecord #to_json
|
|
65
|
+
#
|
|
66
|
+
# @return [String] entity attributes as JSON
|
|
67
|
+
#
|
|
68
|
+
def as_json(options = {})
|
|
69
|
+
hash = super
|
|
70
|
+
|
|
71
|
+
hash["secret"] = plaintext_secret if hash.key?("secret")
|
|
72
|
+
hash
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def generate_uid
|
|
78
|
+
self.uid = Doorkeeper::OAuth::Helpers::UniqueToken.generate if uid.blank?
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def generate_secret
|
|
82
|
+
return unless secret.blank?
|
|
83
|
+
|
|
84
|
+
renew_secret
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def scopes_match_configured
|
|
88
|
+
if scopes.present? && !Doorkeeper::OAuth::Helpers::ScopeChecker.valid?(
|
|
89
|
+
scope_str: scopes.to_s,
|
|
90
|
+
server_scopes: Doorkeeper.config.scopes,
|
|
91
|
+
)
|
|
92
|
+
errors.add(:scopes, :not_match_configured)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def enforce_scopes?
|
|
97
|
+
Doorkeeper.config.enforce_configured_scopes?
|
|
98
|
+
end
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
class_methods do
|
|
102
|
+
# Returns Applications associated with active (not revoked) Access Tokens
|
|
103
|
+
# that are owned by the specific Resource Owner.
|
|
104
|
+
#
|
|
105
|
+
# @param resource_owner [ActiveRecord::Base]
|
|
106
|
+
# Resource Owner model instance
|
|
107
|
+
#
|
|
108
|
+
# @return [ActiveRecord::Relation]
|
|
109
|
+
# Applications authorized for the Resource Owner
|
|
110
|
+
#
|
|
111
|
+
def authorized_for(resource_owner)
|
|
112
|
+
resource_access_tokens = Doorkeeper.config.access_token_model.active_for(resource_owner)
|
|
113
|
+
where(id: resource_access_tokens.select(:application_id).distinct)
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Revokes AccessToken and AccessGrant records that have not been revoked and
|
|
117
|
+
# associated with the specific Application and Resource Owner.
|
|
118
|
+
#
|
|
119
|
+
# @param resource_owner [ActiveRecord::Base]
|
|
120
|
+
# instance of the Resource Owner model
|
|
121
|
+
#
|
|
122
|
+
def revoke_tokens_and_grants_for(id, resource_owner)
|
|
123
|
+
Doorkeeper.config.access_token_model.revoke_all_for(id, resource_owner)
|
|
124
|
+
Doorkeeper.config.access_grant_model.revoke_all_for(id, resource_owner)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -8,7 +8,7 @@ module Doorkeeper
|
|
|
8
8
|
class RedirectUriValidator < ActiveModel::EachValidator
|
|
9
9
|
def validate_each(record, attribute, value)
|
|
10
10
|
if value.blank?
|
|
11
|
-
return if Doorkeeper.
|
|
11
|
+
return if Doorkeeper.config.allow_blank_redirect_uri?(record)
|
|
12
12
|
|
|
13
13
|
record.errors.add(attribute, :blank)
|
|
14
14
|
else
|
|
@@ -34,7 +34,7 @@ module Doorkeeper
|
|
|
34
34
|
end
|
|
35
35
|
|
|
36
36
|
def forbidden_uri?(uri)
|
|
37
|
-
Doorkeeper.
|
|
37
|
+
Doorkeeper.config.forbid_redirect_uri.call(uri)
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def unspecified_scheme?(uri)
|
|
@@ -48,7 +48,7 @@ module Doorkeeper
|
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
def invalid_ssl_uri?(uri)
|
|
51
|
-
forces_ssl = Doorkeeper.
|
|
51
|
+
forces_ssl = Doorkeeper.config.force_ssl_in_redirect_uri
|
|
52
52
|
non_https = uri.try(:scheme) == "http"
|
|
53
53
|
|
|
54
54
|
if forces_ssl.respond_to?(:call)
|