doorkeeper 4.4.3 → 5.0.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 (181) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.gitlab-ci.yml +16 -0
  4. data/.travis.yml +2 -0
  5. data/Appraisals +2 -2
  6. data/Gemfile +1 -1
  7. data/NEWS.md +61 -8
  8. data/README.md +92 -9
  9. data/Rakefile +6 -0
  10. data/UPGRADE.md +2 -0
  11. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  12. data/app/controllers/doorkeeper/application_controller.rb +4 -3
  13. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  14. data/app/controllers/doorkeeper/applications_controller.rb +42 -22
  15. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  16. data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
  17. data/app/controllers/doorkeeper/tokens_controller.rb +2 -6
  18. data/app/helpers/doorkeeper/dashboard_helper.rb +7 -7
  19. data/app/validators/redirect_uri_validator.rb +3 -2
  20. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  21. data/app/views/doorkeeper/applications/_form.html.erb +25 -24
  22. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  23. data/app/views/doorkeeper/applications/index.html.erb +17 -7
  24. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  25. data/app/views/doorkeeper/applications/show.html.erb +6 -6
  26. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  27. data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
  28. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  29. data/config/locales/en.yml +10 -1
  30. data/doorkeeper.gemspec +18 -20
  31. data/gemfiles/rails_5_2.gemfile +1 -1
  32. data/gemfiles/rails_master.gemfile +4 -1
  33. data/lib/doorkeeper/config.rb +75 -39
  34. data/lib/doorkeeper/engine.rb +4 -0
  35. data/lib/doorkeeper/errors.rb +2 -5
  36. data/lib/doorkeeper/grape/helpers.rb +1 -1
  37. data/lib/doorkeeper/helpers/controller.rb +7 -2
  38. data/lib/doorkeeper/models/access_grant_mixin.rb +71 -0
  39. data/lib/doorkeeper/models/access_token_mixin.rb +39 -22
  40. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  41. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  42. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  43. data/lib/doorkeeper/oauth/authorization/token.rb +36 -14
  44. data/lib/doorkeeper/oauth/authorization_code_request.rb +27 -2
  45. data/lib/doorkeeper/oauth/base_request.rb +20 -9
  46. data/lib/doorkeeper/oauth/client/credentials.rb +1 -1
  47. data/lib/doorkeeper/oauth/client.rb +0 -2
  48. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
  49. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
  50. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
  51. data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
  52. data/lib/doorkeeper/oauth/error_response.rb +11 -3
  53. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  54. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -4
  55. data/lib/doorkeeper/oauth/pre_authorization.rb +41 -11
  56. data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -1
  57. data/lib/doorkeeper/oauth/scopes.rb +1 -1
  58. data/lib/doorkeeper/oauth/token.rb +5 -2
  59. data/lib/doorkeeper/oauth/token_introspection.rb +2 -2
  60. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  61. data/lib/doorkeeper/oauth.rb +13 -0
  62. data/lib/doorkeeper/orm/active_record/application.rb +22 -14
  63. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  64. data/lib/doorkeeper/orm/active_record.rb +2 -0
  65. data/lib/doorkeeper/rails/helpers.rb +2 -4
  66. data/lib/doorkeeper/rails/routes.rb +14 -6
  67. data/lib/doorkeeper/rake/db.rake +40 -0
  68. data/lib/doorkeeper/rake/setup.rake +6 -0
  69. data/lib/doorkeeper/rake.rb +14 -0
  70. data/lib/doorkeeper/request/authorization_code.rb +0 -2
  71. data/lib/doorkeeper/request/client_credentials.rb +0 -2
  72. data/lib/doorkeeper/request/code.rb +0 -2
  73. data/lib/doorkeeper/request/password.rb +0 -2
  74. data/lib/doorkeeper/request/refresh_token.rb +0 -2
  75. data/lib/doorkeeper/request/token.rb +0 -2
  76. data/lib/doorkeeper/request.rb +28 -35
  77. data/lib/doorkeeper/version.rb +5 -25
  78. data/lib/doorkeeper.rb +19 -17
  79. data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
  80. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  81. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  82. data/lib/generators/doorkeeper/migration_generator.rb +23 -18
  83. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  84. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
  85. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  86. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  87. data/lib/generators/doorkeeper/templates/initializer.rb +76 -11
  88. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  89. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  90. data/spec/controllers/applications_controller_spec.rb +126 -13
  91. data/spec/controllers/authorizations_controller_spec.rb +277 -47
  92. data/spec/controllers/protected_resources_controller_spec.rb +16 -16
  93. data/spec/controllers/token_info_controller_spec.rb +4 -12
  94. data/spec/controllers/tokens_controller_spec.rb +13 -15
  95. data/spec/dummy/app/assets/config/manifest.js +2 -0
  96. data/spec/dummy/config/environments/test.rb +4 -5
  97. data/spec/dummy/config/initializers/doorkeeper.rb +10 -5
  98. data/spec/dummy/config/initializers/new_framework_defaults.rb +4 -0
  99. data/spec/dummy/config/routes.rb +3 -42
  100. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  101. data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
  102. data/spec/dummy/db/schema.rb +36 -36
  103. data/spec/generators/application_owner_generator_spec.rb +1 -1
  104. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  105. data/spec/generators/install_generator_spec.rb +1 -1
  106. data/spec/generators/migration_generator_spec.rb +1 -1
  107. data/spec/generators/pkce_generator_spec.rb +43 -0
  108. data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
  109. data/spec/generators/views_generator_spec.rb +1 -1
  110. data/spec/grape/grape_integration_spec.rb +1 -1
  111. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  112. data/spec/lib/config_spec.rb +80 -31
  113. data/spec/lib/doorkeeper_spec.rb +1 -126
  114. data/spec/lib/models/expirable_spec.rb +0 -3
  115. data/spec/lib/models/revocable_spec.rb +0 -2
  116. data/spec/lib/models/scopes_spec.rb +0 -4
  117. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  118. data/spec/lib/oauth/authorization_code_request_spec.rb +9 -2
  119. data/spec/lib/oauth/base_request_spec.rb +40 -2
  120. data/spec/lib/oauth/base_response_spec.rb +1 -1
  121. data/spec/lib/oauth/client/credentials_spec.rb +1 -3
  122. data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
  123. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  124. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  125. data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
  126. data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
  127. data/spec/lib/oauth/client_spec.rb +0 -3
  128. data/spec/lib/oauth/code_request_spec.rb +4 -2
  129. data/spec/lib/oauth/error_response_spec.rb +0 -3
  130. data/spec/lib/oauth/error_spec.rb +0 -2
  131. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  132. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  133. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  134. data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -7
  135. data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
  136. data/spec/lib/oauth/password_access_token_request_spec.rb +37 -2
  137. data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
  138. data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
  139. data/spec/lib/oauth/scopes_spec.rb +0 -3
  140. data/spec/lib/oauth/token_request_spec.rb +4 -5
  141. data/spec/lib/oauth/token_response_spec.rb +0 -1
  142. data/spec/lib/oauth/token_spec.rb +37 -14
  143. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  144. data/spec/lib/request/strategy_spec.rb +0 -1
  145. data/spec/lib/server_spec.rb +1 -1
  146. data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
  147. data/spec/models/doorkeeper/access_token_spec.rb +66 -22
  148. data/spec/models/doorkeeper/application_spec.rb +14 -47
  149. data/spec/requests/applications/applications_request_spec.rb +134 -1
  150. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  151. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  152. data/spec/requests/endpoints/token_spec.rb +7 -5
  153. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
  154. data/spec/requests/flows/authorization_code_spec.rb +197 -1
  155. data/spec/requests/flows/client_credentials_spec.rb +46 -6
  156. data/spec/requests/flows/implicit_grant_errors_spec.rb +1 -1
  157. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  158. data/spec/requests/flows/password_spec.rb +56 -2
  159. data/spec/requests/flows/refresh_token_spec.rb +2 -2
  160. data/spec/requests/flows/revoke_token_spec.rb +11 -11
  161. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  162. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  163. data/spec/requests/protected_resources/private_api_spec.rb +1 -1
  164. data/spec/routing/custom_controller_routes_spec.rb +59 -7
  165. data/spec/routing/default_routes_spec.rb +2 -2
  166. data/spec/routing/scoped_routes_spec.rb +16 -2
  167. data/spec/spec_helper.rb +54 -3
  168. data/spec/spec_helper_integration.rb +2 -74
  169. data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
  170. data/spec/support/doorkeeper_rspec.rb +19 -0
  171. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  172. data/spec/support/helpers/request_spec_helper.rb +10 -2
  173. data/spec/support/helpers/url_helper.rb +7 -3
  174. data/spec/support/http_method_shim.rb +12 -16
  175. data/spec/validators/redirect_uri_validator_spec.rb +7 -1
  176. data/spec/version/version_spec.rb +3 -3
  177. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  178. metadata +37 -33
  179. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
  180. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
  181. data/spec/controllers/application_metal_controller.rb +0 -10
