doorkeeper 3.1.0 → 4.4.3

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.

Files changed (195) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.github/ISSUE_TEMPLATE.md +25 -0
  4. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  5. data/.gitignore +6 -1
  6. data/.hound.yml +2 -13
  7. data/.rubocop.yml +17 -0
  8. data/.travis.yml +26 -10
  9. data/Appraisals +18 -0
  10. data/CODE_OF_CONDUCT.md +46 -0
  11. data/CONTRIBUTING.md +2 -0
  12. data/Gemfile +5 -5
  13. data/NEWS.md +141 -2
  14. data/README.md +149 -66
  15. data/RELEASING.md +5 -12
  16. data/Rakefile +1 -1
  17. data/SECURITY.md +15 -0
  18. data/app/controllers/doorkeeper/application_controller.rb +4 -6
  19. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  20. data/app/controllers/doorkeeper/applications_controller.rb +18 -8
  21. data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
  22. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  23. data/app/controllers/doorkeeper/tokens_controller.rb +62 -15
  24. data/app/helpers/doorkeeper/dashboard_helper.rb +14 -10
  25. data/app/validators/redirect_uri_validator.rb +12 -2
  26. data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
  27. data/app/views/doorkeeper/applications/_form.html.erb +13 -2
  28. data/app/views/doorkeeper/applications/index.html.erb +2 -0
  29. data/app/views/doorkeeper/applications/show.html.erb +4 -1
  30. data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
  31. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  32. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  33. data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
  34. data/config/locales/en.yml +12 -7
  35. data/doorkeeper.gemspec +16 -11
  36. data/gemfiles/rails_4_2.gemfile +13 -0
  37. data/gemfiles/rails_5_0.gemfile +12 -0
  38. data/gemfiles/rails_5_1.gemfile +12 -0
  39. data/gemfiles/rails_5_2.gemfile +12 -0
  40. data/gemfiles/rails_master.gemfile +14 -0
  41. data/lib/doorkeeper/config.rb +119 -46
  42. data/lib/doorkeeper/engine.rb +11 -7
  43. data/lib/doorkeeper/errors.rb +18 -0
  44. data/lib/doorkeeper/grape/helpers.rb +14 -8
  45. data/lib/doorkeeper/helpers/controller.rb +8 -19
  46. data/lib/doorkeeper/models/access_grant_mixin.rb +10 -21
  47. data/lib/doorkeeper/models/access_token_mixin.rb +147 -43
  48. data/lib/doorkeeper/models/application_mixin.rb +33 -35
  49. data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
  50. data/lib/doorkeeper/models/concerns/expirable.rb +15 -5
  51. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  52. data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
  53. data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
  54. data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
  55. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
  56. data/lib/doorkeeper/oauth/authorization_code_request.rb +7 -5
  57. data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +9 -2
  58. data/lib/doorkeeper/oauth/base_response.rb +29 -0
  59. data/lib/doorkeeper/oauth/client/credentials.rb +21 -8
  60. data/lib/doorkeeper/oauth/client.rb +2 -3
  61. data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
  62. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  63. data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
  64. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
  65. data/lib/doorkeeper/oauth/code_response.rb +16 -16
  66. data/lib/doorkeeper/oauth/error.rb +2 -2
  67. data/lib/doorkeeper/oauth/error_response.rb +10 -10
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +17 -1
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -4
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -13
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +5 -3
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +23 -14
  75. data/lib/doorkeeper/oauth/scopes.rb +18 -8
  76. data/lib/doorkeeper/oauth/token.rb +20 -21
  77. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  78. data/lib/doorkeeper/oauth/token_request.rb +1 -2
  79. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +34 -8
  82. data/lib/doorkeeper/orm/active_record/application.rb +48 -11
  83. data/lib/doorkeeper/orm/active_record.rb +17 -22
  84. data/lib/doorkeeper/rails/helpers.rb +6 -9
  85. data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
  86. data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
  87. data/lib/doorkeeper/rails/routes.rb +17 -11
  88. data/lib/doorkeeper/request/authorization_code.rb +7 -1
  89. data/lib/doorkeeper/request/password.rb +2 -2
  90. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  91. data/lib/doorkeeper/request.rb +7 -1
  92. data/lib/doorkeeper/server.rb +0 -8
  93. data/lib/doorkeeper/validations.rb +3 -2
  94. data/lib/doorkeeper/version.rb +34 -1
  95. data/lib/doorkeeper.rb +10 -2
  96. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +31 -0
  97. data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
  98. data/lib/generators/doorkeeper/migration_generator.rb +13 -1
  99. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +35 -0
  100. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +11 -0
  101. data/{spec/dummy/db/migrate/20130902175349_add_owner_to_application.rb → lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb} +1 -1
  102. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +11 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +38 -6
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +69 -0
  105. data/spec/controllers/application_metal_controller.rb +10 -0
  106. data/spec/controllers/applications_controller_spec.rb +15 -4
  107. data/spec/controllers/authorizations_controller_spec.rb +74 -27
  108. data/spec/controllers/protected_resources_controller_spec.rb +70 -32
  109. data/spec/controllers/token_info_controller_spec.rb +17 -13
  110. data/spec/controllers/tokens_controller_spec.rb +198 -12
  111. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
  112. data/spec/dummy/app/controllers/home_controller.rb +1 -1
  113. data/spec/dummy/app/controllers/metal_controller.rb +1 -1
  114. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
  115. data/spec/dummy/app/models/user.rb +0 -4
  116. data/spec/dummy/config/application.rb +2 -36
  117. data/spec/dummy/config/environment.rb +1 -1
  118. data/spec/dummy/config/environments/test.rb +4 -15
  119. data/spec/dummy/config/initializers/doorkeeper.rb +19 -3
  120. data/spec/dummy/config/initializers/new_framework_defaults.rb +6 -0
  121. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  122. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  123. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  124. data/{lib/generators/doorkeeper/templates/migration.rb → spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb} +16 -4
  125. data/{lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb → spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb} +4 -2
  126. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +13 -0
  127. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb +13 -0
  128. data/spec/dummy/db/schema.rb +24 -22
  129. data/spec/factories.rb +4 -2
  130. data/spec/generators/application_owner_generator_spec.rb +24 -5
  131. data/spec/generators/migration_generator_spec.rb +24 -3
  132. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  133. data/spec/grape/grape_integration_spec.rb +135 -0
  134. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  135. data/spec/lib/config_spec.rb +159 -14
  136. data/spec/lib/doorkeeper_spec.rb +135 -13
  137. data/spec/lib/models/expirable_spec.rb +0 -1
  138. data/spec/lib/models/revocable_spec.rb +27 -4
  139. data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
  140. data/spec/lib/oauth/authorization_code_request_spec.rb +55 -12
  141. data/spec/lib/oauth/base_request_spec.rb +155 -0
  142. data/spec/lib/oauth/base_response_spec.rb +45 -0
  143. data/spec/lib/oauth/client/credentials_spec.rb +45 -2
  144. data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
  145. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  146. data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
  147. data/spec/lib/oauth/code_request_spec.rb +1 -3
  148. data/spec/lib/oauth/code_response_spec.rb +34 -0
  149. data/spec/lib/oauth/error_response_spec.rb +9 -9
  150. data/spec/lib/oauth/error_spec.rb +1 -1
  151. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -1
  152. data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
  153. data/spec/lib/oauth/password_access_token_request_spec.rb +14 -8
  154. data/spec/lib/oauth/pre_authorization_spec.rb +12 -7
  155. data/spec/lib/oauth/refresh_token_request_spec.rb +52 -9
  156. data/spec/lib/oauth/scopes_spec.rb +28 -2
  157. data/spec/lib/oauth/token_request_spec.rb +6 -8
  158. data/spec/lib/oauth/token_spec.rb +12 -5
  159. data/spec/lib/server_spec.rb +10 -3
  160. data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
  161. data/spec/models/doorkeeper/access_token_spec.rb +116 -48
  162. data/spec/models/doorkeeper/application_spec.rb +145 -29
  163. data/spec/requests/applications/applications_request_spec.rb +5 -5
  164. data/spec/requests/endpoints/authorization_spec.rb +5 -6
  165. data/spec/requests/endpoints/token_spec.rb +8 -1
  166. data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
  167. data/spec/requests/flows/authorization_code_spec.rb +6 -13
  168. data/spec/requests/flows/client_credentials_spec.rb +29 -1
  169. data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
  170. data/spec/requests/flows/password_spec.rb +118 -15
  171. data/spec/requests/flows/refresh_token_spec.rb +89 -19
  172. data/spec/requests/flows/revoke_token_spec.rb +105 -91
  173. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  174. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  175. data/spec/routing/custom_controller_routes_spec.rb +4 -0
  176. data/spec/routing/default_routes_spec.rb +5 -1
  177. data/spec/spec_helper.rb +2 -0
  178. data/spec/spec_helper_integration.rb +22 -4
  179. data/spec/support/dependencies/factory_girl.rb +2 -2
  180. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  181. data/spec/support/helpers/model_helper.rb +34 -7
  182. data/spec/support/helpers/request_spec_helper.rb +17 -5
  183. data/spec/support/helpers/url_helper.rb +9 -8
  184. data/spec/support/http_method_shim.rb +38 -0
  185. data/spec/support/shared/controllers_shared_context.rb +15 -10
  186. data/spec/support/shared/models_shared_examples.rb +5 -5
  187. data/spec/validators/redirect_uri_validator_spec.rb +51 -6
  188. data/spec/version/version_spec.rb +15 -0
  189. metadata +128 -46
  190. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  191. data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
  192. data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
  193. data/spec/dummy/db/migrate/20130902165751_create_doorkeeper_tables.rb +0 -41
  194. data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
  195. data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -1,12 +1,47 @@
