doorkeeper 5.4.0.rc2 → 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/CHANGELOG.md +90 -10
- data/README.md +4 -4
- data/app/controllers/doorkeeper/application_controller.rb +1 -0
- data/app/controllers/doorkeeper/authorizations_controller.rb +16 -5
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +34 -26
- data/app/views/doorkeeper/applications/show.html.erb +16 -12
- data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
- data/config/locales/en.yml +3 -1
- data/lib/doorkeeper.rb +5 -0
- data/lib/doorkeeper/config.rb +91 -62
- data/lib/doorkeeper/config/option.rb +1 -3
- data/lib/doorkeeper/config/validations.rb +53 -0
- data/lib/doorkeeper/engine.rb +1 -1
- data/lib/doorkeeper/grant_flow.rb +45 -0
- 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/helpers/controller.rb +4 -0
- data/lib/doorkeeper/models/access_grant_mixin.rb +1 -2
- data/lib/doorkeeper/models/access_token_mixin.rb +4 -4
- data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +5 -1
- data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
- data/lib/doorkeeper/oauth/authorization/token.rb +11 -5
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +10 -17
- data/lib/doorkeeper/oauth/base_request.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +1 -0
- data/lib/doorkeeper/oauth/code_request.rb +2 -2
- data/lib/doorkeeper/oauth/code_response.rb +17 -11
- data/lib/doorkeeper/oauth/error_response.rb +4 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -3
- data/lib/doorkeeper/oauth/password_access_token_request.rb +23 -3
- data/lib/doorkeeper/oauth/pre_authorization.rb +33 -8
- data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -0
- data/lib/doorkeeper/oauth/token.rb +3 -3
- data/lib/doorkeeper/oauth/token_introspection.rb +1 -5
- data/lib/doorkeeper/oauth/token_request.rb +1 -1
- data/lib/doorkeeper/orm/active_record.rb +5 -14
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +11 -1
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +9 -1
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +26 -15
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +5 -0
- data/lib/doorkeeper/rails/routes.rb +1 -3
- data/lib/doorkeeper/rake/db.rake +3 -3
- data/lib/doorkeeper/rake/setup.rake +5 -0
- data/lib/doorkeeper/request.rb +49 -12
- data/lib/doorkeeper/request/password.rb +1 -0
- data/lib/doorkeeper/server.rb +1 -1
- data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
- data/lib/doorkeeper/version.rb +3 -7
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +1 -1
- data/lib/generators/doorkeeper/templates/initializer.rb +9 -7
- metadata +26 -13
@@ -62,6 +62,19 @@ module Doorkeeper
|
|
62
62
|
attributes[:previous_refresh_token] = refresh_token.refresh_token
|
63
63
|
end
|
64
64
|
|
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
|
+
#
|
65
78
|
@access_token = server_config.access_token_model.create_for(
|
66
79
|
application: refresh_token.application,
|
67
80
|
resource_owner: resource_owner,
|
@@ -32,13 +32,13 @@ module Doorkeeper
|
|
32
32
|
|
33
33
|
def from_bearer_authorization(request)
|
34
34
|
pattern = /^Bearer /i
|
35
|
-
header
|
35
|
+
header = request.authorization
|
36
36
|
token_from_header(header, pattern) if match?(header, pattern)
|
37
37
|
end
|
38
38
|
|
39
39
|
def from_basic_authorization(request)
|
40
40
|
pattern = /^Basic /i
|
41
|
-
header
|
41
|
+
header = request.authorization
|
42
42
|
token_from_basic_header(header, pattern) if match?(header, pattern)
|
43
43
|
end
|
44
44
|
|
@@ -54,7 +54,7 @@ module Doorkeeper
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def token_from_header(header, pattern)
|
57
|
-
header.gsub
|
57
|
+
header.gsub(pattern, "")
|
58
58
|
end
|
59
59
|
|
60
60
|
def match?(header, pattern)
|
@@ -179,11 +179,7 @@ module Doorkeeper
|
|
179
179
|
allow_introspection = Doorkeeper.config.allow_token_introspection
|
180
180
|
return allow_introspection unless allow_introspection.respond_to?(:call)
|
181
181
|
|
182
|
-
allow_introspection.call(
|
183
|
-
@token,
|
184
|
-
auth_client,
|
185
|
-
auth_token,
|
186
|
-
)
|
182
|
+
allow_introspection.call(@token, auth_client, auth_token)
|
187
183
|
end
|
188
184
|
|
189
185
|
# Allows to customize introspection response.
|
@@ -20,9 +20,8 @@ module Doorkeeper
|
|
20
20
|
require "doorkeeper/orm/active_record/access_token"
|
21
21
|
require "doorkeeper/orm/active_record/application"
|
22
22
|
|
23
|
-
if Doorkeeper.config.active_record_options[:establish_connection]
|
23
|
+
if (options = Doorkeeper.config.active_record_options[:establish_connection])
|
24
24
|
Doorkeeper::Orm::ActiveRecord.models.each do |model|
|
25
|
-
options = Doorkeeper.config.active_record_options[:establish_connection]
|
26
25
|
model.establish_connection(options)
|
27
26
|
end
|
28
27
|
end
|
@@ -38,22 +37,14 @@ module Doorkeeper
|
|
38
37
|
end
|
39
38
|
|
40
39
|
def self.lazy_load(&block)
|
41
|
-
|
42
|
-
# already lazy-loaded :(
|
43
|
-
loaded = ActiveSupport.instance_variable_get(:"@loaded") || {}
|
44
|
-
|
45
|
-
if loaded.key?(:active_record)
|
46
|
-
block.call
|
47
|
-
else
|
48
|
-
ActiveSupport.on_load(:active_record, {}, &block)
|
49
|
-
end
|
40
|
+
ActiveSupport.on_load(:active_record, {}, &block)
|
50
41
|
end
|
51
42
|
|
52
43
|
def self.models
|
53
44
|
[
|
54
|
-
Doorkeeper
|
55
|
-
Doorkeeper
|
56
|
-
Doorkeeper
|
45
|
+
Doorkeeper.config.access_grant_model,
|
46
|
+
Doorkeeper.config.access_token_model,
|
47
|
+
Doorkeeper.config.application_model,
|
57
48
|
]
|
58
49
|
end
|
59
50
|
end
|
@@ -5,7 +5,7 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
self.table_name =
|
8
|
+
self.table_name = compute_doorkeeper_table_name
|
9
9
|
|
10
10
|
include ::Doorkeeper::AccessGrantMixin
|
11
11
|
|
@@ -54,5 +54,15 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
54
54
|
secret_strategy.store_secret(self, :token, @raw_token)
|
55
55
|
end
|
56
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
|
57
67
|
end
|
58
68
|
end
|
@@ -5,7 +5,7 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
self.table_name =
|
8
|
+
self.table_name = compute_doorkeeper_table_name
|
9
9
|
|
10
10
|
include ::Doorkeeper::AccessTokenMixin
|
11
11
|
|
@@ -46,6 +46,14 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
46
46
|
def refresh_token_revoked_on_use?
|
47
47
|
column_names.include?("previous_refresh_token")
|
48
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
|
49
57
|
end
|
50
58
|
end
|
51
59
|
end
|
@@ -5,7 +5,7 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
self.table_name =
|
8
|
+
self.table_name = compute_doorkeeper_table_name
|
9
9
|
|
10
10
|
include ::Doorkeeper::ApplicationMixin
|
11
11
|
|
@@ -88,6 +88,17 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
88
88
|
Doorkeeper.configuration.authorize_resource_owner_for_client.call(self, resource_owner)
|
89
89
|
end
|
90
90
|
|
91
|
+
# We need to hook into this method to allow serializing plan-text secrets
|
92
|
+
# when secrets hashing enabled.
|
93
|
+
#
|
94
|
+
# @param key [String] attribute name
|
95
|
+
#
|
96
|
+
def read_attribute_for_serialization(key)
|
97
|
+
return super unless key.to_s == "secret"
|
98
|
+
|
99
|
+
plaintext_secret || secret
|
100
|
+
end
|
101
|
+
|
91
102
|
private
|
92
103
|
|
93
104
|
def generate_uid
|
@@ -126,31 +137,23 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
126
137
|
only = Array.wrap(opts[:only]).map(&:to_s)
|
127
138
|
|
128
139
|
only = if only.blank?
|
129
|
-
|
140
|
+
client_serializable_attributes
|
130
141
|
else
|
131
|
-
only &
|
142
|
+
only & client_serializable_attributes
|
132
143
|
end
|
133
144
|
|
134
145
|
only -= Array.wrap(opts[:except]).map(&:to_s) if opts.key?(:except)
|
135
146
|
only.uniq
|
136
147
|
end
|
137
148
|
|
138
|
-
# We need to hook into this method to allow serializing plan-text secrets
|
139
|
-
# when secrets hashing enabled.
|
140
|
-
#
|
141
|
-
# @param key [String] attribute name
|
142
|
-
#
|
143
|
-
def read_attribute_for_serialization(key)
|
144
|
-
return super unless key.to_s == "secret"
|
145
|
-
|
146
|
-
plaintext_secret || secret
|
147
|
-
end
|
148
|
-
|
149
149
|
# Collection of attributes that could be serialized for public.
|
150
150
|
# Override this method if you need additional attributes to be serialized.
|
151
151
|
#
|
152
152
|
# @return [Array<String>] collection of serializable attributes
|
153
|
-
|
153
|
+
#
|
154
|
+
# NOTE: `serializable_attributes` method already taken by Rails >= 6
|
155
|
+
#
|
156
|
+
def client_serializable_attributes
|
154
157
|
attributes = %w[id name created_at]
|
155
158
|
attributes << "uid" unless confidential?
|
156
159
|
attributes
|
@@ -182,6 +185,14 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
182
185
|
Doorkeeper.config.access_token_model.revoke_all_for(id, resource_owner)
|
183
186
|
Doorkeeper.config.access_grant_model.revoke_all_for(id, resource_owner)
|
184
187
|
end
|
188
|
+
|
189
|
+
private
|
190
|
+
|
191
|
+
def compute_doorkeeper_table_name
|
192
|
+
table_name = "oauth_application"
|
193
|
+
table_name = table_name.pluralize if pluralize_table_names
|
194
|
+
"#{table_name_prefix}#{table_name}#{table_name_suffix}"
|
195
|
+
end
|
185
196
|
end
|
186
197
|
end
|
187
198
|
end
|
@@ -21,6 +21,7 @@ module Doorkeeper
|
|
21
21
|
record.errors.add(attribute, :unspecified_scheme) if unspecified_scheme?(uri)
|
22
22
|
record.errors.add(attribute, :relative_uri) if relative_uri?(uri)
|
23
23
|
record.errors.add(attribute, :secured_uri) if invalid_ssl_uri?(uri)
|
24
|
+
record.errors.add(attribute, :invalid_uri) if unspecified_host?(uri)
|
24
25
|
end
|
25
26
|
end
|
26
27
|
rescue URI::InvalidURIError
|
@@ -43,6 +44,10 @@ module Doorkeeper
|
|
43
44
|
%w[localhost].include?(uri.try(:scheme))
|
44
45
|
end
|
45
46
|
|
47
|
+
def unspecified_host?(uri)
|
48
|
+
uri.is_a?(URI::HTTP) && uri.host.nil?
|
49
|
+
end
|
50
|
+
|
46
51
|
def relative_uri?(uri)
|
47
52
|
uri.scheme.nil? && uri.host.nil?
|
48
53
|
end
|
@@ -29,8 +29,6 @@ module Doorkeeper
|
|
29
29
|
|
30
30
|
def initialize(routes, mapper = Mapper.new, &block)
|
31
31
|
super
|
32
|
-
|
33
|
-
@mapping.skips.push(:applications, :authorized_applications) if Doorkeeper.config.api_only
|
34
32
|
end
|
35
33
|
|
36
34
|
def generate_routes!(options)
|
@@ -38,7 +36,7 @@ module Doorkeeper
|
|
38
36
|
map_route(:authorizations, :authorization_routes)
|
39
37
|
map_route(:tokens, :token_routes)
|
40
38
|
map_route(:tokens, :revoke_routes)
|
41
|
-
map_route(:tokens, :introspect_routes)
|
39
|
+
map_route(:tokens, :introspect_routes) unless Doorkeeper.config.allow_token_introspection.is_a?(FalseClass)
|
42
40
|
map_route(:applications, :application_routes)
|
43
41
|
map_route(:authorized_applications, :authorized_applications_routes)
|
44
42
|
map_route(:token_info, :token_info_routes)
|
data/lib/doorkeeper/rake/db.rake
CHANGED
@@ -13,7 +13,7 @@ namespace :doorkeeper do
|
|
13
13
|
namespace :cleanup do
|
14
14
|
desc "Removes stale access tokens"
|
15
15
|
task revoked_tokens: "doorkeeper:setup" do
|
16
|
-
cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper
|
16
|
+
cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper.config.access_token_model)
|
17
17
|
cleaner.clean_revoked
|
18
18
|
end
|
19
19
|
|
@@ -26,13 +26,13 @@ namespace :doorkeeper do
|
|
26
26
|
|
27
27
|
desc "Removes stale access grants"
|
28
28
|
task revoked_grants: "doorkeeper:setup" do
|
29
|
-
cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper
|
29
|
+
cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper.config.access_grant_model)
|
30
30
|
cleaner.clean_revoked
|
31
31
|
end
|
32
32
|
|
33
33
|
desc "Removes expired (TTL passed) access grants"
|
34
34
|
task expired_grants: "doorkeeper:setup" do
|
35
|
-
cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper
|
35
|
+
cleaner = Doorkeeper::StaleRecordsCleaner.new(Doorkeeper.config.access_grant_model)
|
36
36
|
cleaner.clean_expired(Doorkeeper.config.authorization_code_expires_in)
|
37
37
|
end
|
38
38
|
end
|
@@ -2,5 +2,10 @@
|
|
2
2
|
|
3
3
|
namespace :doorkeeper do
|
4
4
|
task setup: :environment do
|
5
|
+
# Dirty hack to manually initialize AR because of lazy auto-loading,
|
6
|
+
# in other case we'll see NameError: uninitialized constant Doorkeeper::AccessToken
|
7
|
+
if Doorkeeper.config.orm == :active_record && defined?(::ActiveRecord::Base)
|
8
|
+
Object.const_get("::ActiveRecord::Base")
|
9
|
+
end
|
5
10
|
end
|
6
11
|
end
|
data/lib/doorkeeper/request.rb
CHANGED
@@ -4,32 +4,69 @@ module Doorkeeper
|
|
4
4
|
module Request
|
5
5
|
class << self
|
6
6
|
def authorization_strategy(response_type)
|
7
|
-
|
7
|
+
grant_flow = authorization_flows.detect do |flow|
|
8
|
+
flow.matches_response_type?(response_type)
|
9
|
+
end
|
10
|
+
|
11
|
+
if grant_flow
|
12
|
+
grant_flow.response_type_strategy
|
13
|
+
else
|
14
|
+
# [NOTE]: this will be removed in a newer versions of Doorkeeper.
|
15
|
+
# For retro-compatibility only
|
16
|
+
build_fallback_strategy_class(response_type)
|
17
|
+
end
|
8
18
|
end
|
9
19
|
|
10
20
|
def token_strategy(grant_type)
|
11
21
|
raise Errors::MissingRequiredParameter, :grant_type if grant_type.blank?
|
12
22
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
23
|
+
grant_flow = token_flows.detect do |flow|
|
24
|
+
flow.matches_grant_type?(grant_type)
|
25
|
+
end
|
17
26
|
|
18
|
-
|
19
|
-
|
27
|
+
if grant_flow
|
28
|
+
grant_flow.grant_type_strategy
|
29
|
+
else
|
30
|
+
# [NOTE]: this will be removed in a newer versions of Doorkeeper.
|
31
|
+
# For retro-compatibility only
|
32
|
+
raise Errors::InvalidTokenStrategy unless available.include?(grant_type.to_s)
|
20
33
|
|
21
|
-
|
34
|
+
strategy_class = build_fallback_strategy_class(grant_type)
|
35
|
+
raise Errors::InvalidTokenStrategy unless strategy_class
|
36
|
+
|
37
|
+
strategy_class
|
38
|
+
end
|
22
39
|
end
|
23
40
|
|
24
41
|
private
|
25
42
|
|
26
|
-
def
|
27
|
-
Doorkeeper.
|
43
|
+
def authorization_flows
|
44
|
+
Doorkeeper.configuration.authorization_response_flows
|
45
|
+
end
|
46
|
+
|
47
|
+
def token_flows
|
48
|
+
Doorkeeper.configuration.token_grant_flows
|
28
49
|
end
|
29
50
|
|
30
|
-
|
51
|
+
# [NOTE]: this will be removed in a newer versions of Doorkeeper.
|
52
|
+
# For retro-compatibility only
|
53
|
+
def available
|
54
|
+
Doorkeeper.config.deprecated_token_grant_types_resolver
|
55
|
+
end
|
56
|
+
|
57
|
+
def build_fallback_strategy_class(grant_or_request_type)
|
31
58
|
strategy_class_name = grant_or_request_type.to_s.tr(" ", "_").camelize
|
32
|
-
"Doorkeeper::Request::#{strategy_class_name}".constantize
|
59
|
+
fallback_strategy = "Doorkeeper::Request::#{strategy_class_name}".constantize
|
60
|
+
|
61
|
+
::Kernel.warn <<~WARNING
|
62
|
+
[DOORKEEPER] #{fallback_strategy} found using fallback, it must be
|
63
|
+
registered using `Doorkeeper::GrantFlow.register(grant_flow_name, **options)`.
|
64
|
+
This functionality will be removed in a newer versions of Doorkeeper.
|
65
|
+
WARNING
|
66
|
+
|
67
|
+
fallback_strategy
|
68
|
+
rescue NameError
|
69
|
+
raise Errors::InvalidTokenStrategy
|
33
70
|
end
|
34
71
|
end
|
35
72
|
end
|
data/lib/doorkeeper/server.rb
CHANGED
@@ -13,12 +13,12 @@ module Doorkeeper
|
|
13
13
|
raise Doorkeeper::Errors::NoOrmCleaner, "'#{configured_orm}' ORM has no cleaner!"
|
14
14
|
end
|
15
15
|
|
16
|
-
def self.configured_orm
|
17
|
-
Doorkeeper.config.orm
|
18
|
-
end
|
19
|
-
|
20
16
|
def self.new(base_scope)
|
21
17
|
self.for(base_scope)
|
22
18
|
end
|
19
|
+
|
20
|
+
def self.configured_orm
|
21
|
+
Doorkeeper.config.orm
|
22
|
+
end
|
23
23
|
end
|
24
24
|
end
|
data/lib/doorkeeper/version.rb
CHANGED
@@ -1,16 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Doorkeeper
|
4
|
-
def self.gem_version
|
5
|
-
Gem::Version.new VERSION::STRING
|
6
|
-
end
|
7
|
-
|
8
4
|
module VERSION
|
9
5
|
# Semantic versioning
|
10
6
|
MAJOR = 5
|
11
|
-
MINOR =
|
12
|
-
TINY =
|
13
|
-
PRE =
|
7
|
+
MINOR = 5
|
8
|
+
TINY = 1
|
9
|
+
PRE = nil
|
14
10
|
|
15
11
|
# Full version number
|
16
12
|
STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
|