@@ -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 %>
@@ -1,58 +1,59 @@
1
- <%= form_for application, url: doorkeeper_submit_path(application), html: {class: 'form-horizontal', role: 'form'} do |f| %>
1
+ <%= form_for application, url: doorkeeper_submit_path(application), html: { role: 'form' } do |f| %>
2
2
  <% if application.errors.any? %>
3
3
  <div class="alert alert-danger" data-alert><p><%= t('doorkeeper.applications.form.error') %></p></div>
4
4
  <% end %>
5
5
 
6
- <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:name].present?}" do %>
7
- <%= f.label :name, class: 'col-sm-2 control-label' %>
6
+ <div class="form-group row">
7
+ <%= f.label :name, class: 'col-sm-2 col-form-label font-weight-bold' %>
8
8
  <div class="col-sm-10">
9
- <%= f.text_field :name, class: 'form-control' %>
9
+ <%= f.text_field :name, class: "form-control #{ 'is-invalid' if application.errors[:name].present? }", required: true %>
10
10
  <%= doorkeeper_errors_for application, :name %>
11
11
  </div>
12
- <% end %>
12
+ </div>
13
13
 
14
- <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:redirect_uri].present?}" do %>
15
- <%= f.label :redirect_uri, class: 'col-sm-2 control-label' %>
14
+ <div class="form-group row">
15
+ <%= f.label :redirect_uri, class: 'col-sm-2 col-form-label font-weight-bold' %>
16
16
  <div class="col-sm-10">
