doorkeeper 5.0.0 → 5.1.0

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 (241) hide show
  1. checksums.yaml +5 -5
  2. data/.hound.yml +2 -1
  3. data/.rubocop.yml +37 -4
  4. data/.travis.yml +16 -21
  5. data/Appraisals +29 -7
  6. data/Dangerfile +67 -0
  7. data/Gemfile +19 -5
  8. data/NEWS.md +107 -10
  9. data/README.md +75 -470
  10. data/Rakefile +10 -8
  11. data/app/controllers/doorkeeper/application_controller.rb +3 -2
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -13
  13. data/app/controllers/doorkeeper/applications_controller.rb +21 -7
  14. data/app/controllers/doorkeeper/authorizations_controller.rb +3 -3
  15. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -0
  16. data/app/controllers/doorkeeper/token_info_controller.rb +4 -2
  17. data/app/controllers/doorkeeper/tokens_controller.rb +13 -11
  18. data/app/helpers/doorkeeper/dashboard_helper.rb +3 -1
  19. data/app/validators/redirect_uri_validator.rb +7 -2
  20. data/app/views/doorkeeper/applications/_form.html.erb +6 -0
  21. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  22. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  23. data/bin/console +16 -0
  24. data/config/locales/en.yml +1 -0
  25. data/doorkeeper.gemspec +28 -24
  26. data/gemfiles/rails_5_0.gemfile +9 -4
  27. data/gemfiles/rails_5_1.gemfile +9 -4
  28. data/gemfiles/rails_5_2.gemfile +10 -5
  29. data/gemfiles/rails_6_0.gemfile +17 -0
  30. data/gemfiles/rails_master.gemfile +9 -9
  31. data/lib/doorkeeper/config/option.rb +64 -0
  32. data/lib/doorkeeper/config.rb +197 -76
  33. data/lib/doorkeeper/engine.rb +3 -1
  34. data/lib/doorkeeper/errors.rb +17 -0
  35. data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
  36. data/lib/doorkeeper/grape/helpers.rb +5 -3
  37. data/lib/doorkeeper/helpers/controller.rb +5 -2
  38. data/lib/doorkeeper/models/access_grant_mixin.rb +25 -6
  39. data/lib/doorkeeper/models/access_token_mixin.rb +68 -22
  40. data/lib/doorkeeper/models/application_mixin.rb +45 -1
  41. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  42. data/lib/doorkeeper/models/concerns/expirable.rb +6 -2
  43. data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
  44. data/lib/doorkeeper/models/concerns/ownership.rb +3 -6
  45. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  46. data/lib/doorkeeper/models/concerns/revocable.rb +4 -1
  47. data/lib/doorkeeper/models/concerns/scopes.rb +7 -1
  48. data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
  49. data/lib/doorkeeper/oauth/authorization/code.rb +4 -2
  50. data/lib/doorkeeper/oauth/authorization/context.rb +2 -0
  51. data/lib/doorkeeper/oauth/authorization/token.rb +14 -7
  52. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +3 -1
  53. data/lib/doorkeeper/oauth/authorization_code_request.rb +8 -4
  54. data/lib/doorkeeper/oauth/base_request.rb +2 -0
  55. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  56. data/lib/doorkeeper/oauth/client/credentials.rb +2 -0
  57. data/lib/doorkeeper/oauth/client.rb +3 -1
  58. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -0
  59. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +2 -0
  60. data/lib/doorkeeper/oauth/client_credentials/validation.rb +7 -4
  61. data/lib/doorkeeper/oauth/client_credentials_request.rb +3 -1
  62. data/lib/doorkeeper/oauth/code_request.rb +2 -0
  63. data/lib/doorkeeper/oauth/code_response.rb +4 -2
  64. data/lib/doorkeeper/oauth/error.rb +2 -0
  65. data/lib/doorkeeper/oauth/error_response.rb +20 -6
  66. data/lib/doorkeeper/oauth/forbidden_token_response.rb +10 -3
  67. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +25 -8
  68. data/lib/doorkeeper/oauth/helpers/unique_token.rb +15 -1
  69. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +42 -3
  70. data/lib/doorkeeper/oauth/invalid_token_response.rb +22 -0
  71. data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -2
  72. data/lib/doorkeeper/oauth/pre_authorization.rb +13 -5
  73. data/lib/doorkeeper/oauth/refresh_token_request.rb +15 -4
  74. data/lib/doorkeeper/oauth/scopes.rb +7 -3
  75. data/lib/doorkeeper/oauth/token.rb +4 -2
  76. data/lib/doorkeeper/oauth/token_introspection.rb +76 -8
  77. data/lib/doorkeeper/oauth/token_request.rb +2 -0
  78. data/lib/doorkeeper/oauth/token_response.rb +11 -9
  79. data/lib/doorkeeper/oauth.rb +5 -5
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
  82. data/lib/doorkeeper/orm/active_record/application.rb +26 -7
  83. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
  84. data/lib/doorkeeper/orm/active_record.rb +8 -6
  85. data/lib/doorkeeper/rails/helpers.rb +5 -1
  86. data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
  87. data/lib/doorkeeper/rails/routes/mapping.rb +9 -7
  88. data/lib/doorkeeper/rails/routes.rb +19 -12
  89. data/lib/doorkeeper/rake/db.rake +17 -17
  90. data/lib/doorkeeper/rake.rb +1 -1
  91. data/lib/doorkeeper/request/authorization_code.rb +2 -0
  92. data/lib/doorkeeper/request/client_credentials.rb +2 -0
  93. data/lib/doorkeeper/request/code.rb +2 -0
  94. data/lib/doorkeeper/request/password.rb +2 -0
  95. data/lib/doorkeeper/request/refresh_token.rb +2 -0
  96. data/lib/doorkeeper/request/strategy.rb +2 -0
  97. data/lib/doorkeeper/request/token.rb +2 -0
  98. data/lib/doorkeeper/request.rb +3 -1
  99. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  100. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  101. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  102. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  103. data/lib/doorkeeper/server.rb +2 -0
  104. data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
  105. data/lib/doorkeeper/validations.rb +2 -0
  106. data/lib/doorkeeper/version.rb +4 -2
  107. data/lib/doorkeeper.rb +69 -59
  108. data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
  109. data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
  110. data/lib/generators/doorkeeper/install_generator.rb +11 -9
  111. data/lib/generators/doorkeeper/migration_generator.rb +9 -9
  112. data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
  113. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
  114. data/lib/generators/doorkeeper/templates/initializer.rb +138 -13
  115. data/lib/generators/doorkeeper/templates/migration.rb.erb +17 -10
  116. data/lib/generators/doorkeeper/views_generator.rb +6 -4
  117. data/spec/controllers/application_metal_controller_spec.rb +24 -10
  118. data/spec/controllers/applications_controller_spec.rb +76 -78
  119. data/spec/controllers/authorizations_controller_spec.rb +189 -142
  120. data/spec/controllers/protected_resources_controller_spec.rb +111 -67
  121. data/spec/controllers/token_info_controller_spec.rb +14 -12
  122. data/spec/controllers/tokens_controller_spec.rb +170 -112
  123. data/spec/dummy/Rakefile +3 -1
  124. data/spec/dummy/app/controllers/application_controller.rb +3 -1
  125. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +3 -1
  126. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
  127. data/spec/dummy/app/controllers/home_controller.rb +6 -5
  128. data/spec/dummy/app/controllers/metal_controller.rb +2 -0
  129. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
  130. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  131. data/spec/dummy/app/models/user.rb +2 -0
  132. data/spec/dummy/config/application.rb +26 -2
  133. data/spec/dummy/config/boot.rb +2 -4
  134. data/spec/dummy/config/environment.rb +1 -1
  135. data/spec/dummy/config/environments/development.rb +2 -0
  136. data/spec/dummy/config/environments/production.rb +2 -0
  137. data/spec/dummy/config/environments/test.rb +4 -2
  138. data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
  139. data/spec/dummy/config/initializers/doorkeeper.rb +7 -3
  140. data/spec/dummy/config/initializers/secret_token.rb +3 -1
  141. data/spec/dummy/config/initializers/session_store.rb +3 -1
  142. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  143. data/spec/dummy/config.ru +3 -1
  144. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +20 -13
  145. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
  146. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
  147. data/spec/dummy/db/schema.rb +1 -1
  148. data/spec/dummy/script/rails +7 -4
  149. data/spec/factories.rb +11 -9
  150. data/spec/generators/application_owner_generator_spec.rb +13 -26
  151. data/spec/generators/confidential_applications_generator_spec.rb +12 -28
  152. data/spec/generators/install_generator_spec.rb +19 -14
  153. data/spec/generators/migration_generator_spec.rb +13 -26
  154. data/spec/generators/pkce_generator_spec.rb +11 -26
  155. data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
  156. data/spec/generators/templates/routes.rb +2 -1
  157. data/spec/generators/views_generator_spec.rb +14 -12
  158. data/spec/grape/grape_integration_spec.rb +35 -33
  159. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
  160. data/spec/lib/config_spec.rb +290 -104
  161. data/spec/lib/doorkeeper_spec.rb +8 -6
  162. data/spec/lib/models/expirable_spec.rb +22 -8
  163. data/spec/lib/models/reusable_spec.rb +40 -0
  164. data/spec/lib/models/revocable_spec.rb +8 -6
  165. data/spec/lib/models/scopes_spec.rb +27 -13
  166. data/spec/lib/models/secret_storable_spec.rb +135 -0
  167. data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
  168. data/spec/lib/oauth/authorization_code_request_spec.rb +43 -17
  169. data/spec/lib/oauth/base_request_spec.rb +24 -12
  170. data/spec/lib/oauth/base_response_spec.rb +3 -1
  171. data/spec/lib/oauth/client/credentials_spec.rb +26 -24
  172. data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
  173. data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -20
  174. data/spec/lib/oauth/client_credentials/validation_spec.rb +21 -15
  175. data/spec/lib/oauth/client_credentials_integration_spec.rb +8 -6
  176. data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
  177. data/spec/lib/oauth/client_spec.rb +15 -13
  178. data/spec/lib/oauth/code_request_spec.rb +10 -8
  179. data/spec/lib/oauth/code_response_spec.rb +9 -7
  180. data/spec/lib/oauth/error_response_spec.rb +19 -11
  181. data/spec/lib/oauth/error_spec.rb +4 -2
  182. data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
  183. data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
  184. data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
  185. data/spec/lib/oauth/helpers/uri_checker_spec.rb +124 -93
  186. data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
  187. data/spec/lib/oauth/password_access_token_request_spec.rb +95 -34
  188. data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
  189. data/spec/lib/oauth/refresh_token_request_spec.rb +46 -39
  190. data/spec/lib/oauth/scopes_spec.rb +63 -61
  191. data/spec/lib/oauth/token_request_spec.rb +80 -25
  192. data/spec/lib/oauth/token_response_spec.rb +40 -38
  193. data/spec/lib/oauth/token_spec.rb +64 -45
  194. data/spec/lib/request/strategy_spec.rb +3 -1
  195. data/spec/lib/secret_storing/base_spec.rb +60 -0
  196. data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
  197. data/spec/lib/secret_storing/plain_spec.rb +44 -0
  198. data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
  199. data/spec/lib/server_spec.rb +20 -18
  200. data/spec/lib/{orm/active_record/stale_records_cleaner_spec.rb → stale_records_cleaner_spec.rb} +28 -18
  201. data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
  202. data/spec/models/doorkeeper/access_token_spec.rb +212 -83
  203. data/spec/models/doorkeeper/application_spec.rb +146 -49
  204. data/spec/requests/applications/applications_request_spec.rb +100 -68
  205. data/spec/requests/applications/authorized_applications_spec.rb +20 -18
  206. data/spec/requests/endpoints/authorization_spec.rb +27 -25
  207. data/spec/requests/endpoints/token_spec.rb +38 -36
  208. data/spec/requests/flows/authorization_code_errors_spec.rb +27 -25
  209. data/spec/requests/flows/authorization_code_spec.rb +260 -158
  210. data/spec/requests/flows/client_credentials_spec.rb +54 -52
  211. data/spec/requests/flows/implicit_grant_errors_spec.rb +11 -9
  212. data/spec/requests/flows/implicit_grant_spec.rb +27 -25
  213. data/spec/requests/flows/password_spec.rb +64 -56
  214. data/spec/requests/flows/refresh_token_spec.rb +91 -32
  215. data/spec/requests/flows/revoke_token_spec.rb +49 -63
  216. data/spec/requests/flows/skip_authorization_spec.rb +23 -21
  217. data/spec/requests/protected_resources/metal_spec.rb +7 -5
  218. data/spec/requests/protected_resources/private_api_spec.rb +37 -35
  219. data/spec/routing/custom_controller_routes_spec.rb +71 -65
  220. data/spec/routing/default_routes_spec.rb +22 -20
  221. data/spec/routing/scoped_routes_spec.rb +20 -18
  222. data/spec/spec_helper.rb +15 -13
  223. data/spec/spec_helper_integration.rb +3 -1
  224. data/spec/support/dependencies/factory_bot.rb +3 -1
  225. data/spec/support/doorkeeper_rspec.rb +5 -2
  226. data/spec/support/helpers/access_token_request_helper.rb +3 -1
  227. data/spec/support/helpers/authorization_request_helper.rb +4 -2
  228. data/spec/support/helpers/config_helper.rb +2 -0
  229. data/spec/support/helpers/model_helper.rb +11 -5
  230. data/spec/support/helpers/request_spec_helper.rb +5 -3
  231. data/spec/support/helpers/url_helper.rb +20 -18
  232. data/spec/support/http_method_shim.rb +4 -9
  233. data/spec/support/orm/active_record.rb +3 -1
  234. data/spec/support/shared/controllers_shared_context.rb +68 -10
  235. data/spec/support/shared/hashing_shared_context.rb +36 -0
  236. data/spec/support/shared/models_shared_examples.rb +12 -10
  237. data/spec/validators/redirect_uri_validator_spec.rb +76 -47
  238. data/spec/version/version_spec.rb +7 -5
  239. metadata +70 -21
  240. data/gemfiles/rails_4_2.gemfile +0 -13
  241. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -10
