doorkeeper 5.0.0 → 5.1.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.
Files changed (160) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +12 -3
  3. data/Dangerfile +67 -0
  4. data/Gemfile +3 -1
  5. data/NEWS.md +49 -5
  6. data/README.md +19 -4
  7. data/app/controllers/doorkeeper/application_controller.rb +2 -0
  8. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -0
  9. data/app/controllers/doorkeeper/applications_controller.rb +4 -2
  10. data/app/controllers/doorkeeper/authorizations_controller.rb +3 -3
  11. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -0
  12. data/app/controllers/doorkeeper/token_info_controller.rb +2 -0
  13. data/app/controllers/doorkeeper/tokens_controller.rb +8 -6
  14. data/app/helpers/doorkeeper/dashboard_helper.rb +2 -0
  15. data/app/validators/redirect_uri_validator.rb +2 -0
  16. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  17. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  18. data/bin/console +15 -0
  19. data/doorkeeper.gemspec +23 -22
  20. data/gemfiles/rails_4_2.gemfile +1 -0
  21. data/gemfiles/rails_5_0.gemfile +1 -0
  22. data/gemfiles/rails_5_1.gemfile +1 -0
  23. data/gemfiles/rails_5_2.gemfile +2 -1
  24. data/gemfiles/rails_master.gemfile +1 -0
  25. data/lib/doorkeeper/config.rb +80 -8
  26. data/lib/doorkeeper/engine.rb +2 -0
  27. data/lib/doorkeeper/errors.rb +17 -0
  28. data/lib/doorkeeper/grape/authorization_decorator.rb +2 -0
  29. data/lib/doorkeeper/grape/helpers.rb +2 -0
  30. data/lib/doorkeeper/helpers/controller.rb +5 -2
  31. data/lib/doorkeeper/models/access_grant_mixin.rb +13 -4
  32. data/lib/doorkeeper/models/access_token_mixin.rb +45 -12
  33. data/lib/doorkeeper/models/application_mixin.rb +54 -1
  34. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  35. data/lib/doorkeeper/models/concerns/expirable.rb +2 -0
  36. data/lib/doorkeeper/models/concerns/hashable.rb +137 -0
  37. data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
  38. data/lib/doorkeeper/models/concerns/ownership.rb +2 -0
  39. data/lib/doorkeeper/models/concerns/revocable.rb +2 -0
  40. data/lib/doorkeeper/models/concerns/scopes.rb +3 -1
  41. data/lib/doorkeeper/oauth/authorization/code.rb +3 -1
  42. data/lib/doorkeeper/oauth/authorization/context.rb +2 -0
  43. data/lib/doorkeeper/oauth/authorization/token.rb +3 -1
  44. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
  45. data/lib/doorkeeper/oauth/authorization_code_request.rb +3 -1
  46. data/lib/doorkeeper/oauth/base_request.rb +2 -0
  47. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  48. data/lib/doorkeeper/oauth/client/credentials.rb +2 -0
  49. data/lib/doorkeeper/oauth/client.rb +3 -1
  50. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -0
  51. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +2 -0
  52. data/lib/doorkeeper/oauth/client_credentials/validation.rb +6 -3
  53. data/lib/doorkeeper/oauth/client_credentials_request.rb +2 -0
  54. data/lib/doorkeeper/oauth/code_request.rb +2 -0
  55. data/lib/doorkeeper/oauth/code_response.rb +4 -2
  56. data/lib/doorkeeper/oauth/error.rb +2 -0
  57. data/lib/doorkeeper/oauth/error_response.rb +10 -0
  58. data/lib/doorkeeper/oauth/forbidden_token_response.rb +9 -2
  59. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +25 -8
  60. data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -0
  61. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -2
  62. data/lib/doorkeeper/oauth/invalid_token_response.rb +18 -0
  63. data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -2
  64. data/lib/doorkeeper/oauth/pre_authorization.rb +10 -3
  65. data/lib/doorkeeper/oauth/refresh_token_request.rb +14 -3
  66. data/lib/doorkeeper/oauth/scopes.rb +2 -0
  67. data/lib/doorkeeper/oauth/token.rb +2 -0
  68. data/lib/doorkeeper/oauth/token_introspection.rb +2 -0
  69. data/lib/doorkeeper/oauth/token_request.rb +2 -0
  70. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  71. data/lib/doorkeeper/orm/active_record/access_grant.rb +22 -2
  72. data/lib/doorkeeper/orm/active_record/application.rb +16 -2
  73. data/lib/doorkeeper/orm/active_record.rb +2 -0
  74. data/lib/doorkeeper/rails/helpers.rb +4 -0
  75. data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
  76. data/lib/doorkeeper/rails/routes/mapping.rb +2 -0
  77. data/lib/doorkeeper/rails/routes.rb +9 -2
  78. data/lib/doorkeeper/rake/db.rake +4 -4
  79. data/lib/doorkeeper/request/authorization_code.rb +2 -0
  80. data/lib/doorkeeper/request/client_credentials.rb +2 -0
  81. data/lib/doorkeeper/request/code.rb +2 -0
  82. data/lib/doorkeeper/request/password.rb +2 -0
  83. data/lib/doorkeeper/request/refresh_token.rb +2 -0
  84. data/lib/doorkeeper/request/strategy.rb +2 -0
  85. data/lib/doorkeeper/request/token.rb +2 -0
  86. data/lib/doorkeeper/request.rb +2 -0
  87. data/lib/doorkeeper/server.rb +2 -0
  88. data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
  89. data/lib/doorkeeper/validations.rb +2 -0
  90. data/lib/doorkeeper/version.rb +4 -2
  91. data/lib/doorkeeper.rb +2 -0
  92. data/lib/generators/doorkeeper/templates/initializer.rb +61 -3
  93. data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -3
  94. data/spec/controllers/application_metal_controller_spec.rb +18 -4
  95. data/spec/controllers/applications_controller_spec.rb +37 -41
  96. data/spec/controllers/authorizations_controller_spec.rb +71 -18
  97. data/spec/controllers/protected_resources_controller_spec.rb +44 -2
  98. data/spec/controllers/tokens_controller_spec.rb +11 -16
  99. data/spec/dummy/Rakefile +1 -1
  100. data/spec/dummy/app/controllers/application_controller.rb +1 -1
  101. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +1 -1
  102. data/spec/dummy/app/controllers/home_controller.rb +1 -2
  103. data/spec/dummy/config/application.rb +1 -1
  104. data/spec/dummy/config/boot.rb +2 -4
  105. data/spec/dummy/config/environment.rb +1 -1
  106. data/spec/dummy/config/environments/test.rb +1 -1
  107. data/spec/dummy/config/initializers/doorkeeper.rb +2 -1
  108. data/spec/dummy/config/initializers/new_framework_defaults.rb +1 -3
  109. data/spec/dummy/config/initializers/secret_token.rb +1 -1
  110. data/spec/dummy/config.ru +1 -1
  111. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +4 -4
  112. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
  113. data/spec/dummy/script/rails +4 -3
  114. data/spec/factories.rb +9 -9
  115. data/spec/generators/install_generator_spec.rb +4 -1
  116. data/spec/generators/templates/routes.rb +0 -1
  117. data/spec/generators/views_generator_spec.rb +1 -1
  118. data/spec/grape/grape_integration_spec.rb +1 -1
  119. data/spec/lib/config_spec.rb +109 -8
  120. data/spec/lib/doorkeeper_spec.rb +5 -5
  121. data/spec/lib/models/hashable_spec.rb +183 -0
  122. data/spec/lib/oauth/authorization_code_request_spec.rb +9 -6
  123. data/spec/lib/oauth/base_request_spec.rb +10 -10
  124. data/spec/lib/oauth/client/credentials_spec.rb +2 -2
  125. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -2
  126. data/spec/lib/oauth/client_credentials/validation_spec.rb +5 -1
  127. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  128. data/spec/lib/oauth/code_request_spec.rb +2 -2
  129. data/spec/lib/oauth/code_response_spec.rb +1 -1
  130. data/spec/lib/oauth/helpers/scope_checker_spec.rb +52 -17
  131. data/spec/lib/oauth/helpers/uri_checker_spec.rb +37 -8
  132. data/spec/lib/oauth/password_access_token_request_spec.rb +48 -15
  133. data/spec/lib/oauth/pre_authorization_spec.rb +24 -0
  134. data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
  135. data/spec/lib/oauth/token_request_spec.rb +5 -5
  136. data/spec/lib/oauth/token_response_spec.rb +13 -13
  137. data/spec/lib/oauth/token_spec.rb +18 -1
  138. data/spec/lib/server_spec.rb +6 -6
  139. data/spec/lib/{orm/active_record/stale_records_cleaner_spec.rb → stale_records_cleaner_spec.rb} +14 -4
  140. data/spec/models/doorkeeper/access_grant_spec.rb +61 -0
  141. data/spec/models/doorkeeper/access_token_spec.rb +137 -10
  142. data/spec/models/doorkeeper/application_spec.rb +41 -4
  143. data/spec/requests/applications/applications_request_spec.rb +2 -2
  144. data/spec/requests/endpoints/authorization_spec.rb +2 -2
  145. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
  146. data/spec/requests/flows/authorization_code_spec.rb +115 -15
  147. data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
  148. data/spec/requests/flows/password_spec.rb +10 -4
  149. data/spec/requests/flows/refresh_token_spec.rb +57 -0
  150. data/spec/requests/flows/revoke_token_spec.rb +23 -39
  151. data/spec/requests/protected_resources/private_api_spec.rb +2 -2
  152. data/spec/spec_helper.rb +2 -1
  153. data/spec/support/doorkeeper_rspec.rb +2 -1
  154. data/spec/support/helpers/model_helper.rb +8 -4
  155. data/spec/support/helpers/url_helper.rb +11 -11
  156. data/spec/support/ruby_2_6_rails_4_2_patch.rb +14 -0
  157. data/spec/support/shared/controllers_shared_context.rb +56 -0
  158. data/spec/support/shared/hashing_shared_context.rb +29 -0
  159. data/spec/validators/redirect_uri_validator_spec.rb +2 -2
  160. metadata +31 -8
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  module Authorization
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  module Authorization
@@ -60,7 +62,7 @@ module Doorkeeper
60
62
  {
61
63
  controller: controller,
62
64
  action: :show,
63
- access_token: token.token
65
+ access_token: token.plaintext_token
64
66
  }