1
1
  module Doorkeeper
2
2
  module Models
3
3
  module Revocable
4
+ # Revokes the object (updates `:revoked_at` attribute setting its value
5
+ # to the specific time).
6
+ #
7
+ # @param clock [Time] time object
8
+ #
4
9
  def revoke(clock = Time)
5
- update_attribute :revoked_at, clock.now
10
+ update_attribute :revoked_at, clock.now.utc
6
11
  end
7
12
 
13
+ # Indicates whether the object has been revoked.
14
+ #
15
+ # @return [Boolean] true if revoked, false in other case
16
+ #
8
17
  def revoked?
9
- !!(revoked_at && revoked_at <= Time.now)
18
+ !!(revoked_at && revoked_at <= Time.now.utc)
19
+ end
20
+
21
+ # Revokes token with `:refresh_token` equal to `:previous_refresh_token`
22
+ # and clears `:previous_refresh_token` attribute.
23
+ #
24
+ def revoke_previous_refresh_token!
25
+ return unless refresh_token_revoked_on_use?
26
+ old_refresh_token.revoke if old_refresh_token
27
+ update_attribute :previous_refresh_token, ""
28
+ end
29
+
30
+ private
31
+
32
+ # Searches for Access Token record with `:refresh_token` equal to
33
+ # `:previous_refresh_token` value.
34
+ #
35
+ # @return [Doorkeeper::AccessToken, nil]
36
+ # Access Token record or nil if nothing found
37
+ #
38
+ def old_refresh_token
39
+ @old_refresh_token ||=
40
+ AccessToken.by_refresh_token(previous_refresh_token)
41
+ end
42
+
43
+ def refresh_token_revoked_on_use?
44
+ AccessToken.refresh_token_revoked_on_use?
10
45
  end
