doorkeeper 5.1.0 → 5.5.0

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 (265) hide show
  1. checksums.yaml +4 -4
  2. data/{NEWS.md → CHANGELOG.md} +234 -25
  3. data/README.md +21 -11
  4. data/app/controllers/doorkeeper/application_controller.rb +2 -2
  5. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  6. data/app/controllers/doorkeeper/applications_controller.rb +8 -7
  7. data/app/controllers/doorkeeper/authorizations_controller.rb +56 -19
  8. data/app/controllers/doorkeeper/authorized_applications_controller.rb +5 -5
  9. data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
  10. data/app/controllers/doorkeeper/tokens_controller.rb +93 -25
  11. data/app/views/doorkeeper/applications/_form.html.erb +1 -7
  12. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  13. data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
  14. data/config/locales/en.yml +13 -3
  15. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  16. data/lib/doorkeeper/config/option.rb +20 -2
  17. data/lib/doorkeeper/config/validations.rb +53 -0
  18. data/lib/doorkeeper/config.rb +291 -121
  19. data/lib/doorkeeper/engine.rb +1 -1
  20. data/lib/doorkeeper/errors.rb +13 -18
  21. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  22. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  23. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  24. data/lib/doorkeeper/grant_flow.rb +45 -0
  25. data/lib/doorkeeper/grape/helpers.rb +7 -3
  26. data/lib/doorkeeper/helpers/controller.rb +36 -11
  27. data/lib/doorkeeper/models/access_grant_mixin.rb +22 -18
  28. data/lib/doorkeeper/models/access_token_mixin.rb +194 -51
  29. data/lib/doorkeeper/models/application_mixin.rb +8 -7
  30. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  31. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  32. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  33. data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
  34. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  35. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  36. data/lib/doorkeeper/oauth/authorization/code.rb +25 -14
  37. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  38. data/lib/doorkeeper/oauth/authorization/token.rb +24 -19
  39. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  40. data/lib/doorkeeper/oauth/authorization_code_request.rb +40 -21
  41. data/lib/doorkeeper/oauth/base_request.rb +21 -23
  42. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  43. data/lib/doorkeeper/oauth/client.rb +8 -9
  44. data/lib/doorkeeper/oauth/client_credentials/creator.rb +45 -5
  45. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
  46. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +13 -3
  47. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  48. data/lib/doorkeeper/oauth/code_request.rb +6 -12
  49. data/lib/doorkeeper/oauth/code_response.rb +24 -14
  50. data/lib/doorkeeper/oauth/error.rb +1 -1
  51. data/lib/doorkeeper/oauth/error_response.rb +10 -11
  52. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
  53. data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
  54. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -5
  55. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  56. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  57. data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
  58. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  59. data/lib/doorkeeper/oauth/password_access_token_request.rb +32 -10
  60. data/lib/doorkeeper/oauth/pre_authorization.rb +111 -42
  61. data/lib/doorkeeper/oauth/refresh_token_request.rb +45 -33
  62. data/lib/doorkeeper/oauth/token.rb +6 -7
  63. data/lib/doorkeeper/oauth/token_introspection.rb +24 -18
  64. data/lib/doorkeeper/oauth/token_request.rb +6 -20
  65. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  66. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  67. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  68. data/lib/doorkeeper/orm/active_record/application.rb +5 -83
  69. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +68 -0
  70. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +59 -0
  71. data/lib/doorkeeper/orm/active_record/mixins/application.rb +198 -0
  72. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  73. data/lib/doorkeeper/orm/active_record.rb +20 -6
  74. data/lib/doorkeeper/rails/helpers.rb +4 -4
  75. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  76. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  77. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  78. data/lib/doorkeeper/rails/routes.rb +17 -25
  79. data/lib/doorkeeper/rake/db.rake +6 -6
  80. data/lib/doorkeeper/rake/setup.rake +5 -0
  81. data/lib/doorkeeper/request/authorization_code.rb +5 -3
  82. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  83. data/lib/doorkeeper/request/password.rb +2 -2
  84. data/lib/doorkeeper/request/refresh_token.rb +5 -4
  85. data/lib/doorkeeper/request/strategy.rb +2 -2
  86. data/lib/doorkeeper/request.rb +49 -17
  87. data/lib/doorkeeper/server.rb +7 -11
  88. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  89. data/lib/doorkeeper/version.rb +1 -5
  90. data/lib/doorkeeper.rb +114 -79
  91. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  92. data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
  93. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  94. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  95. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  96. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
  97. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  98. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  99. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  100. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  101. data/lib/generators/doorkeeper/templates/initializer.rb +205 -43
  102. data/lib/generators/doorkeeper/templates/migration.rb.erb +18 -6
  103. metadata +43 -310
  104. data/.coveralls.yml +0 -1
  105. data/.github/ISSUE_TEMPLATE.md +0 -25
  106. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  107. data/.gitignore +0 -20
  108. data/.gitlab-ci.yml +0 -16
  109. data/.hound.yml +0 -3
  110. data/.rspec +0 -1
  111. data/.rubocop.yml +0 -50
  112. data/.travis.yml +0 -35
  113. data/Appraisals +0 -40
  114. data/CODE_OF_CONDUCT.md +0 -46
  115. data/CONTRIBUTING.md +0 -47
  116. data/Dangerfile +0 -67
  117. data/Gemfile +0 -24
  118. data/RELEASING.md +0 -10
  119. data/Rakefile +0 -28
  120. data/SECURITY.md +0 -15
  121. data/UPGRADE.md +0 -2
  122. data/app/validators/redirect_uri_validator.rb +0 -50
  123. data/bin/console +0 -16
  124. data/doorkeeper.gemspec +0 -34
  125. data/gemfiles/rails_5_0.gemfile +0 -17
  126. data/gemfiles/rails_5_1.gemfile +0 -17
  127. data/gemfiles/rails_5_2.gemfile +0 -17
  128. data/gemfiles/rails_6_0.gemfile +0 -17
  129. data/gemfiles/rails_master.gemfile +0 -17
  130. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  131. data/spec/controllers/applications_controller_spec.rb +0 -180
  132. data/spec/controllers/authorizations_controller_spec.rb +0 -527
  133. data/spec/controllers/protected_resources_controller_spec.rb +0 -353
  134. data/spec/controllers/token_info_controller_spec.rb +0 -50
  135. data/spec/controllers/tokens_controller_spec.rb +0 -330
  136. data/spec/dummy/Rakefile +0 -9
  137. data/spec/dummy/app/assets/config/manifest.js +0 -2
  138. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  139. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  140. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  141. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  142. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  143. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  144. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  145. data/spec/dummy/app/models/user.rb +0 -7
  146. data/spec/dummy/app/views/home/index.html.erb +0 -0
  147. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  148. data/spec/dummy/config/application.rb +0 -47
  149. data/spec/dummy/config/boot.rb +0 -7
  150. data/spec/dummy/config/database.yml +0 -15
  151. data/spec/dummy/config/environment.rb +0 -5
  152. data/spec/dummy/config/environments/development.rb +0 -31
  153. data/spec/dummy/config/environments/production.rb +0 -64
  154. data/spec/dummy/config/environments/test.rb +0 -45
  155. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  156. data/spec/dummy/config/initializers/doorkeeper.rb +0 -121
  157. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  158. data/spec/dummy/config/initializers/session_store.rb +0 -10
  159. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  160. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  161. data/spec/dummy/config/routes.rb +0 -13
  162. data/spec/dummy/config.ru +0 -6
  163. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  164. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  165. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  166. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  167. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  168. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  169. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  170. data/spec/dummy/db/schema.rb +0 -68
  171. data/spec/dummy/public/404.html +0 -26
  172. data/spec/dummy/public/422.html +0 -26
  173. data/spec/dummy/public/500.html +0 -26
  174. data/spec/dummy/public/favicon.ico +0 -0
  175. data/spec/dummy/script/rails +0 -9
  176. data/spec/factories.rb +0 -30
  177. data/spec/generators/application_owner_generator_spec.rb +0 -28
  178. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  179. data/spec/generators/install_generator_spec.rb +0 -36
  180. data/spec/generators/migration_generator_spec.rb +0 -28
  181. data/spec/generators/pkce_generator_spec.rb +0 -28
  182. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  183. data/spec/generators/templates/routes.rb +0 -4
  184. data/spec/generators/views_generator_spec.rb +0 -29
  185. data/spec/grape/grape_integration_spec.rb +0 -137
  186. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  187. data/spec/lib/config_spec.rb +0 -697
  188. data/spec/lib/doorkeeper_spec.rb +0 -27
  189. data/spec/lib/models/expirable_spec.rb +0 -61
  190. data/spec/lib/models/reusable_spec.rb +0 -40
  191. data/spec/lib/models/revocable_spec.rb +0 -59
  192. data/spec/lib/models/scopes_spec.rb +0 -53
  193. data/spec/lib/models/secret_storable_spec.rb +0 -135
  194. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  195. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -156
  196. data/spec/lib/oauth/base_request_spec.rb +0 -205
  197. data/spec/lib/oauth/base_response_spec.rb +0 -47
  198. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  199. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -94
  200. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  201. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  202. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
  203. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
  204. data/spec/lib/oauth/client_spec.rb +0 -38
  205. data/spec/lib/oauth/code_request_spec.rb +0 -47
  206. data/spec/lib/oauth/code_response_spec.rb +0 -36
  207. data/spec/lib/oauth/error_response_spec.rb +0 -66
  208. data/spec/lib/oauth/error_spec.rb +0 -23
  209. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
  210. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
  211. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  212. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -247
  213. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
  214. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
  215. data/spec/lib/oauth/pre_authorization_spec.rb +0 -215
  216. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  217. data/spec/lib/oauth/scopes_spec.rb +0 -148
  218. data/spec/lib/oauth/token_request_spec.rb +0 -150
  219. data/spec/lib/oauth/token_response_spec.rb +0 -86
  220. data/spec/lib/oauth/token_spec.rb +0 -158
  221. data/spec/lib/request/strategy_spec.rb +0 -54
  222. data/spec/lib/secret_storing/base_spec.rb +0 -60
  223. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  224. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  225. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  226. data/spec/lib/server_spec.rb +0 -61
  227. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  228. data/spec/models/doorkeeper/access_grant_spec.rb +0 -144
  229. data/spec/models/doorkeeper/access_token_spec.rb +0 -591
  230. data/spec/models/doorkeeper/application_spec.rb +0 -367
  231. data/spec/requests/applications/applications_request_spec.rb +0 -259
  232. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  233. data/spec/requests/endpoints/authorization_spec.rb +0 -73
  234. data/spec/requests/endpoints/token_spec.rb +0 -75
  235. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -78
  236. data/spec/requests/flows/authorization_code_spec.rb +0 -447
  237. data/spec/requests/flows/client_credentials_spec.rb +0 -128
  238. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -34
  239. data/spec/requests/flows/implicit_grant_spec.rb +0 -90
  240. data/spec/requests/flows/password_spec.rb +0 -259
  241. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  242. data/spec/requests/flows/revoke_token_spec.rb +0 -143
  243. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  244. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  245. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  246. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  247. data/spec/routing/default_routes_spec.rb +0 -41
  248. data/spec/routing/scoped_routes_spec.rb +0 -47
  249. data/spec/spec_helper.rb +0 -57
  250. data/spec/spec_helper_integration.rb +0 -4
  251. data/spec/support/dependencies/factory_bot.rb +0 -4
  252. data/spec/support/doorkeeper_rspec.rb +0 -22
  253. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  254. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  255. data/spec/support/helpers/config_helper.rb +0 -11
  256. data/spec/support/helpers/model_helper.rb +0 -78
  257. data/spec/support/helpers/request_spec_helper.rb +0 -98
  258. data/spec/support/helpers/url_helper.rb +0 -62
  259. data/spec/support/http_method_shim.rb +0 -29
  260. data/spec/support/orm/active_record.rb +0 -5
  261. data/spec/support/shared/controllers_shared_context.rb +0 -123
  262. data/spec/support/shared/hashing_shared_context.rb +0 -36
  263. data/spec/support/shared/models_shared_examples.rb +0 -54
  264. data/spec/validators/redirect_uri_validator_spec.rb +0 -158
  265. data/spec/version/version_spec.rb +0 -17