@@ -1,13 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rails/generators'
4
- require 'rails/generators/active_record'
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
5
 
6
6
  module Doorkeeper
7
+ # Generates migration to add previous refresh token column to the
8
+ # database for Doorkeeper tables.
9
+ #
7
10
  class PreviousRefreshTokenGenerator < ::Rails::Generators::Base
8
11
  include ::Rails::Generators::Migration
9
- source_root File.expand_path('templates', __dir__)
10
- desc 'Support revoke refresh token on access token use'
12
+ source_root File.expand_path("templates", __dir__)
13
+ desc "Support revoke refresh token on access token use"
11
14
 
12
15
  def self.next_migration_number(path)
13
16
  ActiveRecord::Generators::Base.next_migration_number(path)
@@ -16,8 +19,8 @@ module Doorkeeper
16
19
  def previous_refresh_token
17
20
  if no_previous_refresh_token_column?
18
21
  migration_template(
19
- 'add_previous_refresh_token_to_access_tokens.rb.erb',
20
- 'db/migrate/add_previous_refresh_token_to_access_tokens.rb'
22
+ "add_previous_refresh_token_to_access_tokens.rb.erb",
23
+ "db/migrate/add_previous_refresh_token_to_access_tokens.rb"
21
24
  )
22
25
  end