11
46
  end
12
47
  end
@@ -4,19 +4,33 @@ module Doorkeeper
4
4
  class Token
5
5
  attr_accessor :pre_auth, :resource_owner, :token
6
6
 
7
+ class << self
8
+ def access_token_expires_in(server, pre_auth_or_oauth_client)
9
+ if (expiration = custom_expiration(server, pre_auth_or_oauth_client))
10
+ expiration
11
+ else
12
+ server.access_token_expires_in
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def custom_expiration(server, pre_auth_or_oauth_client)
19
+ oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
20
+ pre_auth_or_oauth_client.client
21
+ else
22
+ pre_auth_or_oauth_client
23
+ end
24
+
25
+ server.custom_access_token_expires_in.call(oauth_client)
26
+ end
27
+ end
28
+
7
29
  def initialize(pre_auth, resource_owner)
8
30
  @pre_auth = pre_auth
9
31
  @resource_owner = resource_owner
10
32
  end
11
33
 
12
- def self.access_token_expires_in(server, pre_auth_or_oauth_client)
13
- if expiration = custom_expiration(server, pre_auth_or_oauth_client)
14
- expiration
15
- else
16
- server.access_token_expires_in
17
- end
18
- end
19
-
20
34
  def issue_token
21
35
  @token ||= AccessToken.find_or_create_for(
22
36
  pre_auth.client,
@@ -37,16 +51,6 @@ module Doorkeeper
37
51
 
38
52
  private
39
53
 
40
- def self.custom_expiration(server, pre_auth_or_oauth_client)
41
- oauth_client = if pre_auth_or_oauth_client.respond_to?(:client)
42
- pre_auth_or_oauth_client.client
43
- else
44
- pre_auth_or_oauth_client
45
- end
46
-
47
- server.custom_access_token_expires_in.call(oauth_client)
48
- end
49
-
50
54
  def configuration
51
55
  Doorkeeper.configuration
52
56
  end
@@ -1,27 +1,29 @@
1
+ require 'rack/utils'
2
+
1
3
  module Doorkeeper
2
4
  module OAuth
3
5
  module Authorization
4
- module URIBuilder
5
- include Rack::Utils
6
-
7
- extend self
6
+ class URIBuilder
7
+ class << self
8
+ def uri_with_query(url, parameters = {})
9
+ uri = URI.parse(url)
10
+ original_query = Rack::Utils.parse_query(uri.query)
11
+ uri.query = build_query(original_query.merge(parameters))
12
+ uri.to_s
13
+ end
8
14
 
9
- def uri_with_query(url, parameters = {})
10
- uri = URI.parse(url)
11
- original_query = parse_query(uri.query)
12
- uri.query = build_query(original_query.merge(parameters))
13
- uri.to_s
14
- end
15
+ def uri_with_fragment(url, parameters = {})
16
+ uri = URI.parse(url)
17
+ uri.fragment = build_query(parameters)
18
+ uri.to_s
19
+ end
15
20
 
16
- def uri_with_fragment(url, parameters = {})
17
- uri = URI.parse(url)
18
- uri.fragment = build_query(parameters)
19
- uri.to_s
20
- end
21
+ private
21
22
 
22
- def build_query(parameters = {})
23
- parameters = parameters.reject { |k, v| v.blank? }
24
- super parameters
23
+ def build_query(parameters = {})
24
+ parameters = parameters.reject { |_, v| v.blank? }
25
+ Rack::Utils.build_query parameters
26
+ end
25
27
  end
26
28
  end
27
29
  end
@@ -1,12 +1,10 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
- class AuthorizationCodeRequest
4
- include Validations
5
- include OAuth::RequestConcern
6
-
3
+ class AuthorizationCodeRequest < BaseRequest
7
4
  validate :attributes, error: :invalid_request
8
5
  validate :client, error: :invalid_client
9
6
  validate :grant, error: :invalid_grant
7
+ # @see https://tools.ietf.org/html/rfc6749#section-5.2
10
8
  validate :redirect_uri, error: :invalid_grant
11
9
 
12
10
  attr_accessor :server, :grant, :client, :redirect_uri, :access_token
@@ -31,6 +29,7 @@ module Doorkeeper
31
29
  grant.scopes,
32
30
  server)