@@ -11,28 +11,28 @@ module Doorkeeper
11
11
  validate :client_match, error: :invalid_grant
12
12
  validate :scope, error: :invalid_scope
13
13
 
14
- attr_accessor :access_token, :client, :credentials, :refresh_token,
15
- :server
14
+ attr_reader :access_token, :client, :credentials, :refresh_token
15
+ attr_reader :missing_param
16
16
 
17
17
  def initialize(server, refresh_token, credentials, parameters = {})
18
- @server = server
19
- @refresh_token = refresh_token
20
- @credentials = credentials
18
+ @server = server
19
+ @refresh_token = refresh_token
20
+ @credentials = credentials
21
21
  @original_scopes = parameters[:scope] || parameters[:scopes]
22
22
  @refresh_token_parameter = parameters[:refresh_token]
23
-
24
- if credentials
25
- @client = Application.by_uid_and_secret credentials.uid,
26
- credentials.secret
27
- end
23
+ @client = load_client(credentials) if credentials
28
24
  end
29
25
 
30
26
  private
31
27
 
28
+ def load_client(credentials)
29
+ server_config.application_model.by_uid_and_secret(credentials.uid, credentials.secret)
30
+ end
31
+
32
32
  def before_successful_response
33
33
  refresh_token.transaction do
