doorkeeper 4.4.3 → 5.0.0.rc1

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 (169) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +2 -0
  4. data/Appraisals +2 -2
  5. data/Gemfile +1 -1
  6. data/NEWS.md +36 -17
  7. data/README.md +85 -3
  8. data/Rakefile +6 -0
  9. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  10. data/app/controllers/doorkeeper/application_controller.rb +4 -3
  11. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  12. data/app/controllers/doorkeeper/applications_controller.rb +42 -22
  13. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  14. data/app/controllers/doorkeeper/authorized_applications_controller.rb +15 -1
  15. data/app/controllers/doorkeeper/tokens_controller.rb +12 -15
  16. data/app/helpers/doorkeeper/dashboard_helper.rb +7 -7
  17. data/app/validators/redirect_uri_validator.rb +3 -2
  18. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  19. data/app/views/doorkeeper/applications/_form.html.erb +25 -24
  20. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  21. data/app/views/doorkeeper/applications/index.html.erb +17 -7
  22. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  23. data/app/views/doorkeeper/applications/show.html.erb +6 -6
  24. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  25. data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
  26. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  27. data/config/locales/en.yml +9 -1
  28. data/doorkeeper.gemspec +0 -2
  29. data/gemfiles/rails_5_2.gemfile +1 -1
  30. data/lib/doorkeeper/config.rb +58 -35
  31. data/lib/doorkeeper/engine.rb +4 -0
  32. data/lib/doorkeeper/errors.rb +2 -5
  33. data/lib/doorkeeper/grape/helpers.rb +1 -1
  34. data/lib/doorkeeper/helpers/controller.rb +7 -2
  35. data/lib/doorkeeper/models/access_grant_mixin.rb +56 -0
  36. data/lib/doorkeeper/models/access_token_mixin.rb +38 -21
  37. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  38. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  39. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  40. data/lib/doorkeeper/oauth/authorization/token.rb +23 -6
  41. data/lib/doorkeeper/oauth/authorization_code_request.rb +27 -2
  42. data/lib/doorkeeper/oauth/base_request.rb +18 -8
  43. data/lib/doorkeeper/oauth/client/credentials.rb +1 -1
  44. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -1
  45. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -2
  46. data/lib/doorkeeper/oauth/error_response.rb +11 -3
  47. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  48. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -4
  49. data/lib/doorkeeper/oauth/pre_authorization.rb +41 -11
  50. data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -1
  51. data/lib/doorkeeper/oauth/scopes.rb +1 -1
  52. data/lib/doorkeeper/oauth/token.rb +5 -2
  53. data/lib/doorkeeper/oauth/token_introspection.rb +2 -2
  54. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  55. data/lib/doorkeeper/oauth.rb +13 -0
  56. data/lib/doorkeeper/orm/active_record/application.rb +13 -16
  57. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  58. data/lib/doorkeeper/orm/active_record.rb +2 -0
  59. data/lib/doorkeeper/rails/helpers.rb +2 -4
  60. data/lib/doorkeeper/rails/routes.rb +14 -6
  61. data/lib/doorkeeper/rake/db.rake +40 -0
  62. data/lib/doorkeeper/rake/setup.rake +6 -0
  63. data/lib/doorkeeper/rake.rb +14 -0
  64. data/lib/doorkeeper/request.rb +28 -28
  65. data/lib/doorkeeper/version.rb +5 -25
  66. data/lib/doorkeeper.rb +4 -17
  67. data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
  68. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  69. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  70. data/lib/generators/doorkeeper/migration_generator.rb +23 -18
  71. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  72. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
  73. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  74. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  75. data/lib/generators/doorkeeper/templates/initializer.rb +60 -9
  76. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  77. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  78. data/spec/controllers/applications_controller_spec.rb +126 -13
  79. data/spec/controllers/authorizations_controller_spec.rb +252 -49
  80. data/spec/controllers/protected_resources_controller_spec.rb +16 -16
  81. data/spec/controllers/token_info_controller_spec.rb +4 -12
  82. data/spec/controllers/tokens_controller_spec.rb +19 -73
  83. data/spec/dummy/app/assets/config/manifest.js +2 -0
  84. data/spec/dummy/config/environments/test.rb +4 -5
  85. data/spec/dummy/config/initializers/doorkeeper.rb +5 -4
  86. data/spec/dummy/config/initializers/new_framework_defaults.rb +4 -0
  87. data/spec/dummy/config/routes.rb +3 -42
  88. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  89. data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
  90. data/spec/dummy/db/schema.rb +36 -36
  91. data/spec/generators/application_owner_generator_spec.rb +1 -1
  92. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  93. data/spec/generators/install_generator_spec.rb +1 -1
  94. data/spec/generators/migration_generator_spec.rb +1 -1
  95. data/spec/generators/pkce_generator_spec.rb +43 -0
  96. data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
  97. data/spec/generators/views_generator_spec.rb +1 -1
  98. data/spec/grape/grape_integration_spec.rb +1 -1
  99. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  100. data/spec/lib/config_spec.rb +51 -31
  101. data/spec/lib/doorkeeper_spec.rb +1 -126
  102. data/spec/lib/models/expirable_spec.rb +0 -3
  103. data/spec/lib/models/revocable_spec.rb +0 -2
  104. data/spec/lib/models/scopes_spec.rb +0 -4
  105. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  106. data/spec/lib/oauth/authorization_code_request_spec.rb +9 -2
  107. data/spec/lib/oauth/base_request_spec.rb +16 -2
  108. data/spec/lib/oauth/base_response_spec.rb +1 -1
  109. data/spec/lib/oauth/client/credentials_spec.rb +1 -3
  110. data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
  111. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  112. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  113. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  114. data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
  115. data/spec/lib/oauth/client_spec.rb +0 -3
  116. data/spec/lib/oauth/code_request_spec.rb +4 -2
  117. data/spec/lib/oauth/error_response_spec.rb +0 -3
  118. data/spec/lib/oauth/error_spec.rb +0 -2
  119. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  120. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  121. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  122. data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -7
  123. data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
  124. data/spec/lib/oauth/password_access_token_request_spec.rb +37 -2
  125. data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
  126. data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
  127. data/spec/lib/oauth/scopes_spec.rb +0 -3
  128. data/spec/lib/oauth/token_request_spec.rb +4 -5
  129. data/spec/lib/oauth/token_response_spec.rb +0 -1
  130. data/spec/lib/oauth/token_spec.rb +37 -14
  131. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  132. data/spec/lib/request/strategy_spec.rb +0 -1
  133. data/spec/lib/server_spec.rb +1 -1
  134. data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
  135. data/spec/models/doorkeeper/access_token_spec.rb +50 -16
  136. data/spec/models/doorkeeper/application_spec.rb +1 -47
  137. data/spec/requests/applications/applications_request_spec.rb +89 -1
  138. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  139. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  140. data/spec/requests/endpoints/token_spec.rb +7 -5
  141. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
  142. data/spec/requests/flows/authorization_code_spec.rb +198 -2
  143. data/spec/requests/flows/client_credentials_spec.rb +46 -6
  144. data/spec/requests/flows/implicit_grant_errors_spec.rb +1 -1
  145. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  146. data/spec/requests/flows/password_spec.rb +56 -2
  147. data/spec/requests/flows/refresh_token_spec.rb +2 -2
  148. data/spec/requests/flows/revoke_token_spec.rb +11 -11
  149. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  150. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  151. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  152. data/spec/routing/custom_controller_routes_spec.rb +59 -7
  153. data/spec/routing/default_routes_spec.rb +2 -2
  154. data/spec/routing/scoped_routes_spec.rb +16 -2
  155. data/spec/spec_helper.rb +54 -3
  156. data/spec/spec_helper_integration.rb +2 -74
  157. data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
  158. data/spec/support/doorkeeper_rspec.rb +19 -0
  159. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  160. data/spec/support/helpers/request_spec_helper.rb +2 -2
  161. data/spec/support/helpers/url_helper.rb +7 -3
  162. data/spec/support/http_method_shim.rb +12 -16
  163. data/spec/validators/redirect_uri_validator_spec.rb +7 -1
  164. data/spec/version/version_spec.rb +3 -3
  165. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  166. metadata +33 -31
  167. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
  168. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
  169. data/spec/controllers/application_metal_controller.rb +0 -10
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8d8d3550d8406d4abb224c4960d1d6e8a0c4c706
4
- data.tar.gz: b12408cb8b0dc2b14ee69b57798943b5c1bfaa30
3
+ metadata.gz: 1294d2df3309f8b266a7b9de07d4ebf8dd96fe27
4
+ data.tar.gz: 9eea101d6a9b5e72412a373224e8160d0d4cd897
5
5
  SHA512:
6
- metadata.gz: 0674af950f6070d6457e09f73fc89736b092ae6595e484ca6e67e7f126912ea007509d9249fdc4eb01e66bf981c1e49da33712203d8428d10401a43faabd1cfd
7
- data.tar.gz: e447513c202dfde4c622b898da2a98dff64272193136fe399b890bb97488e7915156a2588caa6de3566db411f4c7dfa89e88be3a8b8d0a76511251f2f980c382
6
+ metadata.gz: a7146828263c150652126e56c7a4a177bfaecf44a02d93f7f630d99edbc5a91767e4e86964b52f68c590022ff85375dd5004b78cd621b386b9c767cc67b90a3c
7
+ data.tar.gz: 15d04141cfc2bc9161531bc5b2a5cd98ee55f8cb144b76878ffe7fffb790c6de380a3857cc30813cd979a6c301bec188da6554dcb04d2d2e910b2cb0f240e857
data/.gitignore CHANGED
@@ -17,3 +17,4 @@ gemfiles/*.lock
17
17
  /doc/
18
18
  /rdoc/
19
19
  coverage
20
+ *.gem
data/.travis.yml CHANGED
@@ -8,6 +8,7 @@ rvm:
8
8
  - 2.3
9
9
  - 2.4
10
10
  - 2.5
11
+ - ruby-2.6.0-preview1
11
12
 
12
13
  before_install:
13
14
  - gem update --system # Need for Ruby 2.5.0. https://github.com/travis-ci/travis-ci/issues/8978
@@ -21,6 +22,7 @@ gemfile:
21
22
  - gemfiles/rails_master.gemfile
22
23
 
23
24
  matrix:
25
+ fast_finish: true
24
26
  exclude:
25
27
  - gemfile: gemfiles/rails_5_0.gemfile
26
28
  rvm: 2.1
data/Appraisals CHANGED
@@ -4,12 +4,12 @@ end
4
4
 
5
5
  appraise "rails-5-0" do
6
6
  gem "rails", "~> 5.0.0"
7
- gem "rspec-rails", "~> 3.5"
7
+ gem "rspec-rails", "~> 3.7"
8
8
  end
9
9
 
10
10
  appraise "rails-5-1" do
11
11
  gem "rails", "~> 5.1.0"
12
- gem "rspec-rails", "~> 3.5"
12
+ gem "rspec-rails", "~> 3.7"
13
13
  end
14
14
 
15
15
  appraise "rails-master" do
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "rails", "~> 5.1"
3
+ gem "rails", "~> 5.2"
4
4
 
5
5
  gem "appraisal"
6
6
 
data/NEWS.md CHANGED
@@ -1,25 +1,44 @@
1
1
  # News
2
2
 
3
+ See https://github.com/doorkeeper-gem/doorkeeper/wiki/Migration-from-old-versions for
4
+ upgrade guides.
5
+
3
6
  User-visible changes worth mentioning.
4
7
 
5
8
  ## master
6
-
7
- ## 4.4.3
8
- - [#1143] Adds a config option opt_out_native_route_change to opt out of the
9
- breaking api changed introduced in
10
- https://github.com/doorkeeper-gem/doorkeeper/pull/1003
11
-
12
- ## 4.4.2
13
- - [#1130] Backport fix for native redirect_uri from 5.x.
14
-
15
- ## 4.4.1
16
-
17
- - [#1127] Backport token type to comply with the RFC6750 specification.
18
- - [#1125] Backport Quote surround I18n yes/no keys
19
-
20
- ## 4.4.0
21
-
22
- - [#1120] Backport security fix from 5.x for token revocation when using public clients
9
+ - [#1089] Removed enable_pkce_without_secret configuration option
10
+ - [#1102] Expiration time based on scopes
11
+ - [#1099] All the configuration variables in `Doorkeeper.configuration` now
12
+ always return a non-nil value (`true` or `false`)
13
+ - [#1099] ORM / Query optimization: Do not revoke the refresh token if it is not enabled
14
+ in `doorkeeper.rb`
15
+ - [#996] Expiration Time Base On Grant Type
16
+ - [#997] Allow PKCE authorization_code flow as specified in RFC7636
17
+ - [#907] Fix lookup for matching tokens in certain edge-cases
18
+ - [#992] Add API option to use Doorkeeper without management views for API only
19
+ Rails applications (`api_only`)
20
+ - [#1045] Validate redirect_uri as the native URI when making authorization code requests
21
+ - [#1048] Remove deprecated `Doorkeeper#configured?`, `Doorkeeper#database_installed?`, and
22
+ `Doorkeeper#installed?` method
23
+ - [#1031] Allow public clients to authenticate without `client_secret`. Define an app as
24
+ either public or private/confidential
25
+ - [#1010] Add configuration to enforce configured scopes (`default_scopes` and
26
+ `optional_scopes`) for applications
27
+ - [#1060] Ensure that the native redirect_uri parameter matches with redirect_uri of the client
28
+ - [#1064] Add :before_successful_authorization and :after_successful_authorization hooks
29
+ - [#1069] Upgrade Bootstrap to 4 for Admin
30
+ - [#1068] Add rake task to cleanup databases that can become large over time
31
+ - [#1072] AuthorizationsController: Memoize strategy.authorize_response result to enable
32
+ subclasses to use the response object.
33
+ - [#1075] Call `before_successful_authorization` and `after_successful_authorization` hooks
34
+ on `create` action as well as `new`
35
+ - [#1082] Fix #916: remember routes mapping and use it required places (fix error with
36
+ customized Token Info route).
37
+ - [#1086, #1088] Fix bug with receiving default scopes in the token even if they are
38
+ not present in the application scopes (use scopes intersection).
39
+ - [#1076] Add config to enforce content type to application/x-www-form-urlencoded
40
+ - Fix bug with `force_ssl_in_redirect_uri` when it breaks existing applications with an
41
+ SSL redirect_uri.
23
42
 
24
43
  ## 4.3.2
25
44
 
data/README.md CHANGED
@@ -19,6 +19,7 @@ Supported features:
19
19
  - [Implicit grant](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.2)
20
20
  - [Resource Owner Password Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.3)
21
21
  - [Client Credentials](http://tools.ietf.org/html/draft-ietf-oauth-v2-22#section-4.4)
22
+ - [Proof Key for Code Exchange](https://tools.ietf.org/html/rfc7636)
22
23
  - [OAuth 2.0 Token Revocation](http://tools.ietf.org/html/rfc7009)
23
24
  - [OAuth 2.0 Token Introspection](https://tools.ietf.org/html/rfc7662)
24
25
 
@@ -28,6 +29,7 @@ Please check the documentation for the version of doorkeeper you are using in:
28
29
  https://github.com/doorkeeper-gem/doorkeeper/releases
29
30
 
30
31
  - See the [wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki)
32
+ - See [upgrade guides](https://github.com/doorkeeper-gem/doorkeeper/wiki/Migration-from-old-versions)
31
33
  - For general questions, please post in [Stack Overflow](http://stackoverflow.com/questions/tagged/doorkeeper)
32
34
  - See [SECURITY.md](SECURITY.md) for this project's security disclose
33
35
  policy
@@ -44,9 +46,11 @@ https://github.com/doorkeeper-gem/doorkeeper/releases
44
46
  - [MongoDB](#mongodb)
45
47
  - [Sequel](#sequel)
46
48
  - [Couchbase](#couchbase)
49
+ - [API mode](#api-mode)
47
50
  - [Routes](#routes)
48
51
  - [Authenticating](#authenticating)
49
52
  - [Internationalization (I18n)](#internationalization-i18n)
53
+ - [Rake Tasks](#rake-tasks)
50
54
  - [Protecting resources with OAuth (a.k.a your API endpoint)](#protecting-resources-with-oauth-aka-your-api-endpoint)
51
55
  - [Ruby on Rails controllers](#ruby-on-rails-controllers)
52
56
  - [Grape endpoints](#grape-endpoints)
@@ -103,12 +107,26 @@ for each table that includes a `resource_owner_id` column:
103
107
  add_foreign_key :table_name, :users, column: :resource_owner_id
104
108
  ```
105
109
 
110
+ If you want to enable [PKCE flow] for mobile apps, you need to generate another
111
+ migration:
112
+
113
+ [PKCE flow]: https://tools.ietf.org/html/rfc7636
114
+
115
+ ```sh
116
+ rails generate doorkeeper:pkce
117
+ ```
118
+
106
119
  Then run migrations:
107
120
 
108
121
  ```sh
109
122
  rake db:migrate
110
123
  ```
111
124
 
125
+ Ensure to use non-confidential apps for pkce. PKCE is created, because
126
+ you cannot trust its apps' secret. So whatever app needs pkce: it means, it cannot
127
+ be a confidential app by design.
128
+
129
+
112
130
  Remember to add associations to your model so the related records are deleted.
113
131
  If you don't do this an `ActiveRecord::InvalidForeignKey`-error will be raised
114
132
  when you try to destroy a model with related access grants or access tokens.
@@ -146,6 +164,25 @@ Use [doorkeeper-couchbase] extension if you are using Couchbase database.
146
164
 
147
165
  [doorkeeper-couchbase]: https://github.com/acaprojects/doorkeeper-couchbase
148
166
 
167
+ ### API mode
168
+
169
+ By default Doorkeeper uses full Rails stack to provide all the OAuth 2 functionality
170
+ with additional features like administration area for managing applications. By the
171
+ way, starting from Doorkeeper 5 you can use API mode for your [API only Rails 5 applications](http://edgeguides.rubyonrails.org/api_app.html).
172
+ All you need is just to configure the gem to work in desired mode:
173
+
174
+ ``` ruby
175
+ Doorkeeper.configure do
176
+ # ...
177
+
178
+ api_only
179
+ end
180
+ ```
181
+
182
+ Keep in mind, that in this mode you will not be able to access `Applications` or
183
+ `Authorized Applications` controllers because they will be skipped. Also all the
184
+ redirects will be returned as JSON response with corresponding locations.
185
+
149
186
  ### Routes
150
187
 
151
188
  The installation script will also automatically add the Doorkeeper routes into
@@ -198,7 +235,36 @@ You may want to check other ways of authentication
198
235
 
199
236
  ### Internationalization (I18n)
200
237
 
201
- See language files in [the I18n repository](https://github.com/doorkeeper-gem/doorkeeper-i18n).
238
+ Doorkeeper support multiple languages. See language files in
239
+ [the I18n repository](https://github.com/doorkeeper-gem/doorkeeper-i18n).
240
+
241
+ ### Rake Tasks
242
+
243
+ If you are using `rake`, you can load rake tasks provided by this gem, by adding
244
+ the following line to your `Rakefile`:
245
+
246
+ ```ruby
247
+ Doorkeeper::Rake.load_tasks
248
+ ```
249
+
250
+ #### Cleaning up
251
+
252
+ By default Doorkeeper is retaining expired and revoked access tokens and grants.
253
+ This allows to keep an audit log of those records, but it also leads to the
254
+ corresponding tables to grow large over the lifetime of your application.
255
+
256
+ If you are concerned about those tables growing too large,
257
+ you can regularly run the following rake task to remove stale entries
258
+ from the database:
259
+
260
+ ```rake
261
+ rake doorkeeper:db:cleanup
262
+ ```
263
+
264
+ Note that this will remove tokens that are expired according to the configured TTL
265
+ in `Doorkeeper.configuration.access_token_expires_in`. The specific `expires_in`
266
+ value of each access token **is not considered**. The same is true for access
267
+ grants.
202
268
 
203
269
  ## Protecting resources with OAuth (a.k.a your API endpoint)
204
270
 
@@ -399,6 +465,22 @@ customize the controller used by the list or skip the controller all together.
399
465
  For more information see the page
400
466
  [in the wiki](https://github.com/doorkeeper-gem/doorkeeper/wiki/Customizing-routes).
401
467
 
468
+ By default, everybody can create application with any scopes. However,
469
+ you can enforce users to create applications only with configured scopes
470
+ (`default_scopes` and `optional_scopes` from the Doorkeeper initializer):
471
+
472
+ ```ruby
473
+ # config/initializers/doorkeeper.rb
474
+ Doorkeeper.configure do
475
+ # ...
476
+
477
+ default_scopes :read, :write
478
+ optional_scopes :create, :update
479
+
480
+ enforce_configured_scopes
481
+ end
482
+ ```
483
+
402
484
  ## Other customizations
403
485
 
404
486
  - [Associate users to OAuth applications (ownership)](https://github.com/doorkeeper-gem/doorkeeper/wiki/Associate-users-to-OAuth-applications-%28ownership%29)
@@ -412,7 +494,7 @@ Doorkeeper 4.3.0 it uses [ActiveSupport lazy loading hooks](http://api.rubyonrai
412
494
  to load models. There are [known issue](https://github.com/doorkeeper-gem/doorkeeper/issues/1043)
413
495
  with the `factory_bot_rails` gem (it executes factories building before `ActiveRecord::Base`
414
496
  is initialized using hooks in gem railtie, so you can catch a `uninitialized constant` error).
415
- It is recommended to use pure `factory_bot` gem to solve this problem.
497
+ It is recommended to use pure `factory_bot` gem to solve this problem.
416
498
 
417
499
  ## Upgrading
418
500
 
@@ -429,7 +511,7 @@ To run the local engine server:
429
511
 
430
512
  ```
431
513
  bundle install
432
- bundle exec rails server
514
+ bundle exec rake doorkeeper:server
433
515
  ````
434
516
 
435
517
  By default, it uses the latest Rails version with ActiveRecord. To run the
data/Rakefile CHANGED
@@ -15,6 +15,12 @@ namespace :doorkeeper do
15
15
  cd 'spec/dummy'
16
16
  system 'bundle exec rails g doorkeeper:install --force'
17
17
  end
18
+
19
+ desc 'Runs local test server'
20
+ task :server do
21
+ cd 'spec/dummy'
22
+ system 'bundle exec rails server'
23
+ end
18
24
  end
19
25
 
20
26
  Bundler::GemHelper.install_tasks
@@ -5,6 +5,6 @@
5
5
  *= require_tree .
6
6
  */