33
31
  end
32
+ super
34
33
  end
35
34
 
36
35
  def validate_attributes
@@ -47,7 +46,10 @@ module Doorkeeper
47
46
  end
48
47
 
49
48
  def validate_redirect_uri
50
- grant.redirect_uri == redirect_uri
49
+ Helpers::URIChecker.valid_for_authorization?(
50
+ redirect_uri,
51
+ grant.redirect_uri
52
+ )
51
53
  end
52
54
  end
53
55
  end
@@ -1,8 +1,11 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
- module RequestConcern
3
+ class BaseRequest
4
+ include Validations
5
+
4
6
  def authorize
5
7
  validate
8
+
6
9
  if valid?
7
10
  before_successful_response
8
11
  @response = TokenResponse.new(access_token)
@@ -35,13 +38,17 @@ module Doorkeeper
35
38
  resource_owner_id,
36
39
  scopes,
37
40
  Authorization::Token.access_token_expires_in(server, client),
38
- server.refresh_token_enabled?)
41
+ server.refresh_token_enabled?
42
+ )
39
43
  end
40
44
 
41
45
  def before_successful_response
46
+ Doorkeeper.configuration.before_successful_strategy_response.call(self)
42
47
  end
43
48
 
44
49
  def after_successful_response
50
+ Doorkeeper.configuration.after_successful_strategy_response.
51
+ call(self, @response)
45
52
  end