34
34
  refresh_token.lock!
35
- raise Errors::InvalidTokenReuse if refresh_token.revoked?
35
+ raise Errors::InvalidGrantReuse if refresh_token.revoked?
36
36
 
37
37
  refresh_token.revoke unless refresh_token_revoked_on_use?
38
38
  create_access_token
@@ -41,7 +41,7 @@ module Doorkeeper
41
41
  end
42
42
 
43
43
  def refresh_token_revoked_on_use?
44
- Doorkeeper::AccessToken.refresh_token_revoked_on_use?
44
+ server_config.access_token_model.refresh_token_revoked_on_use?
45
45
  end
46
46
 
47
47
  def default_scopes
@@ -49,34 +49,46 @@ module Doorkeeper
49
49
  end
50
50
 
51
51
  def create_access_token
52
- @access_token = AccessToken.create!(access_token_attributes)
53
- end
52
+ attributes = {}
54
53
 
55
- def access_token_attributes
56
- {
57
- application_id: refresh_token.application_id,
58
- resource_owner_id: refresh_token.resource_owner_id,
59
- scopes: scopes.to_s,
60
- expires_in: access_token_expires_in,
61
- use_refresh_token: true,
62
- }.tap do |attributes|
63
- if refresh_token_revoked_on_use?
64
- 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
65
59
  end