17
- <%= f.text_area :redirect_uri, class: 'form-control' %>
17
+ <%= f.text_area :redirect_uri, class: "form-control #{ 'is-invalid' if application.errors[:redirect_uri].present? }" %>
18
18
  <%= doorkeeper_errors_for application, :redirect_uri %>
19
- <span class="help-block">
19
+ <span class="form-text text-secondary">
20
20
  <%= t('doorkeeper.applications.help.redirect_uri') %>
21
21
  </span>
22
+
22
23
  <% if Doorkeeper.configuration.native_redirect_uri %>
23
- <span class="help-block">
24
- <%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code) { Doorkeeper.configuration.native_redirect_uri }) %>
24
+ <span class="form-text text-secondary">
25
+ <%= raw t('doorkeeper.applications.help.native_redirect_uri', native_redirect_uri: content_tag(:code, class: 'bg-light') { Doorkeeper.configuration.native_redirect_uri }) %>
25
26
  </span>
26
27
  <% end %>
27
28
  </div>
28
- <% end %>
29
+ </div>
29
30
 
30
- <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:confidential].present?}" do %>
31
- <%= f.label :confidential, class: 'col-sm-2 control-label' %>
31
+ <div class="form-group row">
32
+ <%= f.label :confidential, class: 'col-sm-2 form-check-label font-weight-bold' %>
32
33
  <div class="col-sm-10">
33
- <%= f.check_box :confidential, class: 'form-control', disabled: !Doorkeeper::Application.supports_confidentiality? %>
34
+ <%= f.check_box :confidential, class: "checkbox #{ 'is-invalid' if application.errors[:confidential].present? }" %>
34
35
  <%= doorkeeper_errors_for application, :confidential %>
35
- <span class="help-block">
36
+ <span class="form-text text-secondary">
36
37
  <%= t('doorkeeper.applications.help.confidential') %>
37
38
  </span>
38
39
  </div>
39
- <% end %>
40
+ </div>
40
41
 
41
- <%= content_tag :div, class: "form-group#{' has-error' if application.errors[:scopes].present?}" do %>
42
- <%= f.label :scopes, class: 'col-sm-2 control-label' %>
42
+ <div class="form-group row">
43
+ <%= f.label :scopes, class: 'col-sm-2 col-form-label font-weight-bold' %>
43
44
  <div class="col-sm-10">
44
- <%= f.text_field :scopes, class: 'form-control' %>
45
+ <%= f.text_field :scopes, class: "form-control #{ 'has-error' if application.errors[:scopes].present? }" %>
45
46
  <%= doorkeeper_errors_for application, :scopes %>
46
- <span class="help-block">
47
+ <span class="form-text text-secondary">
47
48
  <%= t('doorkeeper.applications.help.scopes') %>
48
49
  </span>
49
50
  </div>
50
- <% end %>
51
+ </div>
51
52
 
52
53
  <div class="form-group">
53
54
  <div class="col-sm-offset-2 col-sm-10">
54
- <%= f.submit t('doorkeeper.applications.buttons.submit'), class: "btn btn-primary" %>
55
- <%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, class: "btn btn-default" %>
55
+ <%= f.submit t('doorkeeper.applications.buttons.submit'), class: 'btn btn-primary' %>
56
+ <%= link_to t('doorkeeper.applications.buttons.cancel'), oauth_applications_path, class: 'btn btn-secondary' %>
56
57
  </div>