7
7
 
8
- td {
9
- vertical-align: middle !important;
8
+ .doorkeeper-admin .form-group > .field_with_errors {
9
+ width: 16.66667%;
10
10
  }
@@ -4,8 +4,9 @@ module Doorkeeper
4
4
 
5
5
  include Helpers::Controller
6
6
 
7
- protect_from_forgery with: :exception
8
-
9
- helper 'doorkeeper/dashboard'
7
+ unless Doorkeeper.configuration.api_only
8
+ protect_from_forgery with: :exception
9
+ helper 'doorkeeper/dashboard'
10
+ end
10
11
  end
11
12
  end
@@ -5,6 +5,7 @@ module Doorkeeper
5
5
  AbstractController::Rendering,
6
6
  ActionController::Rendering,
7
7
  ActionController::Renderers::All,
8
+ AbstractController::Callbacks,
8
9
  Helpers::Controller
9
10
  ].freeze
10
11
 
@@ -12,6 +13,9 @@ module Doorkeeper
12
13
  include mod
13
14
  end
14
15
 
16
+ before_action :enforce_content_type,
17
+ if: -> { Doorkeeper.configuration.enforce_content_type }
18
+
15
19
  ActiveSupport.run_load_hooks(:doorkeeper_metal_controller, self)
16
20
  end