23
26
  end
@@ -25,9 +28,7 @@ module Doorkeeper
25
28
  private
26
29
 
27
30
  def migration_version
28
- if ActiveRecord::VERSION::MAJOR >= 5
29
- "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
30
- end
31
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
31
32
  end
32
33
 
33
34
  def no_previous_refresh_token_column?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  Doorkeeper.configure do
2
4
  # Change the ORM that doorkeeper will use (needs plugins)
3
5
  orm :active_record
@@ -47,7 +49,12 @@ Doorkeeper.configure do
47
49
  # access_token_expires_in 2.hours
48
50
 
49
51
  # Assign custom TTL for access tokens. Will be used instead of access_token_expires_in
50
- # option if defined. `context` has the following properties available
52
+ # option if defined. In case the block returns `nil` value Doorkeeper fallbacks to
53
+ # `access_token_expires_in` configuration option value. If you really need to issue a
54
+ # non-expiring access token (which is not recommended) then you need to return
55
+ # Float::INFINITY from this block.
56
+ #
57
+ # `context` has the following properties available:
51
58
  #
52
59
  # `client` - the OAuth client application (see Doorkeeper::OAuth::Client)
53
60
  # `grant_type` - the grant type of the request (see Doorkeeper::OAuth)
@@ -64,15 +71,74 @@ Doorkeeper.configure do
64
71
 