57
58
  </div>
58
59
  <% end %>
@@ -1,4 +1,4 @@
1
- <div class="page-header">
1
+ <div class="border-bottom mb-4">
2
2
  <h1><%= t('.title') %></h1>
3
3
  </div>
4
4
 
@@ -1,4 +1,4 @@
1
- <div class="page-header">
1
+ <div class="border-bottom mb-4">
2
2
  <h1><%= t('.title') %></h1>
3
3
  </div>
4
4
 
@@ -10,18 +10,28 @@
10
10
  <th><%= t('.name') %></th>
11
11
  <th><%= t('.callback_url') %></th>
12
12
  <th><%= t('.confidential') %></th>
13
- <th></th>
13
+ <th><%= t('.actions') %></th>
14
14
  <th></th>
15
15
  </tr>
16
16
  </thead>
17
17
  <tbody>
18
18
  <% @applications.each do |application| %>
19
19
  <tr id="application_<%= application.id %>">
20
- <td><%= link_to application.name, oauth_application_path(application) %></td>
21
- <td><%= application.redirect_uri %></td>
22
- <td><%= application.confidential? ? t('doorkeeper.applications.index.confidentiality.yes') : t('doorkeeper.applications.index.confidentiality.no') %></td>
23
- <td><%= link_to t('doorkeeper.applications.buttons.edit'), edit_oauth_application_path(application), class: 'btn btn-link' %></td>
24
- <td><%= render 'delete_form', application: application %></td>
20
+ <td class="align-middle">
21
+ <%= link_to application.name, oauth_application_path(application) %>
22
+ </td>
23
+ <td class="align-middle">
24
+ <%= simple_format(application.redirect_uri) %>
25
+ </td>
26
+ <td class="align-middle">
27
+ <%= application.confidential? ? t('doorkeeper.applications.index.confidentiality.yes') : t('doorkeeper.applications.index.confidentiality.no') %>
28
+ </td>
29
+ <td class="align-middle">
30
+ <%= link_to t('doorkeeper.applications.buttons.edit'), edit_oauth_application_path(application), class: 'btn btn-link' %>
31
+ </td>
32
+ <td class="align-middle">
33
+ <%= render 'delete_form', application: application %>
34
+ </td>
25
35
  </tr>
26
36
  <% end %>
27
37
  </tbody>
@@ -1,4 +1,4 @@
1
- <div class="page-header">
1
+ <div class="border-bottom mb-4">
2
2
  <h1><%= t('.title') %></h1>
3
3
  </div>
4
4
 
@@ -1,20 +1,20 @@
1
- <div class="page-header">
1
+ <div class="border-bottom mb-4">
2
2
  <h1><%= t('.title', name: @application.name) %></h1>
3
3
  </div>
4
4
 
5
5
  <div class="row">
6
6
  <div class="col-md-8">
7
7
  <h4><%= t('.application_id') %>:</h4>
8
- <p><code id="application_id"><%= @application.uid %></code></p>
8
+ <p><code class="bg-light" id="application_id"><%= @application.uid %></code></p>
9
9
 
10
10
  <h4><%= t('.secret') %>:</h4>
11
- <p><code id="secret"><%= @application.secret %></code></p>
11
+ <p><code class="bg-light" id="secret"><%= @application.secret %></code></p>
12
12
 
13
13
  <h4><%= t('.scopes') %>:</h4>
14
- <p><code id="scopes"><%= @application.scopes %></code></p>
14
+ <p><code class="bg-light" id="scopes"><%= @application.scopes.presence || raw('&nbsp;') %></code></p>
15
15
 
16
16
  <h4><%= t('.confidential') %>:</h4>
17
- <p><code id="confidential"><%= @application.confidential? %></code></p>
17
+ <p><code class="bg-light" id="confidential"><%= @application.confidential? %></code></p>
18
18
 
19
19
  <h4><%= t('.callback_urls') %>:</h4>
20
20
 
@@ -22,7 +22,7 @@
22
22
  <% @application.redirect_uri.split.each do |uri| %>
23
23
  <tr>
24
24
  <td>
25
- <code><%= uri %></code>
25
+ <code class="bg-light"><%= uri %></code>
26
26
  </td>
27
27
  <td>
28
28
  <%= link_to t('doorkeeper.applications.buttons.authorize'), oauth_authorization_path(client_id: @application.uid, redirect_uri: uri, response_type: 'code', scope: @application.scopes), class: 'btn btn-success', target: '_blank' %>
@@ -1,4 +1,4 @@
1
- <div class="page-header">
1
+ <div class="border-bottom mb-4">
2
2
  <h1><%= t('doorkeeper.authorizations.error.title') %></h1>