17
21
  end
@@ -1,24 +1,25 @@
1
1
  module Doorkeeper
2
2
  class ApplicationsController < Doorkeeper::ApplicationController
3
- layout 'doorkeeper/admin'
3
+ layout 'doorkeeper/admin' unless Doorkeeper.configuration.api_only
4
4
 
5
5
  before_action :authenticate_admin!
6
- before_action :set_application, only: [:show, :edit, :update, :destroy]
6
+ before_action :set_application, only: %i[show edit update destroy]
7
7
 
8
8
  def index
9
- @applications = if Application.respond_to?(:ordered_by)
10
- Application.ordered_by(:created_at)
11
- else
12
- ActiveSupport::Deprecation.warn <<-MSG.squish
13
- Doorkeeper #{Doorkeeper.configuration.orm} extension must implement #ordered_by
14
- method for it's models as it will be used by default in Doorkeeper 5.
15
- MSG
16
-
17
- Application.all
18
- end
9
+ @applications = Application.ordered_by(:created_at)
10
+
11
+ respond_to do |format|
12
+ format.html
13
+ format.json { head :no_content }
14
+ end
19
15
  end
20
16
 
21
- def show; end
17
+ def show
18
+ respond_to do |format|
19
+ format.html
20
+ format.json { render json: @application }
21
+ end
22
+ end
22
23
 