60
+
61
+ if refresh_token_revoked_on_use?
62
+ attributes[:previous_refresh_token] = refresh_token.refresh_token
66
63
  end
67
- end
68
64
 
69
- def access_token_expires_in
70
- context = Authorization::Token.build_context(
71
- client,
72
- Doorkeeper::OAuth::REFRESH_TOKEN,
73
- scopes
65
+ # RFC6749
66
+ # 1.5. Refresh Token
67
+ #
68
+ # Refresh tokens are issued to the client by the authorization server and are
69
+ # used to obtain a new access token when the current access token
70
+ # becomes invalid or expires, or to obtain additional access tokens
71
+ # with identical or narrower scope (access tokens may have a shorter
72
+ # lifetime and fewer permissions than authorized by the resource
73
+ # owner).
74
+ #
75
+ # Here we assume that TTL of the token received after refreshing should be
76
+ # the same as that of the original token.
77
+ #
78
+ @access_token = server_config.access_token_model.create_for(
79
+ application: refresh_token.application,
80
+ resource_owner: resource_owner,
81
+ scopes: scopes,
82
+ expires_in: refresh_token.expires_in,
83
+ use_refresh_token: true,
84
+ **attributes,
74
85
  )
75
- Authorization::Token.access_token_expires_in(server, context)
76
86
  end
77
87
 
78
88
  def validate_token_presence
79
- refresh_token.present? || @refresh_token_parameter.present?
89
+ @missing_param = :refresh_token if refresh_token.blank? && @refresh_token_parameter.blank?
90
+
91
+ @missing_param.nil?
80
92
  end
81
93
 
82
94
  def validate_token
@@ -101,7 +113,7 @@ module Doorkeeper
101
113
  if @original_scopes.present?
102
114
  ScopeChecker.valid?(
103
115
  scope_str: @original_scopes,
104
- server_scopes: refresh_token.scopes
116
+ server_scopes: refresh_token.scopes,
105
117
  )
106
118
  else
107
119
  true
@@ -8,15 +8,14 @@ module Doorkeeper
8
8
  methods.inject(nil) do |_, method|
9
9
  method = self.method(method) if method.is_a?(Symbol)
10
10
  credentials = method.call(request)
11
- break credentials unless credentials.blank?
11
+ break credentials if credentials.present?
12
12
  end
13
13
  end
14
14
 
15
15
  def authenticate(request, *methods)
16
16
  if (token = from_request(request, *methods))
17
- access_token = AccessToken.by_token(token)
18
- refresh_token_enabled = Doorkeeper.configuration.refresh_token_enabled?
19
- if access_token.present? && refresh_token_enabled
17
+ access_token = Doorkeeper.config.access_token_model.by_token(token)
18
+ if access_token.present? && Doorkeeper.config.refresh_token_enabled?
20
19
  access_token.revoke_previous_refresh_token!
21
20
  end
22
21
  access_token
@@ -33,13 +32,13 @@ module Doorkeeper
33
32
 
34
33
  def from_bearer_authorization(request)
35
34
  pattern = /^Bearer /i
36
- header = request.authorization
35
+ header = request.authorization
37
36
  token_from_header(header, pattern) if match?(header, pattern)
38
37
  end
39
38
 
40
39
  def from_basic_authorization(request)
41
40
  pattern = /^Basic /i
42
- header = request.authorization
41
+ header = request.authorization
43
42
  token_from_basic_header(header, pattern) if match?(header, pattern)
44
43
  end
45
44
 
@@ -55,7 +54,7 @@ module Doorkeeper
55
54
  end
56
55
 
57
56
  def token_from_header(header, pattern)
58
- header.gsub pattern, ""
57
+ header.gsub(pattern, "")
59
58
  end
60
59
 
61
60
  def match?(header, pattern)
@@ -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
11
-
12
9
  def initialize(server, token)
13
10
  @server = server
14
11
  @token = token
@@ -25,6 +22,8 @@ module Doorkeeper
25
22
 
26
23
  if @error == :invalid_token
27
24
  OAuth::InvalidTokenResponse.from_access_token(authorized_token)
25
+ elsif @error == :invalid_request
26
+ OAuth::InvalidRequestResponse.from_request(self)
28
27
  else
29
28
  OAuth::ErrorResponse.new(name: @error)
30
29
  end
@@ -36,6 +35,9 @@ module Doorkeeper
36
35
 
37
36
  private
38
37
 
38
+ attr_reader :server, :token
39
+ attr_reader :error, :invalid_request_reason
40
+
39
41
  # If the protected resource uses OAuth 2.0 client credentials to
40
42
  # authenticate to the introspection endpoint and its credentials are
41
43
  # invalid, the authorization server responds with an HTTP 401
@@ -67,9 +69,10 @@ module Doorkeeper
67
69
  # HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
68
70
  # Usage [RFC6750].
69
71
  #
70
- @error = :invalid_token if authorized_token_matches_introspected? || !authorized_token.accessible?
72
+ @error = :invalid_token unless valid_authorized_token?
71
73
  else
72
74
  @error = :invalid_request
75
+ @invalid_request_reason = :request_not_authorized
73
76
  end
74
77
  end
75
78
 
@@ -80,8 +83,7 @@ module Doorkeeper
80
83
 
81
84
  # Bearer Token Authentication
82
85
  def authorized_token
83
- @authorized_token ||=
84
- OAuth::Token.authenticate(server.context.request, :from_bearer_authorization)
86
+ @authorized_token ||= Doorkeeper.authenticate(server.context.request)
85
87
  end
86
88
 
87
89
  # 2.2. Introspection Response
@@ -92,7 +94,7 @@ module Doorkeeper
92
94
  client_id: @token.try(:application).try(:uid),
93
95
  token_type: @token.token_type,
94
96
  exp: @token.expires_at.to_i,
95
- iat: @token.created_at.to_i
97
+ iat: @token.created_at.to_i,
96
98
  )