3
3
  </div>
4
4
 
@@ -26,6 +26,8 @@
26
26
  <%= hidden_field_tag :state, @pre_auth.state %>
27
27
  <%= hidden_field_tag :response_type, @pre_auth.response_type %>
28
28
  <%= hidden_field_tag :scope, @pre_auth.scope %>
29
+ <%= hidden_field_tag :code_challenge, @pre_auth.code_challenge %>
30
+ <%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method %>
29
31
  <%= submit_tag t('doorkeeper.authorizations.buttons.authorize'), class: "btn btn-success btn-lg btn-block" %>
30
32
  <% end %>
31
33
  <%= form_tag oauth_authorization_path, method: :delete do %>
@@ -34,6 +36,8 @@
34
36
  <%= hidden_field_tag :state, @pre_auth.state %>
35
37
  <%= hidden_field_tag :response_type, @pre_auth.response_type %>
36
38
  <%= hidden_field_tag :scope, @pre_auth.scope %>
39
+ <%= hidden_field_tag :code_challenge, @pre_auth.code_challenge %>
40
+ <%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method %>
37
41
  <%= submit_tag t('doorkeeper.authorizations.buttons.deny'), class: "btn btn-danger btn-lg btn-block" %>
38
42
  <% end %>
39
43
  </div>
@@ -4,27 +4,27 @@
4
4
  <meta charset="utf-8">
5
5
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
7
- <title>Doorkeeper</title>
7
+ <title><%= t('doorkeeper.layouts.admin.title') %></title>
8
8
  <%= stylesheet_link_tag "doorkeeper/admin/application" %>
9
9
  <%= csrf_meta_tags %>
10
10
  </head>
11
11
  <body>
12
- <div class="navbar navbar-inverse navbar-static-top" role="navigation">
13
- <div class="container-fluid">
14
- <div class="navbar-header">
15
- <%= link_to t('doorkeeper.layouts.admin.nav.oauth2_provider'), oauth_applications_path, class: 'navbar-brand' %>
16
- </div>
17
- <ul class="nav navbar-nav">
18
- <%= content_tag :li, class: "#{'active' if request.path == oauth_applications_path}" do %>
19
- <%= link_to t('doorkeeper.layouts.admin.nav.applications'), oauth_applications_path %>
20
- <% end %>
21
- <%= content_tag :li do %>
22
- <%= link_to t('doorkeeper.layouts.admin.nav.home'), root_path %>
23
- <% end %>
12
+ <nav class="navbar navbar-expand-lg navbar-dark bg-dark mb-5">
13
+ <%= link_to t('doorkeeper.layouts.admin.nav.oauth2_provider'), oauth_applications_path, class: 'navbar-brand' %>
14
+
15
+ <div class="collapse navbar-collapse">
16
+ <ul class="navbar-nav mr-auto">
17
+ <li class="nav-item <%= 'active' if request.path == oauth_applications_path %>">
18
+ <%= link_to t('doorkeeper.layouts.admin.nav.applications'), oauth_applications_path, class: 'nav-link' %>
19
+ </li>
20
+ <li class="nav-item">
21
+ <%= link_to t('doorkeeper.layouts.admin.nav.home'), root_path, class: 'nav-link' %>
22
+ </li>
24
23
  </ul>
25
24
  </div>
26
- </div>
27
- <div class="container">
25
+ </nav>
26
+
27
+ <div class="doorkeeper-admin container">
28
28
  <%- if flash[:notice].present? %>
29
29
  <div class="alert alert-info">
30
30
  <%= flash[:notice] %>
@@ -14,6 +14,8 @@ en:
14
14
  relative_uri: 'must be an absolute URI.'
15
15
  secured_uri: 'must be an HTTPS/SSL URI.'
16
16
  forbidden_uri: 'is forbidden by the server.'
17
+ scopes:
18
+ not_match_configured: "doesn't match configured on the server."
17
19
 
18
20
  doorkeeper:
19
21
  applications:
@@ -40,6 +42,7 @@ en:
40
42
  name: 'Name'
41
43
  callback_url: 'Callback URL'
42
44
  confidential: 'Confidential?'
45
+ actions: 'Actions'
43
46
  confidentiality:
44
47
  'yes': 'Yes'
45
48
  'no': 'No'
@@ -47,7 +50,7 @@ en:
47
50
  title: 'New Application'
48
51
  show:
49
52
  title: 'Application: %{name}'
50
- application_id: 'Application Id'
53
+ application_id: 'Application UID'
51
54
  secret: 'Secret'
52
55
  scopes: 'Scopes'
53
56
  confidential: 'Confidential'
@@ -78,6 +81,9 @@ en:
78
81
  created_at: 'Created At'