65
67
  end
66
68
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rack/utils'
2
4
 
3
5
  module Doorkeeper
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class AuthorizationCodeRequest < BaseRequest
@@ -47,7 +49,7 @@ module Doorkeeper
47
49
  end
48
50
 
49
51
  def validate_client
50
- !client.nil?
52
+ client.present?
51
53
  end
52
54
 
53
55
  def validate_grant
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class BaseRequest
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class BaseResponse
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class Client
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class Client
@@ -16,7 +18,7 @@ module Doorkeeper
16
18
  end
17
19
 
18
20
  def self.authenticate(credentials, method = Application.method(:by_uid_and_secret))
19
- return false if credentials.blank?
21
+ return if credentials.blank?
20
22
 
21
23
  if (application = method.call(credentials.uid, credentials.secret))
22
24
  new(application)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class ClientCredentialsRequest < BaseRequest
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class ClientCredentialsRequest < BaseRequest
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class ClientCredentialsRequest < BaseRequest
@@ -32,9 +34,10 @@ module Doorkeeper
32
34
  end
33
35
 
34
36
  ScopeChecker.valid?(
35
- @request.scopes.to_s,
36
- @server.scopes,
37
- application_scopes
37
+ scope_str: @request.scopes.to_s,
38
+ server_scopes: @server.scopes,
39
+ app_scopes: application_scopes,
40
+ grant_type: Doorkeeper::OAuth::CLIENT_CREDENTIALS
38
41
  )