65
72
  # The controller Doorkeeper::ApplicationController inherits from.
66
73
  # Defaults to ActionController::Base.
67
- # See https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
74
+ # See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
68
75
  #
69
76
  # base_controller 'ApplicationController'
70
77
 
71
- # Reuse access token for the same resource owner within an application (disabled by default)
78
+ # Reuse access token for the same resource owner within an application (disabled by default).
79
+ #
80
+ # This option protects your application from creating new tokens before old valid one becomes
81
+ # expired so your database doesn't bloat. Keep in mind that when this option is `on` Doorkeeper
82
+ # doesn't updates existing token expiration time, it will create a new token instead.
72
83
  # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
73
84
  #
85
+ # You can not enable this option together with +hash_token_secrets+.
86
+ #
74
87
  # reuse_access_token
75
88
 
89
+ # Set a limit for token_reuse if using reuse_access_token option
90
+ #
91
+ # This option limits token_reusability to some extent.
92
+ # If not set then access_token will be reused unless it expires.
93
+ # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
94
+ #
95
+ # This option should be a percentage(i.e. (0,100])
96
+ #
97
+ # token_reuse_limit 100
98
+
99
+ # Hash access and refresh tokens before persisting them.
100
+ # This will disable the possibility to use +reuse_access_token+
101
+ # since plain values can no longer be retrieved.
102
+ #
103
+ # Note: If you are already a user of doorkeeper and have existing tokens
104
+ # in your installation, they will be invalid without enabling the additional
105
+ # setting `fallback_to_plain_secrets` below.
106
+ #
107
+ # hash_token_secrets
108
+ # By default, token secrets will be hashed using the
109
+ # +Doorkeeper::Hashing::SHA256+ strategy.
110
+ #
111
+ # If you wish to use another hashing implementation, you can override
112
+ # this strategy as follows:
113
+ #
114
+ # hash_token_secrets using: '::Doorkeeper::Hashing::MyCustomHashImpl'
115
+ #
116
+ # Keep in mind that changing the hashing function will invalidate all existing
117
+ # secrets, if there are any.
118
+
119
+ # Hash application secrets before persisting them.
120
+ #
121
+ # hash_application_secrets
122
+ #
123
+ # By default, applications will be hashed
124
+ # with the +Doorkeeper::SecretStoring::SHA256+ strategy.
125
+ #
126
+ # If you wish to use bcrypt for application secret hashing, uncomment
127
+ # this line instead:
128
+ #
129
+ # hash_application_secrets using: '::Doorkeeper::SecretStoring::BCrypt'
130
+
131
+ # When the above option is enabled,
132
+ # and a hashed token or secret is not found,
133
+ # you can allow to fall back to another strategy.
134
+ # For users upgrading doorkeeper and wishing to enable hashing,
135
+ # you will probably want to enable the fallback to plain tokens.
136
+ #
137
+ # This will ensure that old access tokens and secrets
138
+ # will remain valid even if the hashing above is enabled.
139
+ #
140
+ # fallback_to_plain_secrets
141
+
76
142
  # Issue access tokens with refresh token (disabled by default), you may also