79
82
  date_format: '%Y-%m-%d %H:%M:%S'
80
83
 
84
+ pre_authorization:
85
+ status: 'Pre-authorization'
86
+
81
87
  errors:
82
88
  messages:
83
89
  # Common error messages
@@ -86,12 +92,14 @@ en:
86
92
  unauthorized_client: 'The client is not authorized to perform this request using this method.'
87
93
  access_denied: 'The resource owner or authorization server denied the request.'
88
94
  invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
95
+ invalid_code_challenge_method: 'The code challenge method must be plain or S256.'
89
96
  server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
90
97
  temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
91
98
 
92
99
  # Configuration error messages
93
100
  credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
94
101
  resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfigured.'
102
+ admin_authenticator_not_configured: 'Access to admin panel is forbidden due to Doorkeeper.configure.admin_authenticator being unconfigured.'
95
103
 
96
104
  # Access grant errors
97
105
  unsupported_response_type: 'The authorization server does not support this response type.'
@@ -120,6 +128,7 @@ en:
120
128
 
121
129
  layouts:
122
130
  admin:
131
+ title: 'Doorkeeper'
123
132
  nav:
124
133
  oauth2_provider: 'OAuth2 Provider'
125
134
  applications: 'Applications'
data/doorkeeper.gemspec CHANGED
@@ -1,32 +1,30 @@
1
- $LOAD_PATH.push File.expand_path("../lib", __FILE__)
1
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
2
2
 
3
- require "doorkeeper/version"
3
+ require 'doorkeeper/version'
4
4
 
5
5
  Gem::Specification.new do |s|
6
- s.name = "doorkeeper"
6
+ s.name = 'doorkeeper'
7
7
  s.version = Doorkeeper.gem_version
8
- s.authors = ["Felipe Elias Philipp", "Tute Costa", "Jon Moss", "Nikita Bulai"]
8
+ s.authors = ['Felipe Elias Philipp', 'Tute Costa', 'Jon Moss', 'Nikita Bulai']
9
9
  s.email = %w(bulaj.nikita@gmail.com)
10
- s.homepage = "https://github.com/doorkeeper-gem/doorkeeper"
11
- s.summary = "OAuth 2 provider for Rails and Grape"
12
- s.description = "Doorkeeper is an OAuth 2 provider for Rails and Grape."
10
+ s.homepage = 'https://github.com/doorkeeper-gem/doorkeeper'
11
+ s.summary = 'OAuth 2 provider for Rails and Grape'
12
+ s.description = 'Doorkeeper is an OAuth 2 provider for Rails and Grape.'
13
13
  s.license = 'MIT'
14
14
 
15
15
  s.files = `git ls-files`.split("\n")
16
16
  s.test_files = `git ls-files -- spec/*`.split("\n")
17
- s.require_paths = ["lib"]
17
+ s.require_paths = ['lib']
18
18
 
19
- s.add_dependency "railties", ">= 4.2"
20
- s.required_ruby_version = ">= 2.1"
19
+ s.add_dependency 'railties', '>= 4.2'
20
+ s.required_ruby_version = '>= 2.1'
21
21
 
22
- s.add_development_dependency "capybara"
23
- s.add_development_dependency "coveralls"
24
- s.add_development_dependency "grape"
25
- s.add_development_dependency "database_cleaner", "~> 1.6"
26
- s.add_development_dependency "factory_bot", "~> 4.8"
27
- s.add_development_dependency "generator_spec", "~> 0.9.3"
28
- s.add_development_dependency "rake", ">= 11.3.0"
29
- s.add_development_dependency "rspec-rails"
30
-
31
- s.post_install_message = Doorkeeper::CVE_2018_1000211_WARNING
22
+ s.add_development_dependency 'capybara', '~> 2.18'
23
+ s.add_development_dependency 'coveralls'
24
+ s.add_development_dependency 'grape'
25
+ s.add_development_dependency 'database_cleaner', '~> 1.6'
26
+ s.add_development_dependency 'factory_bot', '~> 4.8'
27
+ s.add_development_dependency 'generator_spec', '~> 0.9.3'
28
+ s.add_development_dependency 'rake', '>= 11.3.0'
29
+ s.add_development_dependency 'rspec-rails'
32
30
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "5.2.0.rc1"
5
+ gem "rails", "5.2.0"
6
6
  gem "appraisal"
7
7
  gem "activerecord-jdbcsqlite3-adapter", platforms: :jruby
8
8
  gem "sqlite3", platforms: [:ruby, :mswin, :mingw, :x64_mingw]
@@ -9,6 +9,9 @@ gem "appraisal"
9
9
  gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