39
42
  end
40
43
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class ClientCredentialsRequest < BaseRequest
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class CodeRequest
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class CodeResponse < BaseResponse
@@ -21,7 +23,7 @@ module Doorkeeper
21
23
  elsif response_on_fragment
22
24
  Authorization::URIBuilder.uri_with_fragment(
23
25
  pre_auth.redirect_uri,
24
- access_token: auth.token.token,
26
+ access_token: auth.token.plaintext_token,
25
27
  token_type: auth.token.token_type,
26
28
  expires_in: auth.token.expires_in_seconds,
27
29
  state: pre_auth.state
@@ -29,7 +31,7 @@ module Doorkeeper
29
31
  else
30
32
  Authorization::URIBuilder.uri_with_query(
31
33
  pre_auth.redirect_uri,
32
- code: auth.token.token,
34
+ code: auth.token.plaintext_token,
33
35
  state: pre_auth.state
34
36
  )
35
37
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  Error = Struct.new(:name, :state) do
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class ErrorResponse < BaseResponse
@@ -55,6 +57,10 @@ module Doorkeeper
55
57
  }
56
58
  end
57
59
 
60
+ def raise_exception!
61
+ raise exception_class.new(self), description
62
+ end
63
+
58
64
  protected
59
65
 
60
66
  delegate :realm, to: :configuration