77
143
  # pass a block which accepts `context` to customize when to give a refresh
78
144
  # token or not. Similar to `custom_access_token_expires_in`, `context` has
@@ -84,16 +150,11 @@ Doorkeeper.configure do
84
150
  #
85
151
  # use_refresh_token
86
152
 
87
- # Forbids creating/updating applications with arbitrary scopes that are
88
- # not in configuration, i.e. `default_scopes` or `optional_scopes`.
89
- # (disabled by default)
90
- #
91
- # enforce_configured_scopes
92
-
93
153
  # Provide support for an owner to be assigned to each registered application (disabled by default)
94
154
  # Optional parameter confirmation: true (default false) if you want to enforce ownership of
95
155
  # a registered application
96
- # Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
156
+ # NOTE: you must also run the rails g doorkeeper:application_owner generator
157
+ # to provide the necessary support
97
158
  #
98
159
  # enable_application_owner confirmation: false
99
160
 
@@ -104,6 +165,21 @@ Doorkeeper.configure do
104
165
  # default_scopes :public
105
166
  # optional_scopes :write, :update
106
167
 
168
+ # Define scopes_by_grant_type to restrict only certain scopes for grant_type
169
+ # By default, all the scopes will be available for all the grant types.
170
+ #
171
+ # Keys to this hash should be the name of grant_type and
172
+ # values should be the array of scopes for that grant type.
173
+ # Note: scopes should be from configured_scopes(i.e. deafult or optional)
174
+ #
175
+ # scopes_by_grant_type password: [:write], client_credentials: [:update]
176
+
177
+ # Forbids creating/updating applications with arbitrary scopes that are
178
+ # not in configuration, i.e. `default_scopes` or `optional_scopes`.
179
+ # (disabled by default)
180
+ #
181
+ # enforce_configured_scopes
182
+
107
183
  # Change the way client credentials are retrieved from the request object.
108
184
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
109
185
  # falls back to the `:client_id` and `:client_secret` params from the `params` object.
@@ -121,8 +197,10 @@ Doorkeeper.configure do
121
197
  # access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
122
198
 
123
199
  # Change the native redirect uri for client apps
124
- # When clients register with the following redirect uri, they won't be redirected to any server and the authorization code will be displayed within the provider
125
- # The value can be any string. Use nil to disable this feature. When disabled, clients must provide a valid URL
200
+ # When clients register with the following redirect uri, they won't be redirected to
201
+ # any server and the authorizationcode will be displayed within the provider
202
+ # The value can be any string. Use nil to disable this feature. When disabled, clients
203
+ # must providea valid URL
126
204
  # (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
127
205
  #
128
206
  # native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
@@ -147,6 +225,53 @@ Doorkeeper.configure do
147
225
  #
148
226
  # forbid_redirect_uri { |uri| uri.scheme.to_s.downcase == 'javascript' }
149
227
 
228
+ # Allows to set blank redirect URIs for Applications in case Doorkeeper configured
229
+ # to use URI-less OAuth grant flows like Client Credentials or Resource Owner
230
+ # Password Credentials. The option is on by default and checks configured grant
231
+ # types, but you **need** to manually drop `NOT NULL` constraint from `redirect_uri`
232
+ # column for `oauth_applications` database table.
233
+ #
234
+ # You can completely disable this feature with:
235
+ #
236
+ # allow_blank_redirect_uri false
237
+ #
238
+ # Or you can define your custom check:
239
+ #
240
+ # allow_blank_redirect_uri do |grant_flows, client|
241
+ # client.superapp?
242
+ # end
243
+
244
+ # Specify how authorization errors should be handled.
245
+ # By default, doorkeeper renders json errors when access token
246
+ # is invalid, expired, revoked or has invalid scopes.
247
+ #
248
+ # If you want to render error response yourself (i.e. rescue exceptions),
249
+ # set handle_auth_errors to `:raise` and rescue Doorkeeper::Errors::InvalidToken
250
+ # or following specific errors:
251
+ #
252
+ # Doorkeeper::Errors::TokenForbidden, Doorkeeper::Errors::TokenExpired,
253
+ # Doorkeeper::Errors::TokenRevoked, Doorkeeper::Errors::TokenUnknown
254
+ #
255
+ # handle_auth_errors :raise
256
+
257
+ # Customize token introspection response.
258
+ # Allows to add your own fields to default one that are required by the OAuth spec
259
+ # for the introspection response. It could be `sub`, `aud` and so on.
260
+ # This configuration option can be a proc, lambda or any Ruby object responds
261
+ # to `.call` method and result of it's invocation must be a Hash.
262
+ #
263
+ # custom_introspection_response do |token, context|
264
+ # {
265
+ # "sub": "Z5O3upPC88QrAjx00dis",
266
+ # "aud": "https://protected.example.net/resource",
267
+ # "username": User.find(token.resource_owner_id).username
268
+ # }
269
+ # end
270
+ #
271
+ # or
272
+ #
273
+ # custom_introspection_response CustomIntrospectionResponder
274
+
150
275
  # Specify what grant flows are enabled in array of Strings. The valid