23
24
  def new
24
25
  @application = Application.new
@@ -26,28 +27,47 @@ module Doorkeeper
26
27
 
27
28
  def create
28
29
  @application = Application.new(application_params)
30
+
29
31
  if @application.save
30
- flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
31
- redirect_to oauth_application_url(@application)
32
+ flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications create])
33
+
34
+ respond_to do |format|
35
+ format.html { redirect_to oauth_application_url(@application) }
36
+ format.json { render json: @application }
37
+ end
32
38
  else
33
- render :new
39
+ respond_to do |format|
40
+ format.html { render :new }
41
+ format.json { render json: { errors: @application.errors.full_messages }, status: :unprocessable_entity }
42
+ end
34
43
  end
35
44
  end
36
45
 
37
46
  def edit; end
38
47
 
39
48
  def update
40
- if @application.update_attributes(application_params)
41
- flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :update])
42
- redirect_to oauth_application_url(@application)
49
+ if @application.update(application_params)
50
+ flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications update])
51
+
52
+ respond_to do |format|
53
+ format.html { redirect_to oauth_application_url(@application) }
54
+ format.json { render json: @application }
55
+ end
43
56
  else
44
- render :edit
57
+ respond_to do |format|
58
+ format.html { render :edit }
59
+ format.json { render json: { errors: @application.errors.full_messages }, status: :unprocessable_entity }
60
+ end
45
61
  end