@@ -63,6 +69,10 @@ module Doorkeeper
63
69
  Doorkeeper.configuration
64
70
  end
65
71
 
72
+ def exception_class
73
+ raise NotImplementedError, "error response must define #exception_class"
74
+ end
75
+
66
76
  private
67
77
 
68
78
  def authenticate_info
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class ForbiddenTokenResponse < ErrorResponse
@@ -21,8 +23,13 @@ module Doorkeeper
21
23
  end
22
24
 
23
25
  def description
24
- scope = { scope: %i[doorkeeper scopes] }
25
- @description ||= @scopes.map { |r| I18n.translate r, scope }.join('\n')
26
+ @description ||= @scopes.map { |s| I18n.t(s, scope: %i[doorkeeper scopes]) }.join("\n")
27
+ end
28
+
29
+ protected
30
+
31
+ def exception_class
32
+ Doorkeeper::Errors::TokenForbidden
26
33
  end
27
34
  end
28
35
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  module Helpers
@@ -5,31 +7,46 @@ module Doorkeeper
5
7
  class Validator
6
8
  attr_reader :parsed_scopes, :scope_str
7
9
 
8
- def initialize(scope_str, server_scopes, application_scopes)
10
+ def initialize(scope_str, server_scopes, app_scopes, grant_type)
9
11
  @parsed_scopes = OAuth::Scopes.from_string(scope_str)
10
12
  @scope_str = scope_str
11
- @valid_scopes = valid_scopes(server_scopes, application_scopes)
13
+ @valid_scopes = valid_scopes(server_scopes, app_scopes)
14
+
15
+ if grant_type
16
+ @scopes_by_grant_type = Doorkeeper.configuration.scopes_by_grant_type[grant_type.to_sym]
17
+ end
12
18
  end
13
19
 
14
20
  def valid?
15
21
  scope_str.present? &&
16
22
  scope_str !~ /[\n\r\t]/ &&
17
- @valid_scopes.has_scopes?(parsed_scopes)
23
+ @valid_scopes.has_scopes?(parsed_scopes) &&
24
+ permitted_to_grant_type?
18
25
  end
19
26
 
20
27
  private
21
28
 
22
- def valid_scopes(server_scopes, application_scopes)
23
- if application_scopes.present?
24
- application_scopes
29
+ def valid_scopes(server_scopes, app_scopes)
30
+ if app_scopes.present?
31
+ app_scopes
25
32
  else