46
53
  end
47
54
  end
@@ -0,0 +1,29 @@
1
+ module Doorkeeper
2
+ module OAuth
3
+ class BaseResponse
4
+ def body
5
+ {}
6
+ end
7
+
8
+ def description
9
+ ""
10
+ end
11
+
12
+ def headers
13
+ {}
14
+ end
15
+
16
+ def redirectable?
17
+ false
18
+ end
19
+
20
+ def redirect_uri
21
+ ""
22
+ end
23
+
24
+ def status
25
+ :ok
26
+ end
27
+ end
28
+ end
29
+ end
@@ -1,19 +1,32 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
3
  class Client
4
- class Credentials < Struct.new(:uid, :secret)
5
- extend Methods
4
+ Credentials = Struct.new(:uid, :secret) do
5
+ class << self
6
+ def from_request(request, *credentials_methods)
7
+ credentials_methods.inject(nil) do |credentials, method|
8
+ method = self.method(method) if method.is_a?(Symbol)
9
+ credentials = Credentials.new(*method.call(request))
10
+ break credentials unless credentials.blank?
11
+ end
12
+ end
13
+
14
+ def from_params(request)
15
+ request.parameters.values_at(:client_id, :client_secret)
16
+ end
6
17
 
7
- def self.from_request(request, *credentials_methods)
8
- credentials_methods.inject(nil) do |credentials, method|
9
- method = self.method(method) if method.is_a?(Symbol)
10
- credentials = Credentials.new *method.call(request)
11
- break credentials unless credentials.blank?
18
+ def from_basic(request)
19
+ authorization = request.authorization
20
+ if authorization.present? && authorization =~ /^Basic (.*)/m
21
+ Base64.decode64(Regexp.last_match(1)).split(/:/, 2)
22
+ end
12
23
  end
13
24
  end
14
25
 
26
+ # Public clients may have their secret blank, but "credentials" are
27
+ # still present
15
28
  def blank?
16
- uid.blank? || secret.blank?
29
+ uid.blank?
17
30
  end
18
31
  end
19
32
  end
@@ -1,4 +1,3 @@
1
- require 'doorkeeper/oauth/client/methods'
2
1
  require 'doorkeeper/oauth/client/credentials'
3
2
 
4
3
  module Doorkeeper
@@ -13,7 +12,7 @@ module Doorkeeper
13
12
  end
14
13
 
15
14
  def self.find(uid, method = Application.method(:by_uid))
16
- if application = method.call(uid)
15
+ if (application = method.call(uid))
17
16
  new(application)
18
17
  end
19
18
  end
@@ -21,7 +20,7 @@ module Doorkeeper
21
20
  def self.authenticate(credentials, method = Application.method(:by_uid_and_secret))
