doorkeeper 5.3.0 → 5.4.0.rc1
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 +0 -14
- data/CHANGELOG.md +44 -1
- data/Dangerfile +7 -7
- data/Dockerfile +2 -2
- data/Gemfile +9 -9
- data/README.md +6 -4
- data/app/controllers/doorkeeper/applications_controller.rb +4 -4
- data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +57 -20
- data/app/views/doorkeeper/applications/show.html.erb +19 -2
- data/bin/console +14 -0
- data/config/locales/en.yml +3 -1
- data/doorkeeper.gemspec +1 -1
- data/gemfiles/rails_5_0.gemfile +8 -7
- data/gemfiles/rails_5_1.gemfile +8 -7
- data/gemfiles/rails_5_2.gemfile +8 -7
- data/gemfiles/rails_6_0.gemfile +8 -7
- data/gemfiles/rails_master.gemfile +8 -7
- data/lib/doorkeeper/config/abstract_builder.rb +28 -0
- data/lib/doorkeeper/config/option.rb +28 -14
- data/lib/doorkeeper/config.rb +41 -17
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/models/access_grant_mixin.rb +9 -11
- data/lib/doorkeeper/models/access_token_mixin.rb +102 -42
- data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
- 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 +14 -5
- data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +7 -11
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
- data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
- data/lib/doorkeeper/oauth/base_request.rb +11 -19
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +25 -7
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
- data/lib/doorkeeper/oauth/client_credentials/validator.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
- data/lib/doorkeeper/oauth/code_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_response.rb +6 -2
- data/lib/doorkeeper/oauth/error_response.rb +2 -4
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
- data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -5
- data/lib/doorkeeper/oauth/pre_authorization.rb +32 -27
- data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
- data/lib/doorkeeper/oauth/token.rb +1 -1
- data/lib/doorkeeper/oauth/token_introspection.rb +3 -3
- data/lib/doorkeeper/oauth/token_request.rb +2 -2
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +7 -2
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +6 -2
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -2
- 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 +13 -17
- data/lib/doorkeeper/request/strategy.rb +2 -2
- data/lib/doorkeeper/server.rb +3 -3
- data/lib/doorkeeper/version.rb +2 -2
- data/lib/doorkeeper.rb +106 -79
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
- data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +2 -0
- 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 +47 -3
- data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -0
- data/spec/controllers/applications_controller_spec.rb +2 -2
- data/spec/controllers/authorizations_controller_spec.rb +165 -30
- data/spec/controllers/tokens_controller_spec.rb +6 -5
- data/spec/dummy/app/helpers/application_helper.rb +1 -1
- data/spec/dummy/app/models/user.rb +5 -1
- data/spec/dummy/config/application.rb +6 -4
- data/spec/dummy/config/boot.rb +4 -4
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/routes.rb +4 -4
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +2 -2
- data/spec/dummy/db/schema.rb +3 -1
- data/spec/factories.rb +1 -1
- data/spec/generators/enable_polymorphic_resource_owner_generator_spec.rb +47 -0
- data/spec/lib/config_spec.rb +30 -11
- data/spec/lib/models/revocable_spec.rb +2 -3
- data/spec/lib/models/scopes_spec.rb +8 -0
- data/spec/lib/oauth/authorization_code_request_spec.rb +25 -15
- data/spec/lib/oauth/base_request_spec.rb +6 -20
- data/spec/lib/oauth/client_credentials/creator_spec.rb +90 -89
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +84 -86
- data/spec/lib/oauth/client_credentials/validation_spec.rb +38 -40
- data/spec/lib/oauth/client_credentials_request_spec.rb +5 -4
- data/spec/lib/oauth/code_request_spec.rb +1 -1
- data/spec/lib/oauth/code_response_spec.rb +5 -1
- data/spec/lib/oauth/error_response_spec.rb +1 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +24 -13
- data/spec/lib/oauth/pre_authorization_spec.rb +13 -18
- data/spec/lib/oauth/refresh_token_request_spec.rb +19 -30
- data/spec/lib/oauth/token_request_spec.rb +14 -7
- data/spec/lib/option_spec.rb +51 -0
- data/spec/lib/stale_records_cleaner_spec.rb +18 -5
- data/spec/models/doorkeeper/access_grant_spec.rb +18 -4
- data/spec/models/doorkeeper/access_token_spec.rb +507 -479
- data/spec/models/doorkeeper/application_spec.rb +338 -300
- data/spec/requests/endpoints/token_spec.rb +5 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +4 -1
- data/spec/requests/flows/authorization_code_spec.rb +6 -1
- data/spec/requests/flows/client_credentials_spec.rb +41 -0
- data/spec/requests/flows/refresh_token_spec.rb +16 -8
- data/spec/requests/flows/revoke_token_spec.rb +143 -104
- data/spec/support/helpers/access_token_request_helper.rb +1 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/config_helper.rb +1 -1
- data/spec/support/shared/controllers_shared_context.rb +2 -2
- data/spec/support/shared/models_shared_examples.rb +6 -4
- metadata +15 -4
|
@@ -4,7 +4,7 @@ module Doorkeeper
|
|
|
4
4
|
module OAuth
|
|
5
5
|
module Authorization
|
|
6
6
|
class Token
|
|
7
|
-
|
|
7
|
+
attr_reader :pre_auth, :resource_owner, :token
|
|
8
8
|
|
|
9
9
|
class << self
|
|
10
10
|
def build_context(pre_auth_or_oauth_client, grant_type, scopes)
|
|
@@ -57,12 +57,12 @@ module Doorkeeper
|
|
|
57
57
|
pre_auth.scopes,
|
|
58
58
|
)
|
|
59
59
|
|
|
60
|
-
@token =
|
|
61
|
-
pre_auth.client,
|
|
62
|
-
resource_owner
|
|
63
|
-
pre_auth.scopes,
|
|
64
|
-
self.class.access_token_expires_in(
|
|
65
|
-
false,
|
|
60
|
+
@token = Doorkeeper.config.access_token_model.find_or_create_for(
|
|
61
|
+
application: pre_auth.client,
|
|
62
|
+
resource_owner: resource_owner,
|
|
63
|
+
scopes: pre_auth.scopes,
|
|
64
|
+
expires_in: self.class.access_token_expires_in(Doorkeeper.config, context),
|
|
65
|
+
use_refresh_token: false,
|
|
66
66
|
)
|
|
67
67
|
end
|
|
68
68
|
|
|
@@ -76,10 +76,6 @@ module Doorkeeper
|
|
|
76
76
|
|
|
77
77
|
private
|
|
78
78
|
|
|
79
|
-
def configuration
|
|
80
|
-
Doorkeeper.config
|
|
81
|
-
end
|
|
82
|
-
|
|
83
79
|
def controller
|
|
84
80
|
@controller ||= begin
|
|
85
81
|
mapping = Doorkeeper::Rails::Routes.mapping[:token_info] || {}
|
|
@@ -8,9 +8,9 @@ module Doorkeeper
|
|
|
8
8
|
class URIBuilder
|
|
9
9
|
class << self
|
|
10
10
|
def uri_with_query(url, parameters = {})
|
|
11
|
-
uri
|
|
11
|
+
uri = URI.parse(url)
|
|
12
12
|
original_query = Rack::Utils.parse_query(uri.query)
|
|
13
|
-
uri.query
|
|
13
|
+
uri.query = build_query(original_query.merge(parameters))
|
|
14
14
|
uri.to_s
|
|
15
15
|
end
|
|
16
16
|
|
|
@@ -23,8 +23,8 @@ module Doorkeeper
|
|
|
23
23
|
private
|
|
24
24
|
|
|
25
25
|
def build_query(parameters = {})
|
|
26
|
-
parameters = parameters.reject { |_,
|
|
27
|
-
Rack::Utils.build_query
|
|
26
|
+
parameters = parameters.reject { |_, value| value.blank? }
|
|
27
|
+
Rack::Utils.build_query(parameters)
|
|
28
28
|
end
|
|
29
29
|
end
|
|
30
30
|
end
|
|
@@ -11,9 +11,8 @@ module Doorkeeper
|
|
|
11
11
|
validate :redirect_uri, error: :invalid_grant
|
|
12
12
|
validate :code_verifier, error: :invalid_grant
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
attr_reader :invalid_request_reason, :missing_param
|
|
14
|
+
attr_reader :grant, :client, :redirect_uri, :access_token, :code_verifier,
|
|
15
|
+
:invalid_request_reason, :missing_param
|
|
17
16
|
|
|
18
17
|
def initialize(server, grant, client, parameters = {})
|
|
19
18
|
@server = server
|
|
@@ -33,19 +32,30 @@ module Doorkeeper
|
|
|
33
32
|
|
|
34
33
|
grant.revoke
|
|
35
34
|
|
|
35
|
+
resource_owner = if Doorkeeper.config.polymorphic_resource_owner?
|
|
36
|
+
grant.resource_owner
|
|
37
|
+
else
|
|
38
|
+
grant.resource_owner_id
|
|
39
|
+
end
|
|
40
|
+
|
|
36
41
|
find_or_create_access_token(
|
|
37
42
|
grant.application,
|
|
38
|
-
|
|
43
|
+
resource_owner,
|
|
39
44
|
grant.scopes,
|
|
40
45
|
server,
|
|
41
46
|
)
|
|
42
47
|
end
|
|
48
|
+
|
|
43
49
|
super
|
|
44
50
|
end
|
|
45
51
|
|
|
52
|
+
def pkce_supported?
|
|
53
|
+
Doorkeeper.config.access_grant_model.pkce_supported?
|
|
54
|
+
end
|
|
55
|
+
|
|
46
56
|
def validate_pkce_support
|
|
47
57
|
@invalid_request_reason = :not_support_pkce if grant &&
|
|
48
|
-
!
|
|
58
|
+
!pkce_supported? &&
|
|
49
59
|
code_verifier.present?
|
|
50
60
|
|
|
51
61
|
@invalid_request_reason.nil?
|
|
@@ -78,11 +88,11 @@ module Doorkeeper
|
|
|
78
88
|
)
|
|
79
89
|
end
|
|
80
90
|
|
|
81
|
-
# if either side (server or client) request
|
|
82
|
-
# against the DB - if
|
|
91
|
+
# if either side (server or client) request PKCE, check the verifier
|
|
92
|
+
# against the DB - if PKCE is supported
|
|
83
93
|
def validate_code_verifier
|
|
84
94
|
return true unless grant.uses_pkce? || code_verifier
|
|
85
|
-
return false unless
|
|
95
|
+
return false unless pkce_supported?
|
|
86
96
|
|
|
87
97
|
if grant.code_challenge_method == "S256"
|
|
88
98
|
grant.code_challenge == generate_code_challenge(code_verifier)
|
|
@@ -5,11 +5,11 @@ module Doorkeeper
|
|
|
5
5
|
class BaseRequest
|
|
6
6
|
include Validations
|
|
7
7
|
|
|
8
|
-
attr_reader :grant_type
|
|
8
|
+
attr_reader :grant_type, :server
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
validate
|
|
10
|
+
delegate :default_scopes, to: :server
|
|
12
11
|
|
|
12
|
+
def authorize
|
|
13
13
|
if valid?
|
|
14
14
|
before_successful_response
|
|
15
15
|
@response = TokenResponse.new(access_token)
|
|
@@ -26,22 +26,14 @@ module Doorkeeper
|
|
|
26
26
|
@scopes ||= build_scopes
|
|
27
27
|
end
|
|
28
28
|
|
|
29
|
-
def
|
|
30
|
-
server.default_scopes
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
def valid?
|
|
34
|
-
error.nil?
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
def find_or_create_access_token(client, resource_owner_id, scopes, server)
|
|
29
|
+
def find_or_create_access_token(client, resource_owner, scopes, server)
|
|
38
30
|
context = Authorization::Token.build_context(client, grant_type, scopes)
|
|
39
31
|
@access_token = server_config.access_token_model.find_or_create_for(
|
|
40
|
-
client,
|
|
41
|
-
|
|
42
|
-
scopes,
|
|
43
|
-
Authorization::Token.access_token_expires_in(server, context),
|
|
44
|
-
Authorization::Token.refresh_token_enabled?(server, context),
|
|
32
|
+
application: client,
|
|
33
|
+
resource_owner: resource_owner,
|
|
34
|
+
scopes: scopes,
|
|
35
|
+
expires_in: Authorization::Token.access_token_expires_in(server, context),
|
|
36
|
+
use_refresh_token: Authorization::Token.refresh_token_enabled?(server, context),
|
|
45
37
|
)
|
|
46
38
|
end
|
|
47
39
|
|
|
@@ -63,10 +55,10 @@ module Doorkeeper
|
|
|
63
55
|
if @original_scopes.present?
|
|
64
56
|
OAuth::Scopes.from_string(@original_scopes)
|
|
65
57
|
else
|
|
66
|
-
client_scopes = @client
|
|
58
|
+
client_scopes = @client&.scopes
|
|
67
59
|
return default_scopes if client_scopes.blank?
|
|
68
60
|
|
|
69
|
-
default_scopes &
|
|
61
|
+
default_scopes & client_scopes
|
|
70
62
|
end
|
|
71
63
|
end
|
|
72
64
|
end
|
|
@@ -9,7 +9,7 @@ module Doorkeeper
|
|
|
9
9
|
credentials_methods.inject(nil) do |_, method|
|
|
10
10
|
method = self.method(method) if method.is_a?(Symbol)
|
|
11
11
|
credentials = Credentials.new(*method.call(request))
|
|
12
|
-
break credentials
|
|
12
|
+
break credentials if credentials.present?
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
@@ -27,9 +27,7 @@ module Doorkeeper
|
|
|
27
27
|
|
|
28
28
|
# Public clients may have their secret blank, but "credentials" are
|
|
29
29
|
# still present
|
|
30
|
-
|
|
31
|
-
uid.blank?
|
|
32
|
-
end
|
|
30
|
+
delegate :blank?, to: :uid
|
|
33
31
|
end
|
|
34
32
|
end
|
|
35
33
|
end
|
|
@@ -2,24 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
module OAuth
|
|
5
|
-
|
|
5
|
+
module ClientCredentials
|
|
6
6
|
class Creator
|
|
7
7
|
def call(client, scopes, attributes = {})
|
|
8
|
+
existing_token = nil
|
|
9
|
+
|
|
8
10
|
if lookup_existing_token?
|
|
9
11
|
existing_token = find_existing_token_for(client, scopes)
|
|
10
12
|
return existing_token if server_config.reuse_access_token && existing_token&.reusable?
|
|
11
|
-
|
|
12
|
-
existing_token&.revoke if server_config.revoke_previous_client_credentials_token
|
|
13
13
|
end
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
with_revocation(existing_token: existing_token) do
|
|
16
|
+
server_config.access_token_model.find_or_create_for(
|
|
17
|
+
application: client,
|
|
18
|
+
resource_owner: nil,
|
|
19
|
+
scopes: scopes,
|
|
20
|
+
**attributes,
|
|
21
|
+
)
|
|
22
|
+
end
|
|
19
23
|
end
|
|
20
24
|
|
|
21
25
|
private
|
|
22
26
|
|
|
27
|
+
def with_revocation(existing_token:)
|
|
28
|
+
if existing_token && server_config.revoke_previous_client_credentials_token
|
|
29
|
+
existing_token.with_lock do
|
|
30
|
+
raise Errors::DoorkeeperError, :invalid_token_reuse if existing_token.revoked?
|
|
31
|
+
|
|
32
|
+
existing_token.revoke
|
|
33
|
+
|
|
34
|
+
yield
|
|
35
|
+
end
|
|
36
|
+
else
|
|
37
|
+
yield
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
23
41
|
def lookup_existing_token?
|
|
24
42
|
server_config.reuse_access_token || server_config.revoke_previous_client_credentials_token
|
|
25
43
|
end
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
module OAuth
|
|
5
|
-
|
|
5
|
+
module ClientCredentials
|
|
6
6
|
class Issuer
|
|
7
|
-
|
|
7
|
+
attr_reader :token, :validator, :error
|
|
8
8
|
|
|
9
9
|
def initialize(server, validator)
|
|
10
10
|
@server = server
|
|
@@ -19,6 +19,7 @@ module Doorkeeper
|
|
|
19
19
|
@token = false
|
|
20
20
|
@error = validator.error
|
|
21
21
|
end
|
|
22
|
+
|
|
22
23
|
@token
|
|
23
24
|
end
|
|
24
25
|
|
|
@@ -3,18 +3,12 @@
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
module OAuth
|
|
5
5
|
class ClientCredentialsRequest < BaseRequest
|
|
6
|
-
|
|
7
|
-
attr_reader :response
|
|
8
|
-
attr_writer :issuer
|
|
6
|
+
attr_reader :client, :original_scopes, :response
|
|
9
7
|
|
|
10
8
|
alias error_response response
|
|
11
9
|
|
|
12
10
|
delegate :error, to: :issuer
|
|
13
11
|
|
|
14
|
-
def issuer
|
|
15
|
-
@issuer ||= Issuer.new(server, Validator.new(server, self))
|
|
16
|
-
end
|
|
17
|
-
|
|
18
12
|
def initialize(server, client, parameters = {})
|
|
19
13
|
@client = client
|
|
20
14
|
@server = server
|
|
@@ -26,6 +20,13 @@ module Doorkeeper
|
|
|
26
20
|
issuer.token
|
|
27
21
|
end
|
|
28
22
|
|
|
23
|
+
def issuer
|
|
24
|
+
@issuer ||= ClientCredentials::Issuer.new(
|
|
25
|
+
server,
|
|
26
|
+
ClientCredentials::Validator.new(server, self),
|
|
27
|
+
)
|
|
28
|
+
end
|
|
29
|
+
|
|
29
30
|
private
|
|
30
31
|
|
|
31
32
|
def valid?
|
|
@@ -5,7 +5,7 @@ module Doorkeeper
|
|
|
5
5
|
class CodeResponse < BaseResponse
|
|
6
6
|
include OAuth::Helpers
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
attr_reader :pre_auth, :auth, :response_on_fragment
|
|
9
9
|
|
|
10
10
|
def initialize(pre_auth, auth, options = {})
|
|
11
11
|
@pre_auth = pre_auth
|
|
@@ -17,8 +17,12 @@ module Doorkeeper
|
|
|
17
17
|
true
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
def issued_token
|
|
21
|
+
auth.token
|
|
22
|
+
end
|
|
23
|
+
|
|
20
24
|
def redirect_uri
|
|
21
|
-
if URIChecker.oob_uri?
|
|
25
|
+
if URIChecker.oob_uri?(pre_auth.redirect_uri)
|
|
22
26
|
auth.oob_redirect
|
|
23
27
|
elsif response_on_fragment
|
|
24
28
|
Authorization::URIBuilder.uri_with_fragment(
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Doorkeeper
|
|
4
|
+
module OAuth
|
|
5
|
+
module Hooks
|
|
6
|
+
class Context
|
|
7
|
+
attr_reader :auth, :pre_auth
|
|
8
|
+
|
|
9
|
+
def initialize(**attributes)
|
|
10
|
+
attributes.each do |name, value|
|
|
11
|
+
instance_variable_set(:"@#{name}", value) if respond_to?(name)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def issued_token
|
|
16
|
+
auth&.issued_token
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -6,9 +6,9 @@ module Doorkeeper
|
|
|
6
6
|
attr_reader :reason
|
|
7
7
|
|
|
8
8
|
def self.from_access_token(access_token, attributes = {})
|
|
9
|
-
reason = if access_token
|
|
9
|
+
reason = if access_token&.revoked?
|
|
10
10
|
:revoked
|
|
11
|
-
elsif access_token
|
|
11
|
+
elsif access_token&.expired?
|
|
12
12
|
:expired
|
|
13
13
|
else
|
|
14
14
|
:unknown
|
|
@@ -10,8 +10,7 @@ module Doorkeeper
|
|
|
10
10
|
validate :resource_owner, error: :invalid_grant
|
|
11
11
|
validate :scopes, error: :invalid_scope
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
:access_token
|
|
13
|
+
attr_reader :client, :resource_owner, :parameters, :access_token
|
|
15
14
|
|
|
16
15
|
def initialize(server, client, resource_owner, parameters = {})
|
|
17
16
|
@server = server
|
|
@@ -25,18 +24,17 @@ module Doorkeeper
|
|
|
25
24
|
private
|
|
26
25
|
|
|
27
26
|
def before_successful_response
|
|
28
|
-
find_or_create_access_token(client, resource_owner
|
|
27
|
+
find_or_create_access_token(client, resource_owner, scopes, server)
|
|
29
28
|
super
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
def validate_scopes
|
|
33
|
-
client_scopes = client.try(:scopes)
|
|
34
32
|
return true if scopes.blank?
|
|
35
33
|
|
|
36
34
|
ScopeChecker.valid?(
|
|
37
35
|
scope_str: scopes.to_s,
|
|
38
36
|
server_scopes: server.scopes,
|
|
39
|
-
app_scopes:
|
|
37
|
+
app_scopes: client.try(:scopes),
|
|
40
38
|
grant_type: grant_type,
|
|
41
39
|
)
|
|
42
40
|
end
|
|
@@ -5,39 +5,37 @@ module Doorkeeper
|
|
|
5
5
|
class PreAuthorization
|
|
6
6
|
include Validations
|
|
7
7
|
|
|
8
|
-
validate :client_id,
|
|
9
|
-
validate :client,
|
|
10
|
-
validate :
|
|
11
|
-
validate :
|
|
12
|
-
validate :
|
|
13
|
-
validate :
|
|
8
|
+
validate :client_id, error: :invalid_request
|
|
9
|
+
validate :client, error: :invalid_client
|
|
10
|
+
validate :resource_owner_authorize_for_client, error: :invalid_client
|
|
11
|
+
validate :redirect_uri, error: :invalid_redirect_uri
|
|
12
|
+
validate :params, error: :invalid_request
|
|
13
|
+
validate :response_type, error: :unsupported_response_type
|
|
14
|
+
validate :scopes, error: :invalid_scope
|
|
14
15
|
validate :code_challenge_method, error: :invalid_code_challenge_method
|
|
15
16
|
validate :client_supports_grant_flow, error: :unauthorized_client
|
|
16
17
|
|
|
17
18
|
attr_reader :server, :client_id, :client, :redirect_uri, :response_type, :state,
|
|
18
|
-
:code_challenge, :code_challenge_method, :missing_param
|
|
19
|
+
:code_challenge, :code_challenge_method, :missing_param, :resource_owner
|
|
19
20
|
|
|
20
|
-
def initialize(server,
|
|
21
|
+
def initialize(server, parameters = {}, resource_owner = nil)
|
|
21
22
|
@server = server
|
|
22
|
-
@client_id =
|
|
23
|
-
@response_type =
|
|
24
|
-
@redirect_uri =
|
|
25
|
-
@scope =
|
|
26
|
-
@state =
|
|
27
|
-
@code_challenge =
|
|
28
|
-
@code_challenge_method =
|
|
23
|
+
@client_id = parameters[:client_id]
|
|
24
|
+
@response_type = parameters[:response_type]
|
|
25
|
+
@redirect_uri = parameters[:redirect_uri]
|
|
26
|
+
@scope = parameters[:scope]
|
|
27
|
+
@state = parameters[:state]
|
|
28
|
+
@code_challenge = parameters[:code_challenge]
|
|
29
|
+
@code_challenge_method = parameters[:code_challenge_method]
|
|
30
|
+
@resource_owner = resource_owner
|
|
29
31
|
end
|
|
30
32
|
|
|
31
33
|
def authorizable?
|
|
32
34
|
valid?
|
|
33
35
|
end
|
|
34
36
|
|
|
35
|
-
def validate_client_supports_grant_flow
|
|
36
|
-
Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
|
|
37
|
-
end
|
|
38
|
-
|
|
39
37
|
def scopes
|
|
40
|
-
Scopes.from_string
|
|
38
|
+
Scopes.from_string(scope)
|
|
41
39
|
end
|
|
42
40
|
|
|
43
41
|
def scope
|
|
@@ -55,9 +53,7 @@ module Doorkeeper
|
|
|
55
53
|
end
|
|
56
54
|
end
|
|
57
55
|
|
|
58
|
-
def as_json(
|
|
59
|
-
return pre_auth_hash.merge(attributes.to_h) if attributes.respond_to?(:to_h)
|
|
60
|
-
|
|
56
|
+
def as_json(_options = nil)
|
|
61
57
|
pre_auth_hash
|
|
62
58
|
end
|
|
63
59
|
|
|
@@ -83,6 +79,10 @@ module Doorkeeper
|
|
|
83
79
|
@client.present?
|
|
84
80
|
end
|
|
85
81
|
|
|
82
|
+
def validate_client_supports_grant_flow
|
|
83
|
+
Doorkeeper.config.allow_grant_flow_for_client?(grant_type, client.application)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
86
|
def validate_redirect_uri
|
|
87
87
|
return false if redirect_uri.blank?
|
|
88
88
|
|
|
@@ -115,19 +115,24 @@ module Doorkeeper
|
|
|
115
115
|
)
|
|
116
116
|
end
|
|
117
117
|
|
|
118
|
-
def grant_type
|
|
119
|
-
response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
|
|
120
|
-
end
|
|
121
|
-
|
|
122
118
|
def validate_code_challenge_method
|
|
123
119
|
code_challenge.blank? ||
|
|
124
120
|
(code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
|
|
125
121
|
end
|
|
126
122
|
|
|
123
|
+
def validate_resource_owner_authorize_for_client
|
|
124
|
+
# The `authorize_resource_owner_for_client` config option is used for this validation
|
|
125
|
+
client.application.authorized_for_resource_owner?(@resource_owner)
|
|
126
|
+
end
|
|
127
|
+
|
|
127
128
|
def response_on_fragment?
|
|
128
129
|
response_type == "token"
|
|
129
130
|
end
|
|
130
131
|
|
|
132
|
+
def grant_type
|
|
133
|
+
response_type == "code" ? AUTHORIZATION_CODE : IMPLICIT
|
|
134
|
+
end
|
|
135
|
+
|
|
131
136
|
def pre_auth_hash
|
|
132
137
|
{
|
|
133
138
|
client_id: client.uid,
|
|
@@ -11,9 +11,8 @@ module Doorkeeper
|
|
|
11
11
|
validate :client_match, error: :invalid_grant
|
|
12
12
|
validate :scope, error: :invalid_scope
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
attr_reader :missing_param
|
|
14
|
+
attr_reader :access_token, :client, :credentials, :refresh_token
|
|
15
|
+
attr_reader :missing_param
|
|
17
16
|
|
|
18
17
|
def initialize(server, refresh_token, credentials, parameters = {})
|
|
19
18
|
@server = server
|
|
@@ -50,30 +49,27 @@ module Doorkeeper
|
|
|
50
49
|
end
|
|
51
50
|
|
|
52
51
|
def create_access_token
|
|
53
|
-
|
|
54
|
-
end
|
|
52
|
+
attributes = {}
|
|
55
53
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
expires_in: access_token_expires_in,
|
|
62
|
-
use_refresh_token: true,
|
|
63
|
-
}.tap do |attributes|
|
|
64
|
-
if refresh_token_revoked_on_use?
|
|
65
|
-
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
|
|
66
59
|
end
|
|
60
|
+
|
|
61
|
+
if refresh_token_revoked_on_use?
|
|
62
|
+
attributes[:previous_refresh_token] = refresh_token.refresh_token
|
|
67
63
|
end
|
|
68
|
-
end
|
|
69
64
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
65
|
+
@access_token = server_config.access_token_model.create_for(
|
|
66
|
+
application: refresh_token.application,
|
|
67
|
+
resource_owner: resource_owner,
|
|
68
|
+
scopes: scopes,
|
|
69
|
+
expires_in: refresh_token.expires_in,
|
|
70
|
+
use_refresh_token: true,
|
|
71
|
+
**attributes,
|
|
75
72
|
)
|
|
76
|
-
Authorization::Token.access_token_expires_in(server, context)
|
|
77
73
|
end
|
|
78
74
|
|
|
79
75
|
def validate_token_presence
|
|
@@ -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, :invalid_request_reason
|
|
11
|
-
|
|
12
9
|
def initialize(server, token)
|
|
13
10
|
@server = server
|
|
14
11
|
@token = token
|
|
@@ -38,6 +35,9 @@ module Doorkeeper
|
|
|
38
35
|
|
|
39
36
|
private
|
|
40
37
|
|
|
38
|
+
attr_reader :server, :token
|
|
39
|
+
attr_reader :error, :invalid_request_reason
|
|
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
|
|
43
43
|
# invalid, the authorization server responds with an HTTP 401
|