26
33
  server_scopes
27
34
  end
28
35
  end
36
+
37
+ def permitted_to_grant_type?
38
+ return true unless @scopes_by_grant_type
39
+
40
+ OAuth::Scopes.from_array(@scopes_by_grant_type)
41
+ .has_scopes?(parsed_scopes)
42
+ end
29
43
  end
30
44
 
31
- def self.valid?(scope_str, server_scopes, application_scopes = nil)
32
- Validator.new(scope_str, server_scopes, application_scopes).valid?
45
+ def self.valid?(scope_str:, server_scopes:, app_scopes: nil, grant_type: nil)
46
+ Validator.new(scope_str,
47
+ server_scopes,
48
+ app_scopes,
49
+ grant_type).valid?
33
50
  end
34
51
  end
35
52
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  module Helpers
@@ -1,4 +1,25 @@
1
+ # frozen_string_literal: true
2
+ require 'ipaddr'
3
+
1
4
  module Doorkeeper
5
+ module IPAddrLoopback
6
+ def loopback?
7
+ case @family
8
+ when Socket::AF_INET
9
+ @addr & 0xff000000 == 0x7f000000
10
+ when Socket::AF_INET6
11
+ @addr == 1
12
+ else
13
+ raise AddressFamilyError, "unsupported address family"
14
+ end
15
+ end
16
+ end
17
+
18
+ # For backward compatibility with old rubies
19
+ if Gem::Version.new(RUBY_VERSION) < Gem::Version.new("2.5.0")
20
+ IPAddr.send(:include, Doorkeeper::IPAddrLoopback)
21
+ end
22
+
2
23
  module OAuth
3
24
  module Helpers
4
25
  module URIChecker
@@ -14,16 +35,30 @@ module Doorkeeper
14
35
  url = as_uri(url)
15
36
  client_url = as_uri(client_url)
16
37
 
17
- if client_url.query.present?
38
+ unless client_url.query.nil?
18
39
  return false unless query_matches?(url.query, client_url.query)
19
40
  # Clear out queries so rest of URI can be tested. This allows query
20
41
  # params to be in the request but order not mattering.
21
42
  client_url.query = nil
22
43
  end
44
+
45
+ # RFC8252, Paragraph 7.3
46
+ # @see https://tools.ietf.org/html/rfc8252#section-7.3
47
+ if loopback_uri?(url) && loopback_uri?(client_url)
48
+ url.port = nil
49
+ client_url.port = nil
50
+ end
51
+
23
52
  url.query = nil
24
53
  url == client_url
25
54
  end
26
55
 
56
+ def self.loopback_uri?(uri)
57
+ IPAddr.new(uri.host).loopback?
58
+ rescue IPAddr::Error
59
+ false
60
+ end
61
+
27
62
  def self.valid_for_authorization?(url, client_url)
28
63
  valid?(url) && client_url.split.any? { |other_url| matches?(url, other_url) }
29
64
  end
@@ -33,7 +68,7 @@ module Doorkeeper
33
68
  end
34
69
 
35
70
  def self.query_matches?(query, client_query)
36
- return true if client_query.nil? && query.nil?
71
+ return true if client_query.blank? && query.blank?
37
72
  return false if client_query.nil? || query.nil?
38
73
  # Will return true independent of query order
39
74
  client_query.split('&').sort == query.split('&').sort
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class InvalidTokenResponse < ErrorResponse
@@ -24,6 +26,22 @@ module Doorkeeper
24
26
  scope = { scope: %i[doorkeeper errors messages invalid_token] }
25
27
  @description ||= I18n.translate @reason, scope
26
28
  end
29
+
30
+ protected
31
+
32
+ def exception_class
33
+ errors_mapping.fetch(reason)
34
+ end
35
+
36
+ private
37
+
38
+ def errors_mapping
39
+ {
40
+ expired: Doorkeeper::Errors::TokenExpired,
41
+ revoked: Doorkeeper::Errors::TokenRevoked,
42
+ unknown: Doorkeeper::Errors::TokenUnknown
43
+ }
44
+ end
27
45
  end