97
99
  end
98
100
 
@@ -150,7 +152,7 @@ module Doorkeeper
150
152
  #
151
153
  def active?
152
154
  if authorized_client
153
- valid_token? && authorized_for_client?
155
+ valid_token? && token_introspection_allowed?(auth_client: authorized_client.application)
154
156
  else
155
157
  valid_token?
156
158
  end
@@ -161,19 +163,23 @@ module Doorkeeper
161
163
  @token&.accessible?
162
164
  end
163
165
 
166
+ def valid_authorized_token?
167
+ !authorized_token_matches_introspected? &&
168
+ authorized_token.accessible? &&
169
+ token_introspection_allowed?(auth_token: authorized_token)
170
+ end
171
+
164
172
  # RFC7662 Section 2.1
165
173
  def authorized_token_matches_introspected?
166
174
  authorized_token.token == @token&.token
167
175
  end
168
176
 
169
- # If token doesn't belong to some client, then it is public.
170
- # Otherwise in it required for token to be connected to the same client.
171
- def authorized_for_client?
172
- if @token.application
173
- @token.application == authorized_client.application
174
- else
175
- true
176
- end
177
+ # Config constraints for introspection in Doorkeeper.config.allow_token_introspection
178
+ def token_introspection_allowed?(auth_client: nil, auth_token: nil)
179
+ allow_introspection = Doorkeeper.config.allow_token_introspection
180
+ return allow_introspection unless allow_introspection.respond_to?(:call)
181
+
182
+ allow_introspection.call(@token, auth_client, auth_token)
177
183
  end