46
62
  end
47
63
 
48
64
  def destroy
49
- flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :destroy]) if @application.destroy
50
- redirect_to oauth_applications_url
65
+ flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications destroy]) if @application.destroy
66
+
67
+ respond_to do |format|
68
+ format.html { redirect_to oauth_applications_url }
69
+ format.json { head :no_content }
70
+ end
51
71
  end
52
72
 
53
73
  private
@@ -4,20 +4,15 @@ module Doorkeeper
4
4
 
5
5
  def new
6
6
  if pre_auth.authorizable?
7
- if skip_authorization? || matching_token?
8
- auth = authorization.authorize
9
- redirect_to auth.redirect_uri
10
- else
11
- render :new
12
- end
7
+ render_success
13
8
  else
14
- render :error
9
+ render_error
15
10
  end
16
11
  end
17
12
 
18
13
  # TODO: Handle raise invalid authorization
19
14
  def create
20
- redirect_or_render authorization.authorize
15
+ redirect_or_render authorize_response
21
16
  end
22
17
 
23
18
  def destroy
@@ -26,15 +21,45 @@ module Doorkeeper
26
21
 
27
22
  private
28
23
 
24
+ def render_success
25
+ if skip_authorization? || matching_token?
26
+ redirect_or_render authorize_response
27
+ elsif Doorkeeper.configuration.api_only
28
+ render json: pre_auth
29
+ else
30
+ render :new
31
+ end
32
+ end
33
+
34
+ def render_error
35
+ if Doorkeeper.configuration.api_only
36
+ render json: pre_auth.error_response.body[:error_description],
37
+ status: :bad_request
38
+ else
39
+ render :error
40
+ end
41
+ end
42
+
29
43
  def matching_token?