22
21
  return false if credentials.blank?
23
22
 
24
- if application = method.call(credentials.uid, credentials.secret)
23
+ if (application = method.call(credentials.uid, credentials.secret))
25
24
  new(application)
26
25
  end
27
26
  end
@@ -1,6 +1,6 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
- class ClientCredentialsRequest
3
+ class ClientCredentialsRequest < BaseRequest
4
4
  class Creator
5
5
  def call(client, scopes, attributes = {})
6
6
  AccessToken.find_or_create_for(
@@ -2,12 +2,13 @@ require 'doorkeeper/oauth/client_credentials/validation'
2
2
 
3
3
  module Doorkeeper
4
4
  module OAuth
5
- class ClientCredentialsRequest
5
+ class ClientCredentialsRequest < BaseRequest
6
6
  class Issuer
7
7
  attr_accessor :token, :validation, :error
8
8
 
9
9
  def initialize(server, validation)
10
- @server, @validation = server, validation
10
+ @server = server
11
+ @validation = validation
11
12
  end
12
13
 
13
14
  def create(client, scopes, creator = Creator.new)
@@ -4,7 +4,7 @@ require 'doorkeeper/oauth/helpers/scope_checker'
4
4
 
5
5
  module Doorkeeper
6
6
  module OAuth
7
- class ClientCredentialsRequest
7
+ class ClientCredentialsRequest < BaseRequest
8
8
  class Validation
9
9
  include Validations
10
10
  include OAuth::Helpers
@@ -4,13 +4,12 @@ require 'doorkeeper/oauth/client_credentials/validation'
4
4
 
5
5
  module Doorkeeper
6
6
  module OAuth
7
- class ClientCredentialsRequest
8
- include Validations
9
- include OAuth::RequestConcern
10
-
11
- attr_accessor :issuer, :server, :client, :original_scopes
7
+ class ClientCredentialsRequest < BaseRequest
8
+ attr_accessor :server, :client, :original_scopes
12
9
  attr_reader :response
13
- alias :error_response :response
10
+ attr_writer :issuer
11
+
12
+ alias_method :error_response, :response
14
13
 
15
14
  delegate :error, to: :issuer
16
15
 
@@ -19,8 +18,9 @@ module Doorkeeper
19
18
  end
20
19
 
21
20
  def initialize(server, client, parameters = {})
22
- @client, @server = client, server
23
- @response = nil
21
+ @client = client
22
+ @server = server
23
+ @response = nil
24
24
  @original_scopes = parameters[:scope]
25
25
  end
26
26
 
@@ -1,13 +1,13 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
- class CodeResponse
4
- include OAuth::Authorization::URIBuilder
3
+ class CodeResponse < BaseResponse
5
4
  include OAuth::Helpers
6
5
 
7
6
  attr_accessor :pre_auth, :auth, :response_on_fragment
8
7
 
9
8
  def initialize(pre_auth, auth, options = {})
10
- @pre_auth, @auth = pre_auth, auth
9
+ @pre_auth = pre_auth
10
+ @auth = auth
11
11
  @response_on_fragment = options[:response_on_fragment]
12
12
  end
13
13
 
@@ -18,20 +18,20 @@ module Doorkeeper
18
18
  def redirect_uri
19
19
  if URIChecker.native_uri? pre_auth.redirect_uri
20
20
  auth.native_redirect
21
+ elsif response_on_fragment
22
+ Authorization::URIBuilder.uri_with_fragment(
23
+ pre_auth.redirect_uri,
24
+ access_token: auth.token.token,
25
+ token_type: auth.token.token_type,
26
+ expires_in: auth.token.expires_in_seconds,
27
+ state: pre_auth.state
28
+ )
21
29
  else
22
- if response_on_fragment
23
- uri_with_fragment(
24
- pre_auth.redirect_uri,
25
- access_token: auth.token.token,
26
- token_type: auth.token.token_type,
27
- expires_in: auth.token.expires_in,
28
- state: pre_auth.state
29
- )
30
- else
31
- uri_with_query pre_auth.redirect_uri,
32
- code: auth.token.token,
33
- state: pre_auth.state
34
- end
30
+ Authorization::URIBuilder.uri_with_query(
31
+ pre_auth.redirect_uri,
32
+ code: auth.token.token,
33
+ state: pre_auth.state
34
+ )
35
35
  end
36
36
  end
37
37
  end
@@ -1,10 +1,10 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
- class Error < Struct.new(:name, :state)
3
+ Error = Struct.new(:name, :state) do
4
4
  def description
5
5
  I18n.translate(
6
6
  name,
7
- scope: [:doorkeeper, :errors, :messages],
7
+ scope: %i[doorkeeper errors messages],
8
8
  default: :server_error
9
9
  )
10
10
  end
@@ -1,12 +1,10 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
- class ErrorResponse
4
- include OAuth::Authorization::URIBuilder
3
+ class ErrorResponse < BaseResponse
5
4
  include OAuth::Helpers
6
5
 
7
6
  def self.from_request(request, attributes = {})
8
- state = request.state if request.respond_to?(:state)
9
- new(attributes.merge(name: request.error, state: state))
7
+ new(attributes.merge(name: request.error, state: request.try(:state)))
10
8
  end
11
9
 
12
10
  delegate :name, :description, :state, to: :@error
@@ -36,16 +34,12 @@ module Doorkeeper
36
34
 
37
35
  def redirect_uri
38
36
  if @response_on_fragment
39
- uri_with_fragment @redirect_uri, body
37
+ Authorization::URIBuilder.uri_with_fragment @redirect_uri, body
40
38
  else
41
- uri_with_query @redirect_uri, body
39
+ Authorization::URIBuilder.uri_with_query @redirect_uri, body
42
40
  end
43
41
  end
44
42
 
45
- def authenticate_info
46
- %(Bearer realm="#{realm}", error="#{name}", error_description="#{description}")
47
- end
48
-
49
43
  def headers
50
44
  { 'Cache-Control' => 'no-store',
51
45
  'Pragma' => 'no-cache',
@@ -60,6 +54,12 @@ module Doorkeeper
60
54
  def configuration
61
55
  Doorkeeper.configuration
62
56
  end
57
+
58
+ private
59
+
60
+ def authenticate_info
61
+ %(Bearer realm="#{realm}", error="#{name}", error_description="#{description}")
62
+ end
63
63
  end
64
64
  end
65
65
  end
@@ -21,7 +21,7 @@ module Doorkeeper
21
21
  end
22
22
 
23
23
  def description
24
- scope = { scope: [:doorkeeper, :scopes] }
24
+ scope = { scope: %i[doorkeeper scopes] }
25
25
  @description ||= @scopes.map { |r| I18n.translate r, scope }.join('\n')
26
26
  end
27
27
  end
@@ -13,7 +13,7 @@ module Doorkeeper
13
13
 
14
14
  def valid?
15
15
  scope_str.present? &&
16
- scope_str !~ /[\n|\r|\t]/ &&
16
+ scope_str !~ /[\n\r\t]/ &&
17
17
  @valid_scopes.has_scopes?(parsed_scopes)
18
18
  end
19
19
 
@@ -3,6 +3,7 @@ module Doorkeeper
3
3
  module Helpers
4
4
  module URIChecker
5
5
  def self.valid?(url)
6
+ return true if native_uri?(url)
6
7
  uri = as_uri(url)
7
8
  uri.fragment.nil? && !uri.host.nil? && !uri.scheme.nil?
8
9
  rescue URI::InvalidURIError
@@ -10,7 +11,15 @@ module Doorkeeper
10
11
  end
11
12
 
12
13
  def self.matches?(url, client_url)
13
- url, client_url = as_uri(url), as_uri(client_url)
14
+ url = as_uri(url)
15
+ client_url = as_uri(client_url)
16
+
17
+ if client_url.query.present?
18
+ return false unless query_matches?(url.query, client_url.query)
19
+ # Clear out queries so rest of URI can be tested. This allows query
20
+ # params to be in the request but order not mattering.
21
+ client_url.query = nil
22
+ end
14
23
  url.query = nil
15
24
  url == client_url
16
25
  end
@@ -23,6 +32,13 @@ module Doorkeeper
23
32
  URI.parse(url)
24
33
  end
25
34
 
35
+ def self.query_matches?(query, client_query)
36
+ return true if client_query.nil? && query.nil?
37
+ return false if client_query.nil? || query.nil?
38
+ # Will return true independent of query order
39
+ client_query.split('&').sort == query.split('&').sort
40
+ end
41
+
26
42
  def self.native_uri?(url)
27
43
  url == Doorkeeper.configuration.native_redirect_uri
28
44
  end
@@ -1,11 +1,12 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
3
  class InvalidTokenResponse < ErrorResponse
4
+ attr_reader :reason
5
+
4
6
  def self.from_access_token(access_token, attributes = {})
5
- reason = case
6
- when access_token.try(:revoked?)
7
+ reason = if access_token.try(:revoked?)
7
8
  :revoked
8
- when access_token.try(:expired?)
9
+ elsif access_token.try(:expired?)
9
10
  :expired
10
11
  else
11
12
  :unknown
@@ -20,7 +21,7 @@ module Doorkeeper
20
21
  end
21
22
 
22
23
  def description
23
- scope = { scope: [:doorkeeper, :errors, :messages, :invalid_token] }
24
+ scope = { scope: %i[doorkeeper errors messages invalid_token] }
24
25
  @description ||= I18n.translate @reason, scope
25
26
  end
26
27
  end
@@ -1,33 +1,28 @@
1
1
  module Doorkeeper
2
2
  module OAuth
3
- class PasswordAccessTokenRequest
4
- include Validations
5
- include OAuth::RequestConcern
3
+ class PasswordAccessTokenRequest < BaseRequest
6
4
  include OAuth::Helpers
7
5
 
8
6
  validate :client, error: :invalid_client
9
7
  validate :resource_owner, error: :invalid_grant
10
8
  validate :scopes, error: :invalid_scope
11
9
 
12
- attr_accessor :server, :resource_owner, :credentials, :access_token
13
- attr_accessor :client
10
+ attr_accessor :server, :client, :resource_owner, :parameters,
11
+ :access_token
14
12
 
15
- def initialize(server, credentials, resource_owner, parameters = {})
13
+ def initialize(server, client, resource_owner, parameters = {})
16
14
  @server = server
17
15
  @resource_owner = resource_owner
18
- @credentials = credentials
16
+ @client = client
17
+ @parameters = parameters
19
18
  @original_scopes = parameters[:scope]
20
-
21
- if credentials
22
- @client = Application.by_uid_and_secret credentials.uid,
23
- credentials.secret
24
- end
25
19
  end
26
20
 
27
21
  private
28
22
 
29
23
  def before_successful_response
30
24
  find_or_create_access_token(client, resource_owner.id, scopes, server)
25
+ super
31
26
  end
32
27
 
33
28
  def validate_scopes
@@ -40,7 +35,7 @@ module Doorkeeper
40
35
  end
41
36
 
42
37
  def validate_client
43
- !credentials || !!client
38
+ !parameters[:client_id] || !!client
44
39
  end
45
40
  end
46
41
  end
@@ -57,9 +57,11 @@ module Doorkeeper
57
57
 
58
58
  # TODO: test uri should be matched against the client's one
59
59
  def validate_redirect_uri
60
- return false unless redirect_uri.present?
61
- Helpers::URIChecker.native_uri?(redirect_uri) ||
62
- Helpers::URIChecker.valid_for_authorization?(redirect_uri, client.redirect_uri)
60
+ return false if redirect_uri.blank?
61
+
62
+ Helpers::URIChecker.valid_for_authorization?(
63
+ redirect_uri, client.redirect_uri
64
+ )
63
65
  end
64
66
  end
65
67
  end