10
10
  gem "sqlite3", platform: [:ruby, :mswin, :mingw, :x64_mingw]
11
11
  gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
12
- gem "rspec-rails", "~> 3.7"
12
+
13
+ %w[rspec-core rspec-expectations rspec-mocks rspec-rails rspec-support].each do |lib|
14
+ gem lib, git: "https://github.com/rspec/#{lib}.git", branch: 'master'
15
+ end
13
16
 
14
17
  gemspec path: "../"
@@ -15,19 +15,19 @@ module Doorkeeper
15
15
  end
16
16
 
17
17
  def self.configuration
18
- @config || (fail MissingConfiguration)
18
+ @config || (raise MissingConfiguration)
19
19
  end
20
20
 
21
21
  def self.setup_orm_adapter
22
22
  @orm_adapter = "doorkeeper/orm/#{configuration.orm}".classify.constantize
23
- rescue NameError => e
24
- fail e, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.squish
25
- [doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
26
- trying to load it.
27
-
28
- You probably need to add the related gem for this adapter to work with
29
- doorkeeper.
30
- ERROR_MSG
23
+ rescue NameError => error
24
+ raise error, "ORM adapter not found (#{configuration.orm})", <<-ERROR_MSG.strip_heredoc
25
+ [doorkeeper] ORM adapter not found (#{configuration.orm}), or there was an error
26
+ trying to load it.
27
+
28
+ You probably need to add the related gem for this adapter to work with
29
+ doorkeeper.
30
+ ERROR_MSG
31
31
  end
32
32
 
33
33
  def self.setup_orm_models
@@ -90,7 +90,7 @@ doorkeeper.
90
90
  #
91
91
  # @param methods [Array] Define client credentials
92
92
  def client_credentials(*methods)
93
- @config.instance_variable_set(:@client_credentials, methods)
93
+ @config.instance_variable_set(:@client_credentials_methods, methods)
94
94
  end
95
95
 
96
96
  # Change the way access token is authenticated from the request object.
@@ -103,9 +103,12 @@ doorkeeper.
103
103
  @config.instance_variable_set(:@access_token_methods, methods)
104
104
  end
105
105
 
106
- # Issue access tokens with refresh token (disabled by default)
107
- def use_refresh_token
108
- @config.instance_variable_set(:@refresh_token_enabled, true)
106
+ # Issue access tokens with refresh token (disabled if not set)
107
+ def use_refresh_token(enabled = true, &block)
108
+ @config.instance_variable_set(
109
+ :@refresh_token_enabled,
110
+ block ? block : enabled
111
+ )
109
112
  end
110
113
 
111
114
  # Reuse access token for the same resource owner within an application
@@ -115,13 +118,23 @@ doorkeeper.
115
118
  @config.instance_variable_set(:@reuse_access_token, true)
116
119
  end
117
120
 
118
- # Opt out of breaking api change to the native authorization code flow.
119
- # Opting out sets the authorization code response route for native
120
- # redirect uris to oauth/authorize/<code>. The default is
121
- # oauth/authorize/native?code=<code>.
122
- # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1143
123
- def opt_out_native_route_change
124
- @config.instance_variable_set(:@opt_out_native_route_change, true)
121
+ # Use an API mode for applications generated with --api argument
122
+ # It will skip applications controller, disable forgery protection
123
+ def api_only
124
+ @config.instance_variable_set(:@api_only, true)
125
+ end
126
+
127
+ # Forbids creating/updating applications with arbitrary scopes that are
128
+ # not in configuration, i.e. `default_scopes` or `optional_scopes`.
129
+ # (disabled by default)
130
+ def enforce_configured_scopes
131
+ @config.instance_variable_set(:@enforce_configured_scopes, true)
132
+ end
133
+
134
+ # Enforce request content type as the spec requires:
135
+ # disabled by default for backward compatibility.
136
+ def enforce_content_type
137
+ @config.instance_variable_set(:@enforce_content_type, true)
125
138
  end
126
139
  end
127
140
 
@@ -188,25 +201,39 @@ doorkeeper.
188
201
  option :resource_owner_authenticator,
189
202
  as: :authenticate_resource_owner,
190
203
  default: (lambda do |_routes|
191
- ::Rails.logger.warn(I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured'))
204
+ ::Rails.logger.warn(
205
+ I18n.t('doorkeeper.errors.messages.resource_owner_authenticator_not_configured')
206
+ )
207
+
192
208
  nil
193
209
  end)
194
210
 
195
211
  option :admin_authenticator,
196
212
  as: :authenticate_admin,
197
- default: ->(_routes) {}
213
+ default: (lambda do |_routes|
214
+ ::Rails.logger.warn(
215
+ I18n.t('doorkeeper.errors.messages.admin_authenticator_not_configured')
216
+ )
217
+
218
+ head :forbidden
219
+ end)
198
220
 
199
221
  option :resource_owner_from_credentials,
200
222
  default: (lambda do |_routes|
201
- ::Rails.logger.warn(I18n.t('doorkeeper.errors.messages.credential_flow_not_configured'))
223
+ ::Rails.logger.warn(
224
+ I18n.t('doorkeeper.errors.messages.credential_flow_not_configured')
225
+ )
226
+
202
227
  nil
203
228
  end)
229
+ option :before_successful_authorization, default: ->(_context) {}
230
+ option :after_successful_authorization, default: ->(_context) {}
204
231
  option :before_successful_strategy_response, default: ->(_request) {}
205
232
  option :after_successful_strategy_response,
206
233
  default: ->(_request, _response) {}
207
234
  option :skip_authorization, default: ->(_routes) {}
208
235
  option :access_token_expires_in, default: 7200
209
- option :custom_access_token_expires_in, default: ->(_app) { nil }
236
+ option :custom_access_token_expires_in, default: ->(_context) { nil }
210
237
  option :authorization_code_expires_in, default: 600
211
238
  option :orm, default: :active_record
212
239
  option :native_redirect_uri, default: 'urn:ietf:wg:oauth:2.0:oob'
@@ -241,7 +268,6 @@ doorkeeper.
241
268
  #
242
269
  option :force_ssl_in_redirect_uri, default: !Rails.env.development?
243
270
 
244
-
245
271
  # Use a custom class for generating the access token.
246
272
  # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
247
273
  #
@@ -260,20 +286,35 @@ doorkeeper.
260
286
  default: 'ActionController::Base'
261
287
 
262
288
  attr_reader :reuse_access_token
289
+ attr_reader :api_only
290
+ attr_reader :enforce_content_type
291
+
292
+ def api_only
293
+ @api_only ||= false
294
+ end
295
+
296
+ def enforce_content_type
297
+ @enforce_content_type ||= false
298
+ end
263
299
 
264
300
  def refresh_token_enabled?
265
- @refresh_token_enabled ||= false
266
- !!@refresh_token_enabled
301
+ if defined?(@refresh_token_enabled)
302
+ @refresh_token_enabled
303
+ else
304
+ false
305
+ end
306
+ end
307
+
308
+ def enforce_configured_scopes?
309
+ !!(defined?(@enforce_configured_scopes) && @enforce_configured_scopes)
267
310
  end
268
311
 
269
312
  def enable_application_owner?
270
- @enable_application_owner ||= false
271
- !!@enable_application_owner
313
+ !!(defined?(@enable_application_owner) && @enable_application_owner)
272
314
  end
273
315
 
274
316
  def confirm_application_owner?
275
- @confirm_application_owner ||= false
276
- !!@confirm_application_owner
317
+ !!(defined?(@confirm_application_owner) && @confirm_application_owner)
277
318
  end
278
319
 
279
320
  def default_scopes
@@ -289,7 +330,7 @@ doorkeeper.
289
330
  end
290
331
 
291
332
  def client_credentials_methods
292
- @client_credentials ||= %i[from_basic from_params]
333
+ @client_credentials_methods ||= %i[from_basic from_params]
293
334
  end
294
335
 
295
336
  def access_token_methods
@@ -297,16 +338,11 @@ doorkeeper.
297
338
  end
298
339
 
299
340
  def authorization_response_types
300
- @authorization_response_types ||= calculate_authorization_response_types
341
+ @authorization_response_types ||= calculate_authorization_response_types.freeze
301
342
  end
302
343
 
303
344
  def token_grant_types
304
- @token_grant_types ||= calculate_token_grant_types
305
- end
306
-
307
- def native_authorization_code_route
308
- @opt_out_native_route_change ||= false
309
- @opt_out_native_route_change ? '/:code' : '/native'
345
+ @token_grant_types ||= calculate_token_grant_types.freeze
310
346
  end
311
347
 
312
348
  private
@@ -17,6 +17,10 @@ module Doorkeeper
17
17
 
18
18
  if defined?(Sprockets) && Sprockets::VERSION.chr.to_i >= 4
19
19
  initializer 'doorkeeper.assets.precompile' do |app|
20
+ # Force users to use:
21
+ # //= link doorkeeper/admin/application.css
22
+ # in Doorkeeper 5 for Sprockets 4 instead of precompile.
23
+ # Add note to official docs & Wiki
20
24
  app.config.assets.precompile += %w[
21
25
  doorkeeper/application.css
22
26
  doorkeeper/admin/application.css