28
46
  end
29
47
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class PasswordAccessTokenRequest < BaseRequest
@@ -30,7 +32,12 @@ module Doorkeeper
30
32
  client_scopes = client.try(:scopes)
31
33
  return true if scopes.blank?
32
34
 
33
- ScopeChecker.valid?(scopes.to_s, server.scopes, client_scopes)
35
+ ScopeChecker.valid?(
36
+ scope_str: scopes.to_s,
37
+ server_scopes: server.scopes,
38
+ app_scopes: client_scopes,
39
+ grant_type: grant_type
40
+ )
34
41
  end
35
42
 
36
43
  def validate_resource_owner
@@ -38,7 +45,7 @@ module Doorkeeper
38
45
  end
39
46
 
40
47
  def validate_client
41
- !parameters[:client_id] || !client.nil?
48
+ !parameters[:client_id] || client.present?
42
49
  end
43
50
  end
44
51
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class PreAuthorization
@@ -75,12 +77,17 @@ module Doorkeeper
75
77
  return true if scope.blank?
76
78
 
77
79
  Helpers::ScopeChecker.valid?(
78
- scope,
79
- server.scopes,
80
- client.application.scopes
80
+ scope_str: scope,
81
+ server_scopes: server.scopes,
82
+ app_scopes: client.application.scopes,
83
+ grant_type: grant_type
81
84
  )
82
85
  end
83
86
 
87
+ def grant_type
88
+ response_type == 'code' ? AUTHORIZATION_CODE : IMPLICIT
89
+ end
90
+
84
91
  def validate_redirect_uri
85
92
  return false if redirect_uri.blank?
86
93
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class RefreshTokenRequest < BaseRequest
@@ -82,16 +84,25 @@ module Doorkeeper
82
84
  end
83
85
 
84
86
  def validate_client
85
- !credentials || !!client
87
+ return true if credentials.blank?
88
+
89
+ client.present?
86
90
  end
87
91
 
92
+ # @see https://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-1.5
93
+ #
88
94
  def validate_client_match
89
- !client || refresh_token.application_id == client.id
95
+ return true if refresh_token.application_id.blank?
96
+
97
+ client && refresh_token.application_id == client.id
90
98
  end
91
99
 
92
100
  def validate_scope
93
101
  if @original_scopes.present?
94
- ScopeChecker.valid?(@original_scopes, refresh_token.scopes)
102
+ ScopeChecker.valid?(
103
+ scope_str: @original_scopes,
104
+ server_scopes: refresh_token.scopes
105
+ )
95
106
  else
96
107
  true
97
108
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class Scopes
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class Token
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  # RFC7662 OAuth 2.0 Token Introspection
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class TokenRequest
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  class TokenResponse
@@ -9,10 +11,10 @@ module Doorkeeper
9
11
 
10
12
  def body
11
13
  {
12
- 'access_token' => token.token,
14
+ 'access_token' => token.plaintext_token,
13
15
  'token_type' => token.token_type,
14
16
  'expires_in' => token.expires_in_seconds,
15
- 'refresh_token' => token.refresh_token,
17
+ 'refresh_token' => token.plaintext_refresh_token,
16
18
  'scope' => token.scopes_string,
17
19
  'created_at' => token.created_at.to_i
18
20
  }.reject { |_, value| value.blank? }
@@ -16,11 +16,30 @@ module Doorkeeper
16
16
 
17
17
  belongs_to :application, belongs_to_options
18
18
 
19
- validates :resource_owner_id, :application_id, :token, :expires_in, :redirect_uri, presence: true
19
+ validates :resource_owner_id,
20
+ :application_id,
21
+ :token,
22
+ :expires_in,
23
+ :redirect_uri,
24
+ presence: true
25
+
20
26
  validates :token, uniqueness: true