30
- AccessToken.matching_token_for pre_auth.client,
31
- current_resource_owner.id,
32
- pre_auth.scopes
44
+ token = AccessToken.matching_token_for(
45
+ pre_auth.client,
46
+ current_resource_owner.id,
47
+ pre_auth.scopes
48
+ )
49
+
50
+ token && token.accessible?
33
51
  end
34
52
 
35
53
  def redirect_or_render(auth)
36
54
  if auth.redirectable?
37
- redirect_to auth.redirect_uri
55
+ if Doorkeeper.configuration.api_only
56
+ render(
57
+ json: { status: :redirect, redirect_uri: auth.redirect_uri },
58
+ status: auth.status
59
+ )
60
+ else
61
+ redirect_to auth.redirect_uri
62
+ end
38
63
  else
39
64
  render json: auth.body, status: auth.status
40
65
  end
@@ -53,5 +78,23 @@ module Doorkeeper
53
78
  def strategy
54
79
  @strategy ||= server.authorization_request pre_auth.response_type
55
80
  end
81
+
82
+ def authorize_response
83
+ @authorize_response ||= begin
84
+ authorizable = pre_auth.authorizable?
85
+ before_successful_authorization if authorizable
86
+ auth = strategy.authorize
87
+ after_successful_authorization if authorizable
88
+ auth
89
+ end
90
+ end
91
+
92
+ def after_successful_authorization
93
+ Doorkeeper.configuration.after_successful_authorization.call(self)
94
+ end
95
+
96
+ def before_successful_authorization
97
+ Doorkeeper.configuration.before_successful_authorization.call(self)
98
+ end
56
99
  end
57
100
  end
@@ -4,11 +4,25 @@ module Doorkeeper
4
4
 
5
5
  def index