178
184
 
179
185
  # Allows to customize introspection response.
@@ -183,9 +189,9 @@ module Doorkeeper
183
189
  # @see https://tools.ietf.org/html/rfc7662#section-2.2
184
190
  #
185
191
  def customize_response(response)
186
- customized_response = Doorkeeper.configuration.custom_introspection_response.call(
192
+ customized_response = Doorkeeper.config.custom_introspection_response.call(
187
193
  token,
188
- server.context
194
+ server.context,
189
195
  )
190
196
  return response if customized_response.blank?
191
197
 
@@ -3,36 +3,22 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class TokenRequest
6
- attr_accessor :pre_auth, :resource_owner
6
+ attr_reader :pre_auth, :resource_owner
7
7
 
8
8
  def initialize(pre_auth, resource_owner)
9
- @pre_auth = pre_auth
9
+ @pre_auth = pre_auth
10
10
  @resource_owner = resource_owner
11
11
  end
12
12
 
13
13
  def authorize
14
- if pre_auth.authorizable?
15
- auth = Authorization::Token.new(pre_auth, resource_owner)
16
- auth.issue_token
17
- @response = CodeResponse.new pre_auth,
18
- auth,
19
- response_on_fragment: true
20
- else
21
- @response = error_response
22
- end
14
+ auth = Authorization::Token.new(pre_auth, resource_owner)
15
+ auth.issue_token!
16
+ CodeResponse.new(pre_auth, auth, response_on_fragment: true)
23
17
  end
24
18
 
25
19
  def deny
26
20
  pre_auth.error = :access_denied
27
- error_response
28
- end
29
-
30
- private
31
-
32
- def error_response
33
- ErrorResponse.from_request pre_auth,
34
- redirect_uri: pre_auth.redirect_uri,
35
- response_on_fragment: true
21
+ pre_auth.error_response
36
22
  end
37
23
  end
38
24
  end
@@ -3,7 +3,7 @@
3
3
  module Doorkeeper
4
4
  module OAuth
5
5
  class TokenResponse
6
- attr_accessor :token
6
+ attr_reader :token
7
7
 
8
8
  def initialize(token)
9
9
  @token = token
@@ -1,48 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Doorkeeper
4
- class AccessGrant < ActiveRecord::Base
5
- self.table_name = "#{table_name_prefix}oauth_access_grants#{table_name_suffix}"
6
-
7
- include AccessGrantMixin
8
-
9
- belongs_to :application, class_name: "Doorkeeper::Application",
10
- optional: true, inverse_of: :access_grants
11
-
12
- validates :resource_owner_id,
13
- :application_id,
14
- :token,
15
- :expires_in,
16
- :redirect_uri,
17
- presence: true
18
-
19
- validates :token, uniqueness: true
3
+ require "doorkeeper/orm/active_record/mixins/access_grant"
20
4
 
21
- before_validation :generate_token, on: :create
22
-
23
- # We keep a volatile copy of the raw token for initial communication
24
- # The stored refresh_token may be mapped and not available in cleartext.
25
- #
26
- # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
27
- # while hashing strategies do not, so you cannot rely on this value
28
- # returning a present value for persisted tokens.
29
- def plaintext_token
30
- if secret_strategy.allows_restoring_secrets?
31
- secret_strategy.restore_secret(self, :token)
32
- else
33
- @raw_token
34
- end
35
- end
36
-
37
- private
38
-
39
- # Generates token value with UniqueToken class.
40
- #
41
- # @return [String] token value
42
- #
43
- def generate_token
44
- @raw_token = UniqueToken.generate
45
- secret_strategy.store_secret(self, :token, @raw_token)
46
- end
5
+ module Doorkeeper
6
+ class AccessGrant < ::ActiveRecord::Base
7
+ include Doorkeeper::Orm::ActiveRecord::Mixins::AccessGrant
47
8
  end
48
9
  end
@@ -1,40 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Doorkeeper
4
- class AccessToken < ActiveRecord::Base
5
- self.table_name = "#{table_name_prefix}oauth_access_tokens#{table_name_suffix}"
6
-
7
- include AccessTokenMixin
8
-
9
- belongs_to :application, class_name: "Doorkeeper::Application",
10
- inverse_of: :access_tokens, optional: true
11
-
12
- validates :token, presence: true, uniqueness: true
13
- validates :refresh_token, uniqueness: true, if: :use_refresh_token?
3
+ require "doorkeeper/orm/active_record/mixins/access_token"
14
4
 
15
- # @attr_writer [Boolean, nil] use_refresh_token
16
- # indicates the possibility of using refresh token
17
- attr_writer :use_refresh_token
18
-
19
- before_validation :generate_token, on: :create
20
- before_validation :generate_refresh_token,
21
- on: :create, if: :use_refresh_token?
22
-
23
- # Searches for not revoked Access Tokens associated with the
24
- # specific Resource Owner.
25
- #
26
- # @param resource_owner [ActiveRecord::Base]
27
- # Resource Owner model instance
28
- #
29
- # @return [ActiveRecord::Relation]
30
- # active Access Tokens for Resource Owner
31
- #
32
- def self.active_for(resource_owner)
33
- where(resource_owner_id: resource_owner.id, revoked_at: nil)
34
- end
35
-
36
- def self.refresh_token_revoked_on_use?
37
- column_names.include?("previous_refresh_token")
38
- end
5
+ module Doorkeeper
6
+ class AccessToken < ::ActiveRecord::Base
7
+ include Doorkeeper::Orm::ActiveRecord::Mixins::AccessToken
39
8
  end
40
9
  end
@@ -1,88 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- module Doorkeeper
4
- class Application < ActiveRecord::Base
5
- self.table_name = "#{table_name_prefix}oauth_applications#{table_name_suffix}"
6
-
7
- include ApplicationMixin
8
-
9
- has_many :access_grants, dependent: :delete_all, class_name: "Doorkeeper::AccessGrant"
10
- has_many :access_tokens, dependent: :delete_all, class_name: "Doorkeeper::AccessToken"
11
-
12
- validates :name, :secret, :uid, presence: true
13
- validates :uid, uniqueness: true
14
- validates :redirect_uri, redirect_uri: true
15
- validates :confidential, inclusion: { in: [true, false] }
16
-
17
- validate :scopes_match_configured, if: :enforce_scopes?
18
-
19
- before_validation :generate_uid, :generate_secret, on: :create
20
-
21
- has_many :authorized_tokens, -> { where(revoked_at: nil) }, class_name: "AccessToken"
22
- has_many :authorized_applications, through: :authorized_tokens, source: :application
23
-
24
- # Returns Applications associated with active (not revoked) Access Tokens
25
- # that are owned by the specific Resource Owner.
26
- #
27
- # @param resource_owner [ActiveRecord::Base]
28
- # Resource Owner model instance
29
- #
30
- # @return [ActiveRecord::Relation]
31
- # Applications authorized for the Resource Owner
32
- #
33
- def self.authorized_for(resource_owner)
34
- resource_access_tokens = AccessToken.active_for(resource_owner)
35
- where(id: resource_access_tokens.select(:application_id).distinct)
36
- end
3
+ require "doorkeeper/orm/active_record/redirect_uri_validator"
4
+ require "doorkeeper/orm/active_record/mixins/application"
37
5
 
38
- # Revokes AccessToken and AccessGrant records that have not been revoked and
39
- # associated with the specific Application and Resource Owner.
40
- #
41
- # @param resource_owner [ActiveRecord::Base]
42
- # instance of the Resource Owner model
43
- #
44
- def self.revoke_tokens_and_grants_for(id, resource_owner)
45
- AccessToken.revoke_all_for(id, resource_owner)
46
- AccessGrant.revoke_all_for(id, resource_owner)
47
- end
48
-
49
- # We keep a volatile copy of the raw secret for initial communication
50
- # The stored refresh_token may be mapped and not available in cleartext.
51
- #
52
- # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
53
- # while hashing strategies do not, so you cannot rely on this value
54
- # returning a present value for persisted tokens.
55
- def plaintext_secret
56
- if secret_strategy.allows_restoring_secrets?
57
- secret_strategy.restore_secret(self, :secret)
58
- else
59
- @raw_secret
60
- end
61
- end
62
-
63
- private
64
-
65
- def generate_uid
66
- self.uid = UniqueToken.generate if uid.blank?
67
- end
68
-
69
- def generate_secret
70
- return unless secret.blank?
71
-
72
- @raw_secret = UniqueToken.generate
73
- secret_strategy.store_secret(self, :secret, @raw_secret)
74
- end
75
-
76
- def scopes_match_configured
77
- if scopes.present? &&
78
- !ScopeChecker.valid?(scope_str: scopes.to_s,
79
- server_scopes: Doorkeeper.configuration.scopes)
80
- errors.add(:scopes, :not_match_configured)
81
- end
82
- end
83
-
84
- def enforce_scopes?
85
- Doorkeeper.configuration.enforce_configured_scopes?
86
- end
6
+ module Doorkeeper
7
+ class Application < ::ActiveRecord::Base
8
+ include ::Doorkeeper::Orm::ActiveRecord::Mixins::Application
87
9
  end
88
10
  end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper::Orm::ActiveRecord::Mixins
4
+ module AccessGrant
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ self.table_name = compute_doorkeeper_table_name
9
+
10
+ include ::Doorkeeper::AccessGrantMixin
11
+
12
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
13
+ optional: true,
14
+ inverse_of: :access_grants
15
+
16
+ if Doorkeeper.config.polymorphic_resource_owner?
17
+ belongs_to :resource_owner, polymorphic: true, optional: false
18
+ else
19
+ validates :resource_owner_id, presence: true
20
+ end
21
+
22
+ validates :application_id,
23
+ :token,
24
+ :expires_in,
25
+ :redirect_uri,
26
+ presence: true
27
+
28
+ validates :token, uniqueness: { case_sensitive: true }
29
+
30
+ before_validation :generate_token, on: :create
31
+
32
+ # We keep a volatile copy of the raw token for initial communication
33
+ # The stored refresh_token may be mapped and not available in cleartext.
34
+ #
35
+ # Some strategies allow restoring stored secrets (e.g. symmetric encryption)
36
+ # while hashing strategies do not, so you cannot rely on this value
37
+ # returning a present value for persisted tokens.
38
+ def plaintext_token
39
+ if secret_strategy.allows_restoring_secrets?
40
+ secret_strategy.restore_secret(self, :token)
41
+ else
42
+ @raw_token
43
+ end
44
+ end
45
+
46
+ private
47
+
48
+ # Generates token value with UniqueToken class.
49
+ #
50
+ # @return [String] token value
51
+ #
52
+ def generate_token
53
+ @raw_token = Doorkeeper::OAuth::Helpers::UniqueToken.generate
54
+ secret_strategy.store_secret(self, :token, @raw_token)
55
+ end
56
+ end
57
+
58
+ module ClassMethods
59
+ private
60
+
61
+ def compute_doorkeeper_table_name
62
+ table_name = "oauth_access_grant"
63
+ table_name = table_name.pluralize if pluralize_table_names
64
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper::Orm::ActiveRecord::Mixins
4
+ module AccessToken
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ self.table_name = compute_doorkeeper_table_name
9
+
10
+ include ::Doorkeeper::AccessTokenMixin
11
+
12
+ belongs_to :application, class_name: Doorkeeper.config.application_class.to_s,
13
+ inverse_of: :access_tokens,
14
+ optional: true
15
+
16
+ if Doorkeeper.config.polymorphic_resource_owner?
17
+ belongs_to :resource_owner, polymorphic: true, optional: true
18
+ end
19
+
20
+ validates :token, presence: true, uniqueness: { case_sensitive: true }
21
+ validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
22
+
23
+ # @attr_writer [Boolean, nil] use_refresh_token
24
+ # indicates the possibility of using refresh token
25
+ attr_writer :use_refresh_token
26
+
27
+ before_validation :generate_token, on: :create
28
+ before_validation :generate_refresh_token,
29
+ on: :create, if: :use_refresh_token?
30
+ end
31
+
32
+ module ClassMethods
33
+ # Searches for not revoked Access Tokens associated with the
34
+ # specific Resource Owner.
35
+ #
36
+ # @param resource_owner [ActiveRecord::Base]
37
+ # Resource Owner model instance
38
+ #
39
+ # @return [ActiveRecord::Relation]
40
+ # active Access Tokens for Resource Owner
41
+ #
42
+ def active_for(resource_owner)
43
+ by_resource_owner(resource_owner).where(revoked_at: nil)
44
+ end
45
+
46
+ def refresh_token_revoked_on_use?
47
+ column_names.include?("previous_refresh_token")
48
+ end
49
+
50
+ private
51
+
52
+ def compute_doorkeeper_table_name
53
+ table_name = "oauth_access_token"
54
+ table_name = table_name.pluralize if pluralize_table_names
55
+ "#{table_name_prefix}#{table_name}#{table_name_suffix}"
56
+ end
57
+ end
58
+ end
59
+ end