doorkeeper 5.5.4 → 5.8.1
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/CHANGELOG.md +111 -8
- data/README.md +5 -9
- data/app/controllers/doorkeeper/authorizations_controller.rb +34 -11
- data/app/controllers/doorkeeper/tokens_controller.rb +28 -6
- data/app/views/doorkeeper/authorizations/error.html.erb +3 -1
- data/app/views/doorkeeper/authorizations/form_post.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +16 -16
- data/config/locales/en.yml +4 -1
- data/lib/doorkeeper/config/abstract_builder.rb +1 -1
- data/lib/doorkeeper/config/validations.rb +15 -3
- data/lib/doorkeeper/config.rb +95 -55
- data/lib/doorkeeper/engine.rb +10 -3
- data/lib/doorkeeper/errors.rb +32 -0
- data/lib/doorkeeper/helpers/controller.rb +1 -1
- data/lib/doorkeeper/models/access_token_mixin.rb +71 -9
- data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
- data/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +30 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +7 -1
- data/lib/doorkeeper/oauth/authorization/token.rb +7 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +36 -12
- data/lib/doorkeeper/oauth/base_request.rb +14 -12
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +13 -13
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +5 -4
- data/lib/doorkeeper/oauth/client_credentials/validator.rb +4 -5
- data/lib/doorkeeper/oauth/client_credentials_request.rb +10 -2
- data/lib/doorkeeper/oauth/code_request.rb +1 -1
- data/lib/doorkeeper/oauth/error.rb +4 -3
- data/lib/doorkeeper/oauth/error_response.rb +19 -4
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +4 -4
- data/lib/doorkeeper/oauth/invalid_request_response.rb +4 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +6 -6
- data/lib/doorkeeper/oauth/pre_authorization.rb +31 -23
- data/lib/doorkeeper/oauth/refresh_token_request.rb +17 -9
- data/lib/doorkeeper/oauth/scopes.rb +55 -1
- data/lib/doorkeeper/oauth/token_introspection.rb +34 -20
- data/lib/doorkeeper/oauth/token_request.rb +1 -1
- data/lib/doorkeeper/oauth/token_response.rb +5 -3
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +0 -6
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +21 -4
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +22 -4
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +2 -2
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +5 -2
- data/lib/doorkeeper/orm/active_record.rb +30 -37
- data/lib/doorkeeper/rails/routes.rb +12 -3
- data/lib/doorkeeper/rake/setup.rake +0 -5
- data/lib/doorkeeper/revocable_tokens/revocable_access_token.rb +21 -0
- data/lib/doorkeeper/revocable_tokens/revocable_refresh_token.rb +21 -0
- data/lib/doorkeeper/version.rb +2 -2
- data/lib/doorkeeper.rb +78 -5
- data/lib/generators/doorkeeper/remove_applications_secret_not_null_constraint_generator.rb +33 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +44 -6
- data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -4
- data/lib/generators/doorkeeper/templates/remove_applications_secret_not_null_constraint.rb.erb +7 -0
- metadata +28 -21
@@ -6,6 +6,8 @@ module Doorkeeper
|
|
6
6
|
include Enumerable
|
7
7
|
include Comparable
|
8
8
|
|
9
|
+
DYNAMIC_SCOPE_WILDCARD = "*"
|
10
|
+
|
9
11
|
def self.from_string(string)
|
10
12
|
string ||= ""
|
11
13
|
new.tap do |scope|
|
@@ -26,7 +28,15 @@ module Doorkeeper
|
|
26
28
|
end
|
27
29
|
|
28
30
|
def exists?(scope)
|
29
|
-
|
31
|
+
scope = scope.to_s
|
32
|
+
|
33
|
+
@scopes.any? do |allowed_scope|
|
34
|
+
if dynamic_scopes_enabled? && dynamic_scopes_present?(allowed_scope, scope)
|
35
|
+
dynamic_scope_match?(allowed_scope, scope)
|
36
|
+
else
|
37
|
+
allowed_scope == scope
|
38
|
+
end
|
39
|
+
end
|
30
40
|
end
|
31
41
|
|
32
42
|
def add(*scopes)
|
@@ -60,12 +70,56 @@ module Doorkeeper
|
|
60
70
|
end
|
61
71
|
end
|
62
72
|
|
73
|
+
# DEPRECATED: With dynamic scopes, #allowed should be called because
|
74
|
+
# A & B doesn't really make sense with dynamic scopes.
|
75
|
+
#
|
76
|
+
# For example, if A = user:* and B is user:1, A & B = [].
|
77
|
+
# If we modified this method to take dynamic scopes into an account, then order
|
78
|
+
# becomes important, and this would violate the principle that A & B = B & A.
|
63
79
|
def &(other)
|
80
|
+
return allowed(other) if dynamic_scopes_enabled?
|
81
|
+
|
64
82
|
self.class.from_array(all & to_array(other))
|
65
83
|
end
|
66
84
|
|
85
|
+
# Returns a set of scopes that are allowed, taking dynamic
|
86
|
+
# scopes into account. This instance's scopes is taken as the allowed set,
|
87
|
+
# and the passed value is the set to filter.
|
88
|
+
#
|
89
|
+
# @param other The set of scopes to filter
|
90
|
+
def allowed(other)
|
91
|
+
filtered_scopes = other.select { |scope| self.exists?(scope) }
|
92
|
+
self.class.from_array(filtered_scopes)
|
93
|
+
end
|
94
|
+
|
67
95
|
private
|
68
96
|
|
97
|
+
def dynamic_scopes_enabled?
|
98
|
+
Doorkeeper.config.enable_dynamic_scopes?
|
99
|
+
end
|
100
|
+
|
101
|
+
def dynamic_scope_delimiter
|
102
|
+
return unless dynamic_scopes_enabled?
|
103
|
+
|
104
|
+
@dynamic_scope_delimiter ||= Doorkeeper.config.dynamic_scopes_delimiter
|
105
|
+
end
|
106
|
+
|
107
|
+
def dynamic_scopes_present?(allowed, requested)
|
108
|
+
allowed.include?(dynamic_scope_delimiter) && requested.include?(dynamic_scope_delimiter)
|
109
|
+
end
|
110
|
+
|
111
|
+
def dynamic_scope_match?(allowed, requested)
|
112
|
+
allowed_pattern = allowed.split(dynamic_scope_delimiter, 2)
|
113
|
+
request_pattern = requested.split(dynamic_scope_delimiter, 2)
|
114
|
+
|
115
|
+
return false if allowed_pattern[0] != request_pattern[0]
|
116
|
+
return false if allowed_pattern[1].blank?
|
117
|
+
return false if request_pattern[1].blank?
|
118
|
+
return true if allowed_pattern[1] == DYNAMIC_SCOPE_WILDCARD && allowed_pattern[1].present?
|
119
|
+
|
120
|
+
allowed_pattern[1] == request_pattern[1]
|
121
|
+
end
|
122
|
+
|
69
123
|
def to_array(other)
|
70
124
|
case other
|
71
125
|
when Scopes
|
@@ -6,26 +6,27 @@ module Doorkeeper
|
|
6
6
|
#
|
7
7
|
# @see https://datatracker.ietf.org/doc/html/rfc7662
|
8
8
|
class TokenIntrospection
|
9
|
+
attr_reader :token, :error, :invalid_request_reason
|
10
|
+
|
9
11
|
def initialize(server, token)
|
10
12
|
@server = server
|
11
13
|
@token = token
|
12
|
-
|
13
|
-
authorize!
|
14
14
|
end
|
15
15
|
|
16
16
|
def authorized?
|
17
|
+
authorize!
|
17
18
|
@error.blank?
|
18
19
|
end
|
19
20
|
|
20
21
|
def error_response
|
21
22
|
return if @error.blank?
|
22
23
|
|
23
|
-
if @error ==
|
24
|
+
if @error == Errors::InvalidToken
|
24
25
|
OAuth::InvalidTokenResponse.from_access_token(authorized_token)
|
25
|
-
elsif @error ==
|
26
|
+
elsif @error == Errors::InvalidRequest
|
26
27
|
OAuth::InvalidRequestResponse.from_request(self)
|
27
28
|
else
|
28
|
-
OAuth::ErrorResponse.
|
29
|
+
OAuth::ErrorResponse.from_request(self)
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
@@ -35,8 +36,7 @@ module Doorkeeper
|
|
35
36
|
|
36
37
|
private
|
37
38
|
|
38
|
-
attr_reader :server
|
39
|
-
attr_reader :error, :invalid_request_reason
|
39
|
+
attr_reader :server
|
40
40
|
|
41
41
|
# If the protected resource uses OAuth 2.0 client credentials to
|
42
42
|
# authenticate to the introspection endpoint and its credentials are
|
@@ -58,24 +58,38 @@ module Doorkeeper
|
|
58
58
|
def authorize!
|
59
59
|
# Requested client authorization
|
60
60
|
if server.credentials
|
61
|
-
|
61
|
+
authorize_using_basic_auth!
|
62
62
|
elsif authorized_token
|
63
|
-
|
64
|
-
#
|
65
|
-
# If the protected resource uses an OAuth 2.0 bearer token to authorize
|
66
|
-
# its call to the introspection endpoint and the token used for
|
67
|
-
# authorization does not contain sufficient privileges or is otherwise
|
68
|
-
# invalid for this request, the authorization server responds with an
|
69
|
-
# HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
|
70
|
-
# Usage [RFC6750].
|
71
|
-
#
|
72
|
-
@error = :invalid_token unless valid_authorized_token?
|
63
|
+
authorize_using_bearer_token!
|
73
64
|
else
|
74
|
-
@error =
|
65
|
+
@error = Errors::InvalidRequest
|
75
66
|
@invalid_request_reason = :request_not_authorized
|
76
67
|
end
|
77
68
|
end
|
78
69
|
|
70
|
+
def authorize_using_basic_auth!
|
71
|
+
# Note that a properly formed and authorized query for an inactive or
|
72
|
+
# otherwise invalid token (or a token the protected resource is not
|
73
|
+
# allowed to know about) is not considered an error response by this
|
74
|
+
# specification. In these cases, the authorization server MUST instead
|
75
|
+
# respond with an introspection response with the "active" field set to
|
76
|
+
# "false" as described in Section 2.2.
|
77
|
+
@error = Errors::InvalidClient unless authorized_client
|
78
|
+
end
|
79
|
+
|
80
|
+
def authorize_using_bearer_token!
|
81
|
+
# Requested bearer token authorization
|
82
|
+
#
|
83
|
+
# If the protected resource uses an OAuth 2.0 bearer token to authorize
|
84
|
+
# its call to the introspection endpoint and the token used for
|
85
|
+
# authorization does not contain sufficient privileges or is otherwise
|
86
|
+
# invalid for this request, the authorization server responds with an
|
87
|
+
# HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
|
88
|
+
# Usage [RFC6750].
|
89
|
+
#
|
90
|
+
@error = Errors::InvalidToken unless valid_authorized_token?
|
91
|
+
end
|
92
|
+
|
79
93
|
# Client Authentication
|
80
94
|
def authorized_client
|
81
95
|
@authorized_client ||= server.credentials && server.client
|
@@ -134,7 +148,7 @@ module Doorkeeper
|
|
134
148
|
# Since resource servers using token introspection rely on the
|
135
149
|
# authorization server to determine the state of a token, the
|
136
150
|
# authorization server MUST perform all applicable checks against a
|
137
|
-
# token's state.
|
151
|
+
# token's state. For instance, these tests include the following:
|
138
152
|
#
|
139
153
|
# o If the token can expire, the authorization server MUST determine
|
140
154
|
# whether or not the token has expired.
|
@@ -5,12 +5,14 @@ module Doorkeeper
|
|
5
5
|
class TokenResponse
|
6
6
|
attr_reader :token
|
7
7
|
|
8
|
+
alias issued_token token
|
9
|
+
|
8
10
|
def initialize(token)
|
9
11
|
@token = token
|
10
12
|
end
|
11
13
|
|
12
14
|
def body
|
13
|
-
{
|
15
|
+
@body ||= {
|
14
16
|
"access_token" => token.plaintext_token,
|
15
17
|
"token_type" => token.token_type,
|
16
18
|
"expires_in" => token.expires_in_seconds,
|
@@ -26,9 +28,9 @@ module Doorkeeper
|
|
26
28
|
|
27
29
|
def headers
|
28
30
|
{
|
29
|
-
"Cache-Control" => "no-store",
|
30
|
-
"Pragma" => "no-cache",
|
31
|
+
"Cache-Control" => "no-store, no-cache",
|
31
32
|
"Content-Type" => "application/json; charset=utf-8",
|
33
|
+
"Pragma" => "no-cache",
|
32
34
|
}
|
33
35
|
end
|
34
36
|
end
|
@@ -14,12 +14,6 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
14
14
|
optional: true,
|
15
15
|
inverse_of: :access_grants
|
16
16
|
|
17
|
-
if Doorkeeper.config.polymorphic_resource_owner?
|
18
|
-
belongs_to :resource_owner, polymorphic: true, optional: false
|
19
|
-
else
|
20
|
-
validates :resource_owner_id, presence: true
|
21
|
-
end
|
22
|
-
|
23
17
|
validates :application_id,
|
24
18
|
:token,
|
25
19
|
:expires_in,
|
@@ -14,10 +14,6 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
14
14
|
inverse_of: :access_tokens,
|
15
15
|
optional: true
|
16
16
|
|
17
|
-
if Doorkeeper.config.polymorphic_resource_owner?
|
18
|
-
belongs_to :resource_owner, polymorphic: true, optional: true
|
19
|
-
end
|
20
|
-
|
21
17
|
validates :token, presence: true, uniqueness: { case_sensitive: true }
|
22
18
|
validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
|
23
19
|
|
@@ -48,6 +44,27 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
48
44
|
column_names.include?("previous_refresh_token")
|
49
45
|
end
|
50
46
|
|
47
|
+
# Returns non-expired and non-revoked access tokens
|
48
|
+
def not_expired
|
49
|
+
relation = where(revoked_at: nil)
|
50
|
+
|
51
|
+
if supports_expiration_time_math?
|
52
|
+
# have not reached the expiration time or it never expires
|
53
|
+
relation.where("#{expiration_time_sql} > ?", Time.now.utc).or(
|
54
|
+
relation.where(expires_in: nil)
|
55
|
+
)
|
56
|
+
else
|
57
|
+
::Kernel.warn <<~WARNING.squish
|
58
|
+
[DOORKEEPER] Doorkeeper doesn't support expiration time math for your database adapter (#{adapter_name}).
|
59
|
+
Please add a class method `custom_expiration_time_sql` for your AccessToken class/mixin to provide a custom
|
60
|
+
SQL expression to calculate access token expiration time. See lib/doorkeeper/orm/active_record/mixins/access_token.rb
|
61
|
+
for more details.
|
62
|
+
WARNING
|
63
|
+
|
64
|
+
relation
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
51
68
|
private
|
52
69
|
|
53
70
|
def compute_doorkeeper_table_name
|
@@ -20,11 +20,13 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
20
20
|
dependent: :delete_all,
|
21
21
|
class_name: Doorkeeper.config.access_token_class.to_s
|
22
22
|
|
23
|
-
validates :name, :
|
23
|
+
validates :name, :uid, presence: true
|
24
|
+
validates :secret, presence: true, if: -> { secret_required? }
|
24
25
|
validates :uid, uniqueness: { case_sensitive: true }
|
25
|
-
validates :redirect_uri, "doorkeeper/redirect_uri": true
|
26
26
|
validates :confidential, inclusion: { in: [true, false] }
|
27
27
|
|
28
|
+
validates_with Doorkeeper::RedirectUriValidator, attributes: [:redirect_uri]
|
29
|
+
|
28
30
|
validate :scopes_match_configured, if: :enforce_scopes?
|
29
31
|
|
30
32
|
before_validation :generate_uid, :generate_secret, on: :create
|
@@ -44,7 +46,7 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
44
46
|
# @return [String] new transformed secret value
|
45
47
|
#
|
46
48
|
def renew_secret
|
47
|
-
@raw_secret =
|
49
|
+
@raw_secret = secret_generator.generate
|
48
50
|
secret_strategy.store_secret(self, :secret, @raw_secret)
|
49
51
|
end
|
50
52
|
|
@@ -102,12 +104,23 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
102
104
|
|
103
105
|
private
|
104
106
|
|
107
|
+
def secret_generator
|
108
|
+
generator_name = Doorkeeper.config.application_secret_generator
|
109
|
+
generator = generator_name.constantize
|
110
|
+
|
111
|
+
return generator if generator.respond_to?(:generate)
|
112
|
+
|
113
|
+
raise Errors::UnableToGenerateToken, "#{generator} does not respond to `.generate`."
|
114
|
+
rescue NameError
|
115
|
+
raise Errors::TokenGeneratorNotFound, "#{generator_name} not found"
|
116
|
+
end
|
117
|
+
|
105
118
|
def generate_uid
|
106
119
|
self.uid = Doorkeeper::OAuth::Helpers::UniqueToken.generate if uid.blank?
|
107
120
|
end
|
108
121
|
|
109
122
|
def generate_secret
|
110
|
-
return if secret.present?
|
123
|
+
return if secret.present? || !secret_required?
|
111
124
|
|
112
125
|
renew_secret
|
113
126
|
end
|
@@ -125,6 +138,11 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
|
|
125
138
|
Doorkeeper.config.enforce_configured_scopes?
|
126
139
|
end
|
127
140
|
|
141
|
+
def secret_required?
|
142
|
+
confidential? ||
|
143
|
+
!self.class.columns.detect { |column| column.name == "secret" }&.null
|
144
|
+
end
|
145
|
+
|
128
146
|
# Helper method to extract collection of serializable attribute names
|
129
147
|
# considering serialization options (like `only`, `except` and so on).
|
130
148
|
#
|
@@ -45,11 +45,11 @@ module Doorkeeper
|
|
45
45
|
end
|
46
46
|
|
47
47
|
def unspecified_host?(uri)
|
48
|
-
uri.is_a?(URI::HTTP) && uri.host.
|
48
|
+
uri.is_a?(URI::HTTP) && uri.host.blank?
|
49
49
|
end
|
50
50
|
|
51
51
|
def relative_uri?(uri)
|
52
|
-
uri.scheme.nil? && uri.host.
|
52
|
+
uri.scheme.nil? && uri.host.blank?
|
53
53
|
end
|
54
54
|
|
55
55
|
def invalid_ssl_uri?(uri)
|
@@ -15,7 +15,8 @@ module Doorkeeper
|
|
15
15
|
def clean_revoked
|
16
16
|
table = @base_scope.arel_table
|
17
17
|
|
18
|
-
@base_scope
|
18
|
+
@base_scope
|
19
|
+
.where.not(revoked_at: nil)
|
19
20
|
.where(table[:revoked_at].lt(Time.current))
|
20
21
|
.in_batches(&:delete_all)
|
21
22
|
end
|
@@ -24,7 +25,9 @@ module Doorkeeper
|
|
24
25
|
def clean_expired(ttl)
|
25
26
|
table = @base_scope.arel_table
|
26
27
|
|
27
|
-
@base_scope
|
28
|
+
@base_scope
|
29
|
+
.where.not(expires_in: nil)
|
30
|
+
.where(table[:created_at].lt(Time.current - ttl))
|
28
31
|
.in_batches(&:delete_all)
|
29
32
|
end
|
30
33
|
end
|
@@ -1,51 +1,44 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "active_support/lazy_load_hooks"
|
4
|
-
|
5
3
|
module Doorkeeper
|
4
|
+
autoload :AccessGrant, "doorkeeper/orm/active_record/access_grant"
|
5
|
+
autoload :AccessToken, "doorkeeper/orm/active_record/access_token"
|
6
|
+
autoload :Application, "doorkeeper/orm/active_record/application"
|
7
|
+
autoload :RedirectUriValidator, "doorkeeper/orm/active_record/redirect_uri_validator"
|
8
|
+
|
9
|
+
module Models
|
10
|
+
autoload :Ownership, "doorkeeper/models/concerns/ownership"
|
11
|
+
end
|
12
|
+
|
13
|
+
# ActiveRecord ORM for Doorkeeper entity models.
|
14
|
+
# Consists of three main OAuth entities:
|
15
|
+
# * Access Token
|
16
|
+
# * Access Grant
|
17
|
+
# * Application (client)
|
18
|
+
#
|
19
|
+
# Do a lazy loading of all the required and configured stuff.
|
20
|
+
#
|
6
21
|
module Orm
|
7
|
-
# ActiveRecord ORM for Doorkeeper entity models.
|
8
|
-
# Consists of three main OAuth entities:
|
9
|
-
# * Access Token
|
10
|
-
# * Access Grant
|
11
|
-
# * Application (client)
|
12
|
-
#
|
13
|
-
# Do a lazy loading of all the required and configured stuff.
|
14
|
-
#
|
15
22
|
module ActiveRecord
|
16
|
-
|
17
|
-
lazy_load do
|
18
|
-
require "doorkeeper/orm/active_record/stale_records_cleaner"
|
19
|
-
require "doorkeeper/orm/active_record/access_grant"
|
20
|
-
require "doorkeeper/orm/active_record/access_token"
|
21
|
-
require "doorkeeper/orm/active_record/application"
|
23
|
+
autoload :StaleRecordsCleaner, "doorkeeper/orm/active_record/stale_records_cleaner"
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
end
|
28
|
-
end
|
25
|
+
module Mixins
|
26
|
+
autoload :AccessGrant, "doorkeeper/orm/active_record/mixins/access_grant"
|
27
|
+
autoload :AccessToken, "doorkeeper/orm/active_record/mixins/access_token"
|
28
|
+
autoload :Application, "doorkeeper/orm/active_record/mixins/application"
|
29
29
|
end
|
30
30
|
|
31
|
-
def self.
|
32
|
-
|
33
|
-
require "doorkeeper/models/concerns/ownership"
|
34
|
-
|
35
|
-
Doorkeeper.config.application_model.include(Doorkeeper::Models::Ownership)
|
36
|
-
end
|
31
|
+
def self.run_hooks
|
32
|
+
initialize_configured_associations
|
37
33
|
end
|
38
34
|
|
39
|
-
def self.
|
40
|
-
|
41
|
-
|
35
|
+
def self.initialize_configured_associations
|
36
|
+
if Doorkeeper.config.enable_application_owner?
|
37
|
+
Doorkeeper.config.application_model.include ::Doorkeeper::Models::Ownership
|
38
|
+
end
|
42
39
|
|
43
|
-
|
44
|
-
|
45
|
-
Doorkeeper.config.access_grant_model,
|
46
|
-
Doorkeeper.config.access_token_model,
|
47
|
-
Doorkeeper.config.application_model,
|
48
|
-
]
|
40
|
+
Doorkeeper.config.access_grant_model.include ::Doorkeeper::Models::PolymorphicResourceOwner::ForAccessGrant
|
41
|
+
Doorkeeper.config.access_token_model.include ::Doorkeeper::Models::PolymorphicResourceOwner::ForAccessToken
|
49
42
|
end
|
50
43
|
end
|
51
44
|
end
|
@@ -36,7 +36,7 @@ module Doorkeeper
|
|
36
36
|
map_route(:authorizations, :authorization_routes)
|
37
37
|
map_route(:tokens, :token_routes)
|
38
38
|
map_route(:tokens, :revoke_routes)
|
39
|
-
map_route(:tokens, :introspect_routes)
|
39
|
+
map_route(:tokens, :introspect_routes) if introspection_routes?
|
40
40
|
map_route(:applications, :application_routes)
|
41
41
|
map_route(:authorized_applications, :authorized_applications_routes)
|
42
42
|
map_route(:token_info, :token_info_routes)
|
@@ -53,8 +53,8 @@ module Doorkeeper
|
|
53
53
|
as: mapping[:as],
|
54
54
|
controller: mapping[:controllers],
|
55
55
|
) do
|
56
|
-
routes.get
|
57
|
-
routes.get
|
56
|
+
routes.get native_authorization_code_route, action: :show, on: :member
|
57
|
+
routes.get '/', action: :new, on: :member
|
58
58
|
end
|
59
59
|
end
|
60
60
|
|
@@ -96,6 +96,15 @@ module Doorkeeper
|
|
96
96
|
only: %i[index destroy],
|
97
97
|
controller: mapping[:controllers]
|
98
98
|
end
|
99
|
+
|
100
|
+
def native_authorization_code_route
|
101
|
+
Doorkeeper.configuration.native_authorization_code_route
|
102
|
+
end
|
103
|
+
|
104
|
+
def introspection_routes?
|
105
|
+
Doorkeeper.configured? &&
|
106
|
+
!Doorkeeper.config.allow_token_introspection.is_a?(FalseClass)
|
107
|
+
end
|
99
108
|
end
|
100
109
|
end
|
101
110
|
end
|
@@ -2,10 +2,5 @@
|
|
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
|
10
5
|
end
|
11
6
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module RevocableTokens
|
5
|
+
class RevocableAccessToken
|
6
|
+
attr_reader :token
|
7
|
+
|
8
|
+
def initialize(token)
|
9
|
+
@token = token
|
10
|
+
end
|
11
|
+
|
12
|
+
def revocable?
|
13
|
+
token.accessible?
|
14
|
+
end
|
15
|
+
|
16
|
+
def revoke
|
17
|
+
token.revoke
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Doorkeeper
|
4
|
+
module RevocableTokens
|
5
|
+
class RevocableRefreshToken
|
6
|
+
attr_reader :token
|
7
|
+
|
8
|
+
def initialize(token)
|
9
|
+
@token = token
|
10
|
+
end
|
11
|
+
|
12
|
+
def revocable?
|
13
|
+
!token.revoked?
|
14
|
+
end
|
15
|
+
|
16
|
+
def revoke
|
17
|
+
token.revoke
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/doorkeeper/version.rb
CHANGED
data/lib/doorkeeper.rb
CHANGED
@@ -34,6 +34,11 @@ module Doorkeeper
|
|
34
34
|
autoload :Token, "doorkeeper/request/token"
|
35
35
|
end
|
36
36
|
|
37
|
+
module RevocableTokens
|
38
|
+
autoload :RevocableAccessToken, "doorkeeper/revocable_tokens/revocable_access_token"
|
39
|
+
autoload :RevocableRefreshToken, "doorkeeper/revocable_tokens/revocable_refresh_token"
|
40
|
+
end
|
41
|
+
|
37
42
|
module OAuth
|
38
43
|
autoload :BaseRequest, "doorkeeper/oauth/base_request"
|
39
44
|
autoload :AuthorizationCodeRequest, "doorkeeper/oauth/authorization_code_request"
|
@@ -88,7 +93,9 @@ module Doorkeeper
|
|
88
93
|
module Models
|
89
94
|
autoload :Accessible, "doorkeeper/models/concerns/accessible"
|
90
95
|
autoload :Expirable, "doorkeeper/models/concerns/expirable"
|
96
|
+
autoload :ExpirationTimeSqlMath, "doorkeeper/models/concerns/expiration_time_sql_math"
|
91
97
|
autoload :Orderable, "doorkeeper/models/concerns/orderable"
|
98
|
+
autoload :PolymorphicResourceOwner, "doorkeeper/models/concerns/polymorphic_resource_owner"
|
92
99
|
autoload :Scopes, "doorkeeper/models/concerns/scopes"
|
93
100
|
autoload :Reusable, "doorkeeper/models/concerns/reusable"
|
94
101
|
autoload :ResourceOwnerable, "doorkeeper/models/concerns/resource_ownerable"
|
@@ -112,11 +119,77 @@ module Doorkeeper
|
|
112
119
|
autoload :BCrypt, "doorkeeper/secret_storing/bcrypt"
|
113
120
|
end
|
114
121
|
|
115
|
-
|
116
|
-
|
117
|
-
|
122
|
+
class << self
|
123
|
+
attr_reader :orm_adapter
|
124
|
+
|
125
|
+
def configure(&block)
|
126
|
+
@config = Config::Builder.new(&block).build
|
127
|
+
setup
|
128
|
+
@config
|
129
|
+
end
|
130
|
+
|
131
|
+
# @return [Doorkeeper::Config] configuration instance
|
132
|
+
#
|
133
|
+
def configuration
|
134
|
+
@config || configure
|
135
|
+
end
|
136
|
+
|
137
|
+
def configured?
|
138
|
+
!@config.nil?
|
139
|
+
end
|
140
|
+
|
141
|
+
alias config configuration
|
142
|
+
|
143
|
+
def setup
|
144
|
+
setup_orm_adapter
|
145
|
+
|
146
|
+
# Deprecated, will be removed soon
|
147
|
+
unless configuration.orm == :active_record
|
148
|
+
setup_orm_models
|
149
|
+
setup_application_owner
|
150
|
+
end
|
151
|
+
end
|
118
152
|
|
119
|
-
|
120
|
-
|
153
|
+
def setup_orm_adapter
|
154
|
+
@orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
|
155
|
+
rescue NameError => e
|
156
|
+
raise e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
|
157
|
+
[DOORKEEPER] ORM adapter not found (#{configuration.orm}), or there was an error
|
158
|
+
trying to load it.
|
159
|
+
|
160
|
+
You probably need to add the related gem for this adapter to work with
|
161
|
+
doorkeeper.
|
162
|
+
ERROR_MSG
|
163
|
+
end
|
164
|
+
|
165
|
+
def run_orm_hooks
|
166
|
+
config.clear_cache!
|
167
|
+
|
168
|
+
if @orm_adapter.respond_to?(:run_hooks)
|
169
|
+
@orm_adapter.run_hooks
|
170
|
+
else
|
171
|
+
::Kernel.warn <<~MSG.strip_heredoc
|
172
|
+
[DOORKEEPER] ORM "#{configuration.orm}" should move all it's setup logic under `#run_hooks` method for
|
173
|
+
the #{@orm_adapter.name}. Later versions of Doorkeeper will no longer support `setup_orm_models` and
|
174
|
+
`setup_application_owner` API.
|
175
|
+
MSG
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def setup_orm_models
|
180
|
+
@orm_adapter.initialize_models!
|
181
|
+
end
|
182
|
+
|
183
|
+
def setup_application_owner
|
184
|
+
@orm_adapter.initialize_application_owner!
|
185
|
+
end
|
186
|
+
|
187
|
+
def authenticate(request, methods = Doorkeeper.config.access_token_methods)
|
188
|
+
OAuth::Token.authenticate(request, *methods)
|
189
|
+
end
|
190
|
+
|
191
|
+
def gem_version
|
192
|
+
::Gem::Version.new(::Doorkeeper::VERSION::STRING)
|
193
|
+
end
|
121
194
|
end
|
122
195
|
end
|