21
27
 
22
28
  before_validation :generate_token, on: :create
23
29
 
30
+ # Keep a reference to the generated token during generation
31
+ # of this access grant. The actual token may be mapped by
32
+ # the configuration hasher and may not be available in plaintext.
33
+ #
34
+ # If hash tokens are enabled, this will return nil on fetched tokens
35
+ def plaintext_token
36
+ if perform_secret_hashing?
37
+ @raw_token
38
+ else
39
+ token
40
+ end
41
+ end
42
+
24
43
  private
25
44
 
26
45
  # Generates token value with UniqueToken class.
@@ -28,7 +47,8 @@ module Doorkeeper
28
47
  # @return [String] token value
29
48
  #
30
49
  def generate_token
31
- self.token = UniqueToken.generate
50
+ @raw_token = UniqueToken.generate
51
+ self.token = hashed_or_plain_token(@raw_token)
32
52
  end
33
53
  end
34
54
  end
@@ -45,6 +45,16 @@ module Doorkeeper
45
45
  AccessGrant.revoke_all_for(id, resource_owner)
46
46
  end
47
47
 
48
+ # We keep a volatile copy of the raw client_secret for initial communication
49
+ # The stored secret may be mapped and not available in cleartext.
50
+ def plaintext_secret
51
+ if perform_secret_hashing?
52
+ @raw_secret
53
+ else
54
+ secret
55
+ end
56
+ end
57
+
48
58
  private
49
59
 
50
60
  def generate_uid
@@ -52,12 +62,16 @@ module Doorkeeper
52
62
  end
53
63
 
54
64
  def generate_secret
55
- self.secret = UniqueToken.generate if secret.blank?
65
+ return unless secret.blank?
66
+
67
+ @raw_secret = UniqueToken.generate
68
+ self.secret = hashed_or_plain_token(@raw_secret)
56
69
  end
57
70
 
58
71
  def scopes_match_configured
59
72
  if scopes.present? &&
60
- !ScopeChecker.valid?(scopes.to_s, Doorkeeper.configuration.scopes)
73
+ !ScopeChecker.valid?(scope_str: scopes.to_s,
74
+ server_scopes: Doorkeeper.configuration.scopes)
61
75
  errors.add(:scopes, :not_match_configured)
62
76
  end
63
77
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'active_support/lazy_load_hooks'
2
4
 
3
5
  require 'doorkeeper/orm/active_record/stale_records_cleaner'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Rails
3
5
  module Helpers
@@ -19,6 +21,8 @@ module Doorkeeper
19
21
 
20
22
  def doorkeeper_render_error
21
23
  error = doorkeeper_error
24
+ error.raise_exception! if Doorkeeper.configuration.raise_on_errors?
25
+
22
26
  headers.merge!(error.headers.reject { |k| k == "Content-Type" })
23
27
  doorkeeper_render_error_with(error)
24
28
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Rails
3
5
  class Routes # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Rails
3
5
  class Routes # :nodoc:
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'doorkeeper/rails/routes/mapping'
2
4
  require 'doorkeeper/rails/routes/mapper'
3
5
 
@@ -91,11 +93,16 @@ module Doorkeeper
91
93
  end
92
94
 
93
95
  def application_routes(mapping)
94
- routes.resources :doorkeeper_applications, controller: mapping[:controllers], as: :applications, path: 'applications'
96
+ routes.resources :doorkeeper_applications,
97
+ controller: mapping[:controllers],
98
+ as: :applications,
99
+ path: 'applications'
95
100
  end
96
101
 
97
102
  def authorized_applications_routes(mapping)
98
- routes.resources :authorized_applications, only: %i[index destroy], controller: mapping[:controllers]
103
+ routes.resources :authorized_applications,
104
+ only: %i[index destroy],
105
+ controller: mapping[:controllers]
99
106
  end
100
107
  end
101
108
  end