151
276
  # strings and the flows they enable are:
152
277
  #
@@ -177,7 +302,7 @@ Doorkeeper.configure do
177
302
  # end
178
303
 
179
304
  # Hook into Authorization flow in order to implement Single Sign Out
180
- # or add ny other functionality.
305
+ # or add any other functionality.
181
306
  #
182
307
  # before_successful_authorization do |controller|
183
308
  # Rails.logger.info(params.inspect)
@@ -1,9 +1,13 @@
1
1
  class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  create_table :oauth_applications do |t|
4
- t.string :name, null: false
5
- t.string :uid, null: false
6
- t.string :secret, null: false
4
+ t.string :name, null: false
5
+ t.string :uid, null: false
6
+ t.string :secret, null: false
7
+
8
+ # Remove `null: false` if you are planning to use grant flows
9
+ # that doesn't require redirect URI to be used during authorization
10
+ # like Client Credentials flow or Resource Owner Password.
7
11
  t.text :redirect_uri, null: false
8
12
  t.string :scopes, null: false, default: ''
9
13
  t.boolean :confidential, null: false, default: true
@@ -13,7 +17,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
13
17
  add_index :oauth_applications, :uid, unique: true
14
18
 
15
19
  create_table :oauth_access_grants do |t|
16
- t.integer :resource_owner_id, null: false
20
+ t.references :resource_owner, null: false
17
21
  t.references :application, null: false
18
22
  t.string :token, null: false
19
23
  t.integer :expires_in, null: false
@@ -31,21 +35,21 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
31
35
  )
32
36
 
33
37
  create_table :oauth_access_tokens do |t|
34
- t.integer :resource_owner_id
35
- t.references :application
38
+ t.references :resource_owner, index: true
39
+ t.references :application, null: false
36
40
 
37
41
  # If you use a custom token generator you may need to change this column
38
42
  # from string to text, so that it accepts tokens larger than 255
39
43
  # characters. More info on custom token generators in:
40
44
  # https://github.com/doorkeeper-gem/doorkeeper/tree/v3.0.0.rc1#custom-access-token-generator
41
45
  #
42
- # t.text :token, null: false
43
- t.string :token, null: false
46
+ # t.text :token, null: false
47
+ t.string :token, null: false
44
48
 
45
49
  t.string :refresh_token
46
50
  t.integer :expires_in
47
51
  t.datetime :revoked_at
48
- t.datetime :created_at, null: false
52
+ t.datetime :created_at, null: false
49
53
  t.string :scopes
50
54
 
51
55
  # If there is a previous_refresh_token column,
@@ -58,12 +62,15 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
58
62
  end
59
63
 
60
64
  add_index :oauth_access_tokens, :token, unique: true
61
- add_index :oauth_access_tokens, :resource_owner_id
62
65
  add_index :oauth_access_tokens, :refresh_token, unique: true
63
66
  add_foreign_key(
64
67
  :oauth_access_tokens,
65
68
  :oauth_applications,
66
69
  column: :application_id
67
70
  )
71
+
72
+ # Uncomment below to ensure a valid reference to the resource owner's table
73
+ # add_foreign_key :oauth_access_grants, <model>, column: :resource_owner_id
74
+ # add_foreign_key :oauth_access_tokens, <model>, column: :resource_owner_id
68
75
  end
69
76
  end
@@ -2,14 +2,16 @@
2
2
 
3
3
  module Doorkeeper
4
4
  module Generators
5
+ # Generates doorkeeper views for Rails application
6
+ #
5
7
  class ViewsGenerator < ::Rails::Generators::Base
6
- source_root File.expand_path('../../../app/views', __dir__)
8
+ source_root File.expand_path("../../../app/views", __dir__)
7
9
 
8
- desc 'Copies default Doorkeeper views and layouts to your application.'
10
+ desc "Copies default Doorkeeper views and layouts to your application."
9
11
 
10
12
  def manifest
11
- directory 'doorkeeper', 'app/views/doorkeeper'
12
- directory 'layouts/doorkeeper', 'app/views/layouts/doorkeeper'
13
+ directory "doorkeeper", "app/views/doorkeeper"
14
+ directory "layouts/doorkeeper", "app/views/layouts/doorkeeper"
13
15
  end
14
16
  end
15
17
  end
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'spec_helper_integration'
3
+ require "spec_helper_integration"
4
4
 
5
5
  describe Doorkeeper::ApplicationMetalController do
6
6
  controller(Doorkeeper::ApplicationMetalController) do
7
7
  def index
8
8
  render json: {}, status: 200
9
9
  end
10
+
11
+ def create
12
+ render json: {}, status: 200
13
+ end
10
14
  end
11
15
 
12
16
  it "lazy run hooks" do
@@ -16,35 +20,45 @@ describe Doorkeeper::ApplicationMetalController do
16
20
  expect(i).to eq 1