6
6
  @applications = Application.authorized_for(current_resource_owner)
7
+
8
+ respond_to do |format|
9
+ format.html
10
+ format.json { render json: @applications }
11
+ end
7
12
  end
8
13
 
9
14
  def destroy
10
15
  AccessToken.revoke_all_for params[:id], current_resource_owner
11
- redirect_to oauth_authorized_applications_url, notice: I18n.t(:notice, scope: [:doorkeeper, :flash, :authorized_applications, :destroy])
16
+
17
+ respond_to do |format|
18
+ format.html do
19
+ redirect_to oauth_authorized_applications_url, notice: I18n.t(
20
+ :notice, scope: %i[doorkeeper flash authorized_applications destroy]
21
+ )
22
+ end
23
+
24
+ format.json { render :no_content }
25
+ end
12
26
  end
13
27
  end
14
28
  end
@@ -17,9 +17,7 @@ module Doorkeeper
17
17
  # Doorkeeper does not use the token_type_hint logic described in the
18
18
  # RFC 7009 due to the refresh token implementation that is a field in
19
19
  # the access token model.
20
- if authorized?
21
- revoke_token
22
- end
20
+ revoke_token if authorized?
23
21
 
24
22
  # The authorization server responds with HTTP status code 200 if the token
25
23
  # has been revoked successfully or if the client submitted an invalid
@@ -58,22 +56,21 @@ module Doorkeeper
58
56
  # https://tools.ietf.org/html/rfc6749#section-2.1
59
57
  # https://tools.ietf.org/html/rfc7009
60
58
  def authorized?
61
- return unless token.present?
62
- # Client is confidential, therefore client authentication & authorization
63
- # is required
64
- if token.application_id? && token.application.confidential?
65
- # We authorize client by checking token's application
66
- server.client && server.client.application == token.application
67
- else
68
- # Client is public, authentication unnecessary
69
- true
59
+ if token.present?
60
+ # Client is confidential, therefore client authentication & authorization
61
+ # is required
62
+ if token.application_id?
63
+ # We authorize client by checking token's application
64
+ server.client && server.client.application == token.application
65
+ else
66
+ # Client is public, authentication unnecessary
67
+ true
68
+ end
70
69
  end
71
70
  end
72
71
 
73
72
  def revoke_token
74
- if token.accessible?
75
- token.revoke
76
- end
73
+ token.revoke if token.accessible?
77
74
  end
78
75
 
79
76
  def token
@@ -1,15 +1,15 @@
1
1
  module Doorkeeper
2
2
  module DashboardHelper
3
3
  def doorkeeper_errors_for(object, method)
4
- if object.errors[method].present?
5
- output = object.errors[method].map do |msg|
6
- content_tag(:span, class: 'help-block') do
7
- msg.capitalize
8
- end
9
- end
4
+ return if object.errors[method].blank?
10
5
 
11
- safe_join(output)
6
+ output = object.errors[method].map do |msg|
7
+ content_tag(:span, class: 'form-text') do
8
+ msg.capitalize
9
+ end
12
10
  end
11
+
12
+ safe_join(output)
13
13
  end
14
14
 
15
15
  def doorkeeper_submit_path(application)
@@ -34,11 +34,12 @@ class RedirectUriValidator < ActiveModel::EachValidator
34
34
 
35
35
  def invalid_ssl_uri?(uri)
36
36
  forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
37
+ non_https = uri.try(:scheme) == 'http'
37
38
 
38
39
  if forces_ssl.respond_to?(:call)
39
- forces_ssl.call(uri)
40
+ forces_ssl.call(uri) && non_https
40
41
  else
41
- forces_ssl && uri.try(:scheme) == 'http'
42
+ forces_ssl && non_https
42
43
  end
43
44
  end
44
45
  end
@@ -1,4 +1,6 @@
1
1
  <%- submit_btn_css ||= 'btn btn-link' %>
2
2
  <%= form_tag oauth_application_path(application), method: :delete do %>
3
- <%= submit_tag t('doorkeeper.applications.buttons.destroy'), onclick: "return confirm('#{ t('doorkeeper.applications.confirmations.destroy') }')", class: submit_btn_css %>
3
+ <%= submit_tag t('doorkeeper.applications.buttons.destroy'),
4
+ onclick: "return confirm('#{ t('doorkeeper.applications.confirmations.destroy') }')",
5
+ class: submit_btn_css %>
4
6
  <% end %>