17
21
  end
18
22
 
19
- describe 'enforce_content_type' do
23
+ describe "enforce_content_type" do
20
24
  before { allow(Doorkeeper.configuration).to receive(:enforce_content_type).and_return(flag) }
21
25
 
22
- context 'enabled' do
26
+ context "enabled" do
23
27
  let(:flag) { true }
24
28
 
25
- it '200 for the correct media type' do
26
- get :index, params: {}, as: :url_encoded_form
29
+ it "returns a 200 for the requests without body" do
30
+ get :index, params: {}
27
31
  expect(response).to have_http_status 200
28
32
  end
29
33
 
30
- it 'returns a 415 for an incorrect media type' do
31
- get :index, as: :json
34
+ it "returns a 200 for the requests with body and correct media type" do
35
+ post :create, params: {}, as: :url_encoded_form
36
+ expect(response).to have_http_status 200
37
+ end
38
+
39
+ it "returns a 415 for the requests with body and incorrect media type" do
40
+ post :create, params: {}, as: :json
32
41
  expect(response).to have_http_status 415
33
42
  end
34
43
  end
35
44
 
36
- context 'disabled' do
45
+ context "disabled" do
37
46
  let(:flag) { false }
38
47
 
39
- it 'returns a 200 for the correct media type' do
48
+ it "returns a 200 for the correct media type" do
40
49
  get :index, as: :url_encoded_form
41
50
  expect(response).to have_http_status 200
42
51
  end
43
52
 
44
- it 'returns a 200 for an incorrect media type' do
53
+ it "returns a 200 for an incorrect media type" do
45
54
  get :index, as: :json
46
55
  expect(response).to have_http_status 200
47
56
  end
57
+
58
+ it "returns a 200 for the requests with body and incorrect media type" do
59
+ post :create, params: {}, as: :json
60
+ expect(response).to have_http_status 200
61
+ end
48
62
  end
49
63
  end
50
64
  end
@@ -1,8 +1,10 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Doorkeeper
4
6
  describe ApplicationsController do
5
- context 'JSON API' do
7
+ context "JSON API" do
6
8
  render_views
7
9
 
8
10
  before do
@@ -10,81 +12,81 @@ module Doorkeeper
10
12
  allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
11
13
  end
12
14
 
13
- it 'creates an application' do
15
+ it "creates an application" do
14
16
  expect do
15
17
  post :create, params: {
16
- doorkeeper_application: {
17
- name: 'Example',
18
- redirect_uri: 'https://example.com'
19
- }, format: :json
20
- }
21
- end.to change { Doorkeeper::Application.count }
18
+ doorkeeper_application: {
19
+ name: "Example",
20
+ redirect_uri: "https://example.com",
21
+ }, format: :json,
22
+ }
23
+ end.to(change { Doorkeeper::Application.count })
22
24
 
23
25
  expect(response).to be_successful
24
26
 
25
- expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
27
+ expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
26
28
 
27
- expect(json_response['name']).to eq('Example')
28
- expect(json_response['redirect_uri']).to eq('https://example.com')
29
+ expect(json_response["name"]).to eq("Example")
30
+ expect(json_response["redirect_uri"]).to eq("https://example.com")
29
31
  end
30
32
 
31
- it 'returns validation errors on wrong create params' do
33
+ it "returns validation errors on wrong create params" do
32
34
  expect do
33
35
  post :create, params: {
34
- doorkeeper_application: {
35
- name: 'Example'
36
- }, format: :json
37
- }
38
- end.not_to change { Doorkeeper::Application.count }
36
+ doorkeeper_application: {
37
+ name: "Example",
38
+ }, format: :json,
39
+ }
40
+ end.not_to(change { Doorkeeper::Application.count })
39
41
 
40
42
  expect(response).to have_http_status(422)
41
43
 
42
- expect(json_response).to include('errors')
44
+ expect(json_response).to include("errors")
43
45
  end
44
46
 
45
- it 'returns application info' do
46
- application = FactoryBot.create(:application, name: 'Change me')
47
+ it "returns application info" do
48
+ application = FactoryBot.create(:application, name: "Change me")
47
49
 
48
50
  get :show, params: { id: application.id, format: :json }
49
51
 
50
52
  expect(response).to be_successful
51
53
 
52
- expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
54
+ expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
53
55
  end
54
56
 
55
- it 'updates application' do
56
- application = FactoryBot.create(:application, name: 'Change me')
57
+ it "updates application" do
58
+ application = FactoryBot.create(:application, name: "Change me")
57
59
 
58
60
  put :update, params: {
59
61
  id: application.id,
60
62
  doorkeeper_application: {
61
- name: 'Example App',
62
- redirect_uri: 'https://example.com'
63
- }, format: :json
63
+ name: "Example App",
64
+ redirect_uri: "https://example.com",
65
+ }, format: :json,
64
66
  }
65
67
 
66
- expect(application.reload.name).to eq 'Example App'
68
+ expect(application.reload.name).to eq "Example App"
67
69
 
68
- expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
70
+ expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
69
71
  end
70
72
 
71
- it 'returns validation errors on wrong update params' do
72
- application = FactoryBot.create(:application, name: 'Change me')
73
+ it "returns validation errors on wrong update params" do
74
+ application = FactoryBot.create(:application, name: "Change me")
73
75
 
74
76
  put :update, params: {
75
77
  id: application.id,
76
78
  doorkeeper_application: {
77
- name: 'Example App',
78
- redirect_uri: 'localhost:3000'
79
- }, format: :json
79
+ name: "Example App",
80
+ redirect_uri: "localhost:3000",
81
+ }, format: :json,
80
82
  }
81
83
 
82
84
  expect(response).to have_http_status(422)
83
85
 
84
- expect(json_response).to include('errors')
86
+ expect(json_response).to include("errors")
85
87
  end
86
88
 
87
- it 'destroys an application' do
89
+ it "destroys an application" do
88
90
  application = FactoryBot.create(:application)
89
91
 
90
92
  delete :destroy, params: { id: application.id, format: :json }
@@ -94,39 +96,38 @@ module Doorkeeper
94
96
  end
95
97
  end
96
98
 
97
- context 'when admin is not authenticated' do
99
+ context "when admin is not authenticated" do
98
100
  before do
99
101
  allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(proc do
100
102
  redirect_to main_app.root_url
101
103
  end)
102
104
  end
103
105
 
104
- it 'redirects as set in Doorkeeper.authenticate_admin' do
106
+ it "redirects as set in Doorkeeper.authenticate_admin" do
105
107
  get :index
106
108
  expect(response).to redirect_to(controller.main_app.root_url)
107
109
  end
108
110
 
109
- it 'does not create application' do
111
+ it "does not create application" do
110
112
  expect do
111
- post :create,
112
- params: {
113
- doorkeeper_application: {
114
- name: 'Example',
115
- redirect_uri: 'https://example.com'
116
- }
117
- }
118
- end.not_to change { Doorkeeper::Application.count }
113
+ post :create, params: {
114
+ doorkeeper_application: {
115
+ name: "Example",
116
+ redirect_uri: "https://example.com",
117
+ },
118
+ }
119
+ end.not_to(change { Doorkeeper::Application.count })
119
120
  end
120
121
  end
121
122
 
122
- context 'when admin is authenticated' do
123
+ context "when admin is authenticated" do
123
124
  render_views
124
125
 
125
126
  before do
126
127
  allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
127
128
  end
128
129
 
129
- it 'sorts applications by created_at' do
130
+ it "sorts applications by created_at" do
130
131
  first_application = FactoryBot.create(:application)
131
132
  second_application = FactoryBot.create(:application)
132
133
  expect(Doorkeeper::Application).to receive(:ordered_by).and_call_original
@@ -137,45 +138,42 @@ module Doorkeeper
137
138
  expect(response.body).to have_selector("tbody tr:last-child#application_#{second_application.id}")
138
139
  end
139
140
 
140
- it 'creates application' do
141
+ it "creates application" do
141
142
  expect do
142
- post :create,
143
- params: {
144
- doorkeeper_application: {
145
- name: 'Example',
146
- redirect_uri: 'https://example.com'
147
- }
148
- }
143
+ post :create, params: {
144
+ doorkeeper_application: {
145
+ name: "Example",
146
+ redirect_uri: "https://example.com",
147
+ },
148
+ }
149
149
  end.to change { Doorkeeper::Application.count }.by(1)
150
150
 
151
151
  expect(response).to be_redirect
152
152
  end
153
153
 
154
- it 'does not allow mass assignment of uid or secret' do
154
+ it "does not allow mass assignment of uid or secret" do
155
155
  application = FactoryBot.create(:application)
156
- put :update,
157
- params: {
158
- id: application.id,
159
- doorkeeper_application: {
160
- uid: '1A2B3C4D',
161
- secret: '1A2B3C4D'
162
- }
163
- }
164
-
165
- expect(application.reload.uid).not_to eq '1A2B3C4D'
156
+ put :update, params: {
157
+ id: application.id,
158
+ doorkeeper_application: {
159
+ uid: "1A2B3C4D",
160
+ secret: "1A2B3C4D",
161
+ },
162
+ }
163
+
164
+ expect(application.reload.uid).not_to eq "1A2B3C4D"
166
165
  end
167
166
 
168
- it 'updates application' do
167
+ it "updates application" do
169
168
  application = FactoryBot.create(:application)
170
- put :update,
171
- params: {
172
- id: application.id, doorkeeper_application: {
173
- name: 'Example',
174
- redirect_uri: 'https://example.com'
175
- }
176
- }
177
-
178
- expect(application.reload.name).to eq 'Example'
169
+ put :update, params: {
170
+ id: application.id, doorkeeper_application: {
171
+ name: "Example",
172
+ redirect_uri: "https://example.com",
173
+ },
174
+ }
175
+
176
+ expect(application.reload.name).to eq "Example"
179
177
  end
180
178
  end
181
179
  end