doorkeeper 4.4.0 → 5.6.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (284) hide show
  1. checksums.yaml +5 -5
  2. data/{NEWS.md → CHANGELOG.md} +471 -16
  3. data/README.md +108 -403
  4. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  5. data/app/controllers/doorkeeper/application_controller.rb +8 -5
  6. data/app/controllers/doorkeeper/application_metal_controller.rb +7 -11
  7. data/app/controllers/doorkeeper/applications_controller.rb +62 -27
  8. data/app/controllers/doorkeeper/authorizations_controller.rb +112 -18
  9. data/app/controllers/doorkeeper/authorized_applications_controller.rb +22 -3
  10. data/app/controllers/doorkeeper/token_info_controller.rb +16 -4
  11. data/app/controllers/doorkeeper/tokens_controller.rb +104 -35
  12. data/app/helpers/doorkeeper/dashboard_helper.rb +9 -7
  13. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  14. data/app/views/doorkeeper/applications/_form.html.erb +27 -26
  15. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  16. data/app/views/doorkeeper/applications/index.html.erb +17 -7
  17. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  18. data/app/views/doorkeeper/applications/show.html.erb +38 -17
  19. data/app/views/doorkeeper/authorizations/error.html.erb +4 -2
  20. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  21. data/app/views/doorkeeper/authorizations/new.html.erb +16 -10
  22. data/app/views/layouts/doorkeeper/admin.html.erb +16 -14
  23. data/config/locales/en.yml +28 -5
  24. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  25. data/lib/doorkeeper/config/option.rb +82 -0
  26. data/lib/doorkeeper/config/validations.rb +53 -0
  27. data/lib/doorkeeper/config.rb +477 -142
  28. data/lib/doorkeeper/engine.rb +17 -4
  29. data/lib/doorkeeper/errors.rb +25 -16
  30. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  31. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  32. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  33. data/lib/doorkeeper/grant_flow.rb +45 -0
  34. data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
  35. data/lib/doorkeeper/grape/helpers.rb +13 -7
  36. data/lib/doorkeeper/helpers/controller.rb +43 -10
  37. data/lib/doorkeeper/models/access_grant_mixin.rb +97 -3
  38. data/lib/doorkeeper/models/access_token_mixin.rb +273 -67
  39. data/lib/doorkeeper/models/application_mixin.rb +50 -5
  40. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  41. data/lib/doorkeeper/models/concerns/expirable.rb +7 -3
  42. data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
  43. data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
  44. data/lib/doorkeeper/models/concerns/ownership.rb +4 -7
  45. data/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +30 -0
  46. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  47. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  48. data/lib/doorkeeper/models/concerns/revocable.rb +3 -27
  49. data/lib/doorkeeper/models/concerns/scopes.rb +12 -2
  50. data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
  51. data/lib/doorkeeper/oauth/authorization/code.rb +54 -12
  52. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  53. data/lib/doorkeeper/oauth/authorization/token.rb +64 -24
  54. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +7 -5
  55. data/lib/doorkeeper/oauth/authorization_code_request.rb +69 -11
  56. data/lib/doorkeeper/oauth/base_request.rb +36 -24
  57. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  58. data/lib/doorkeeper/oauth/client/credentials.rb +5 -5
  59. data/lib/doorkeeper/oauth/client.rb +10 -11
  60. data/lib/doorkeeper/oauth/client_credentials/creator.rb +44 -4
  61. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +16 -9
  62. data/lib/doorkeeper/oauth/client_credentials/validator.rb +55 -0
  63. data/lib/doorkeeper/oauth/client_credentials_request.rb +10 -11
  64. data/lib/doorkeeper/oauth/code_request.rb +8 -12
  65. data/lib/doorkeeper/oauth/code_response.rb +27 -15
  66. data/lib/doorkeeper/oauth/error.rb +3 -1
  67. data/lib/doorkeeper/oauth/error_response.rb +34 -14
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +11 -3
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -18
  70. data/lib/doorkeeper/oauth/helpers/unique_token.rb +20 -3
  71. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +42 -6
  72. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  73. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  74. data/lib/doorkeeper/oauth/invalid_token_response.rb +29 -4
  75. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  76. data/lib/doorkeeper/oauth/password_access_token_request.rb +43 -10
  77. data/lib/doorkeeper/oauth/pre_authorization.rb +136 -26
  78. data/lib/doorkeeper/oauth/refresh_token_request.rb +67 -31
  79. data/lib/doorkeeper/oauth/scopes.rb +8 -4
  80. data/lib/doorkeeper/oauth/token.rb +12 -8
  81. data/lib/doorkeeper/oauth/token_introspection.rb +99 -25
  82. data/lib/doorkeeper/oauth/token_request.rb +8 -20
  83. data/lib/doorkeeper/oauth/token_response.rb +13 -10
  84. data/lib/doorkeeper/oauth.rb +13 -0
  85. data/lib/doorkeeper/orm/active_record/access_grant.rb +5 -30
  86. data/lib/doorkeeper/orm/active_record/access_token.rb +5 -43
  87. data/lib/doorkeeper/orm/active_record/application.rb +6 -57
  88. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +63 -0
  89. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +77 -0
  90. data/lib/doorkeeper/orm/active_record/mixins/application.rb +210 -0
  91. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  92. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +36 -0
  93. data/lib/doorkeeper/orm/active_record.rb +31 -20
  94. data/lib/doorkeeper/rails/helpers.rb +10 -8
  95. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  96. data/lib/doorkeeper/rails/routes/mapper.rb +4 -2
  97. data/lib/doorkeeper/rails/routes/mapping.rb +9 -7
  98. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  99. data/lib/doorkeeper/rails/routes.rb +45 -25
  100. data/lib/doorkeeper/rake/db.rake +40 -0
  101. data/lib/doorkeeper/rake/setup.rake +6 -0
  102. data/lib/doorkeeper/rake.rb +14 -0
  103. data/lib/doorkeeper/request/authorization_code.rb +6 -4
  104. data/lib/doorkeeper/request/client_credentials.rb +3 -3
  105. data/lib/doorkeeper/request/code.rb +1 -1
  106. data/lib/doorkeeper/request/password.rb +4 -3
  107. data/lib/doorkeeper/request/refresh_token.rb +6 -5
  108. data/lib/doorkeeper/request/strategy.rb +4 -2
  109. data/lib/doorkeeper/request/token.rb +1 -1
  110. data/lib/doorkeeper/request.rb +61 -34
  111. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  112. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  113. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  114. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  115. data/lib/doorkeeper/server.rb +9 -11
  116. data/lib/doorkeeper/stale_records_cleaner.rb +24 -0
  117. data/lib/doorkeeper/validations.rb +2 -0
  118. data/lib/doorkeeper/version.rb +7 -29
  119. data/lib/doorkeeper.rb +180 -65
  120. data/lib/generators/doorkeeper/application_owner_generator.rb +24 -18
  121. data/lib/generators/doorkeeper/confidential_applications_generator.rb +33 -0
  122. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  123. data/lib/generators/doorkeeper/install_generator.rb +19 -9
  124. data/lib/generators/doorkeeper/migration_generator.rb +23 -18
  125. data/lib/generators/doorkeeper/pkce_generator.rb +33 -0
  126. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +28 -22
  127. data/{spec/dummy/db/migrate/20180210183654_add_confidential_to_application.rb → lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb} +2 -2
  128. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  129. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  130. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +8 -0
  131. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  132. data/lib/generators/doorkeeper/templates/initializer.rb +402 -32
  133. data/lib/generators/doorkeeper/templates/migration.rb.erb +47 -18
  134. data/lib/generators/doorkeeper/views_generator.rb +8 -4
  135. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  136. metadata +97 -309
  137. data/.coveralls.yml +0 -1
  138. data/.github/ISSUE_TEMPLATE.md +0 -25
  139. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  140. data/.gitignore +0 -19
  141. data/.hound.yml +0 -2
  142. data/.rspec +0 -1
  143. data/.rubocop.yml +0 -17
  144. data/.travis.yml +0 -38
  145. data/Appraisals +0 -18
  146. data/CODE_OF_CONDUCT.md +0 -46
  147. data/CONTRIBUTING.md +0 -47
  148. data/Gemfile +0 -10
  149. data/RELEASING.md +0 -10
  150. data/Rakefile +0 -20
  151. data/SECURITY.md +0 -15
  152. data/app/validators/redirect_uri_validator.rb +0 -44
  153. data/doorkeeper.gemspec +0 -32
  154. data/gemfiles/rails_4_2.gemfile +0 -13
  155. data/gemfiles/rails_5_0.gemfile +0 -12
  156. data/gemfiles/rails_5_1.gemfile +0 -12
  157. data/gemfiles/rails_5_2.gemfile +0 -12
  158. data/gemfiles/rails_master.gemfile +0 -14
  159. data/lib/doorkeeper/oauth/client_credentials/validation.rb +0 -45
  160. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
  161. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
  162. data/spec/controllers/application_metal_controller.rb +0 -10
  163. data/spec/controllers/applications_controller_spec.rb +0 -69
  164. data/spec/controllers/authorizations_controller_spec.rb +0 -218
  165. data/spec/controllers/protected_resources_controller_spec.rb +0 -309
  166. data/spec/controllers/token_info_controller_spec.rb +0 -56
  167. data/spec/controllers/tokens_controller_spec.rb +0 -274
  168. data/spec/dummy/Rakefile +0 -7
  169. data/spec/dummy/app/controllers/application_controller.rb +0 -3
  170. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -7
  171. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -12
  172. data/spec/dummy/app/controllers/home_controller.rb +0 -17
  173. data/spec/dummy/app/controllers/metal_controller.rb +0 -11
  174. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -11
  175. data/spec/dummy/app/helpers/application_helper.rb +0 -5
  176. data/spec/dummy/app/models/user.rb +0 -5
  177. data/spec/dummy/app/views/home/index.html.erb +0 -0
  178. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  179. data/spec/dummy/config/application.rb +0 -23
  180. data/spec/dummy/config/boot.rb +0 -9
  181. data/spec/dummy/config/database.yml +0 -15
  182. data/spec/dummy/config/environment.rb +0 -5
  183. data/spec/dummy/config/environments/development.rb +0 -29
  184. data/spec/dummy/config/environments/production.rb +0 -62
  185. data/spec/dummy/config/environments/test.rb +0 -44
  186. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -7
  187. data/spec/dummy/config/initializers/doorkeeper.rb +0 -107
  188. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -6
  189. data/spec/dummy/config/initializers/secret_token.rb +0 -8
  190. data/spec/dummy/config/initializers/session_store.rb +0 -8
  191. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -14
  192. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  193. data/spec/dummy/config/routes.rb +0 -52
  194. data/spec/dummy/config.ru +0 -4
  195. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  196. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  197. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -62
  198. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  199. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  200. data/spec/dummy/db/schema.rb +0 -68
  201. data/spec/dummy/public/404.html +0 -26
  202. data/spec/dummy/public/422.html +0 -26
  203. data/spec/dummy/public/500.html +0 -26
  204. data/spec/dummy/public/favicon.ico +0 -0
  205. data/spec/dummy/script/rails +0 -6
  206. data/spec/factories.rb +0 -28
  207. data/spec/generators/application_owner_generator_spec.rb +0 -41
  208. data/spec/generators/install_generator_spec.rb +0 -31
  209. data/spec/generators/migration_generator_spec.rb +0 -41
  210. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -57
  211. data/spec/generators/templates/routes.rb +0 -3
  212. data/spec/generators/views_generator_spec.rb +0 -27
  213. data/spec/grape/grape_integration_spec.rb +0 -135
  214. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -24
  215. data/spec/lib/config_spec.rb +0 -437
  216. data/spec/lib/doorkeeper_spec.rb +0 -150
  217. data/spec/lib/models/expirable_spec.rb +0 -50
  218. data/spec/lib/models/revocable_spec.rb +0 -59
  219. data/spec/lib/models/scopes_spec.rb +0 -43
  220. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -41
  221. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -108
  222. data/spec/lib/oauth/base_request_spec.rb +0 -155
  223. data/spec/lib/oauth/base_response_spec.rb +0 -45
  224. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  225. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -44
  226. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -86
  227. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -54
  228. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  229. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -105
  230. data/spec/lib/oauth/client_spec.rb +0 -39
  231. data/spec/lib/oauth/code_request_spec.rb +0 -43
  232. data/spec/lib/oauth/code_response_spec.rb +0 -34
  233. data/spec/lib/oauth/error_response_spec.rb +0 -61
  234. data/spec/lib/oauth/error_spec.rb +0 -23
  235. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -23
  236. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -64
  237. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -20
  238. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -213
  239. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -56
  240. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -96
  241. data/spec/lib/oauth/pre_authorization_spec.rb +0 -155
  242. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -166
  243. data/spec/lib/oauth/scopes_spec.rb +0 -149
  244. data/spec/lib/oauth/token_request_spec.rb +0 -96
  245. data/spec/lib/oauth/token_response_spec.rb +0 -85
  246. data/spec/lib/oauth/token_spec.rb +0 -116
  247. data/spec/lib/request/strategy_spec.rb +0 -53
  248. data/spec/lib/server_spec.rb +0 -59
  249. data/spec/models/doorkeeper/access_grant_spec.rb +0 -36
  250. data/spec/models/doorkeeper/access_token_spec.rb +0 -418
  251. data/spec/models/doorkeeper/application_spec.rb +0 -286
  252. data/spec/requests/applications/applications_request_spec.rb +0 -94
  253. data/spec/requests/applications/authorized_applications_spec.rb +0 -30
  254. data/spec/requests/endpoints/authorization_spec.rb +0 -71
  255. data/spec/requests/endpoints/token_spec.rb +0 -71
  256. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -76
  257. data/spec/requests/flows/authorization_code_spec.rb +0 -149
  258. data/spec/requests/flows/client_credentials_spec.rb +0 -86
  259. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -32
  260. data/spec/requests/flows/implicit_grant_spec.rb +0 -61
  261. data/spec/requests/flows/password_spec.rb +0 -197
  262. data/spec/requests/flows/refresh_token_spec.rb +0 -174
  263. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  264. data/spec/requests/flows/skip_authorization_spec.rb +0 -59
  265. data/spec/requests/protected_resources/metal_spec.rb +0 -14
  266. data/spec/requests/protected_resources/private_api_spec.rb +0 -81
  267. data/spec/routing/custom_controller_routes_spec.rb +0 -75
  268. data/spec/routing/default_routes_spec.rb +0 -39
  269. data/spec/routing/scoped_routes_spec.rb +0 -31
  270. data/spec/spec_helper.rb +0 -4
  271. data/spec/spec_helper_integration.rb +0 -74
  272. data/spec/support/dependencies/factory_girl.rb +0 -2
  273. data/spec/support/helpers/access_token_request_helper.rb +0 -11
  274. data/spec/support/helpers/authorization_request_helper.rb +0 -41
  275. data/spec/support/helpers/config_helper.rb +0 -9
  276. data/spec/support/helpers/model_helper.rb +0 -72
  277. data/spec/support/helpers/request_spec_helper.rb +0 -88
  278. data/spec/support/helpers/url_helper.rb +0 -56
  279. data/spec/support/http_method_shim.rb +0 -38
  280. data/spec/support/orm/active_record.rb +0 -3
  281. data/spec/support/shared/controllers_shared_context.rb +0 -65
  282. data/spec/support/shared/models_shared_examples.rb +0 -52
  283. data/spec/validators/redirect_uri_validator_spec.rb +0 -123
  284. data/spec/version/version_spec.rb +0 -15
@@ -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), as: :doorkeeper_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
- <% 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 }) %>
25
- </span>
22
+
23
+ <% if Doorkeeper.configuration.allow_blank_redirect_uri?(application) %>
24
+ <span class="form-text text-secondary">
25
+ <%= t('doorkeeper.applications.help.blank_redirect_uri') %>
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,35 +1,56 @@
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>
12
+ <code class="bg-light" id="secret">
13
+ <% secret = flash[:application_secret].presence || @application.plaintext_secret %>
14
+ <% if secret.blank? && Doorkeeper.config.application_secret_hashed? %>
15
+ <span class="bg-light font-italic text-uppercase text-muted"><%= t('.secret_hashed') %></span>
16
+ <% else %>
17
+ <%= secret %>
18
+ <% end %>
19
+ </code>
20
+ </p>
12
21
 
13
22
  <h4><%= t('.scopes') %>:</h4>
14
- <p><code id="scopes"><%= @application.scopes %></code></p>
23
+ <p>
24
+ <code class="bg-light" id="scopes">
25
+ <% if @application.scopes.present? %>
26
+ <%= @application.scopes %>
27
+ <% else %>
28
+ <span class="bg-light font-italic text-uppercase text-muted"><%= t('.not_defined') %></span>
29
+ <% end %>
30
+ </code>
31
+ </p>
15
32
 
16
33
  <h4><%= t('.confidential') %>:</h4>
17
- <p><code id="confidential"><%= @application.confidential? %></code></p>
34
+ <p><code class="bg-light" id="confidential"><%= @application.confidential? %></code></p>
18
35
 
19
36
  <h4><%= t('.callback_urls') %>:</h4>
20
37
 
21
- <table>
22
- <% @application.redirect_uri.split.each do |uri| %>
23
- <tr>
24
- <td>
25
- <code><%= uri %></code>
26
- </td>
27
- <td>
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' %>
29
- </td>
30
- </tr>
31
- <% end %>
32
- </table>
38
+ <% if @application.redirect_uri.present? %>
39
+ <table>
40
+ <% @application.redirect_uri.split.each do |uri| %>
41
+ <tr>
42
+ <td>
43
+ <code class="bg-light"><%= uri %></code>
44
+ </td>
45
+ <td>
46
+ <%= 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' %>
47
+ </td>
48
+ </tr>
49
+ <% end %>
50
+ </table>
51
+ <% else %>
52
+ <span class="bg-light font-italic text-uppercase text-muted"><%= t('.not_defined') %></span>
53
+ <% end %>
33
54
  </div>
34
55
 
35
56
  <div class="col-md-4">
@@ -1,7 +1,9 @@
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
 
5
5
  <main role="main">
6
- <pre><%= @pre_auth.error_response.body[:error_description] %></pre>
6
+ <pre>
7
+ <%= (respond_to?(:error_response) ? error_response : @pre_auth.error_response).body[:error_description] %>
8
+ </pre>
7
9
  </main>
@@ -0,0 +1,15 @@
1
+ <header class="page-header">
2
+ <h1><%= t('.title') %></h1>
3
+ </header>
4
+
5
+ <%= form_tag @pre_auth.redirect_uri, method: :post, name: :redirect_form, authenticity_token: false do %>
6
+ <% @authorize_response.body.compact.each do |key, value| %>
7
+ <%= hidden_field_tag key, value %>
8
+ <% end %>
9
+ <% end %>
10
+
11
+ <script>
12
+ window.onload = function () {
13
+ document.forms['redirect_form'].submit();
14
+ };
15
+ </script>
@@ -21,19 +21,25 @@
21
21
 
22
22
  <div class="actions">
23
23
  <%= form_tag oauth_authorization_path, method: :post do %>
24
- <%= hidden_field_tag :client_id, @pre_auth.client.uid %>
25
- <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
26
- <%= hidden_field_tag :state, @pre_auth.state %>
27
- <%= hidden_field_tag :response_type, @pre_auth.response_type %>
28
- <%= hidden_field_tag :scope, @pre_auth.scope %>
24
+ <%= hidden_field_tag :client_id, @pre_auth.client.uid, id: nil %>
25
+ <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri, id: nil %>
26
+ <%= hidden_field_tag :state, @pre_auth.state, id: nil %>
27
+ <%= hidden_field_tag :response_type, @pre_auth.response_type, id: nil %>
28
+ <%= hidden_field_tag :response_mode, @pre_auth.response_mode, id: nil %>
29
+ <%= hidden_field_tag :scope, @pre_auth.scope, id: nil %>
30
+ <%= hidden_field_tag :code_challenge, @pre_auth.code_challenge, id: nil %>
31
+ <%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method, id: nil %>
29
32
  <%= submit_tag t('doorkeeper.authorizations.buttons.authorize'), class: "btn btn-success btn-lg btn-block" %>
30
33
  <% end %>
31
34
  <%= form_tag oauth_authorization_path, method: :delete do %>
32
- <%= hidden_field_tag :client_id, @pre_auth.client.uid %>
33
- <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri %>
34
- <%= hidden_field_tag :state, @pre_auth.state %>
35
- <%= hidden_field_tag :response_type, @pre_auth.response_type %>
36
- <%= hidden_field_tag :scope, @pre_auth.scope %>
35
+ <%= hidden_field_tag :client_id, @pre_auth.client.uid, id: nil %>
36
+ <%= hidden_field_tag :redirect_uri, @pre_auth.redirect_uri, id: nil %>
37
+ <%= hidden_field_tag :state, @pre_auth.state, id: nil %>
38
+ <%= hidden_field_tag :response_type, @pre_auth.response_type, id: nil %>
39
+ <%= hidden_field_tag :response_mode, @pre_auth.response_mode, id: nil %>
40
+ <%= hidden_field_tag :scope, @pre_auth.scope, id: nil %>
41
+ <%= hidden_field_tag :code_challenge, @pre_auth.code_challenge, id: nil %>
42
+ <%= hidden_field_tag :code_challenge_method, @pre_auth.code_challenge_method, id: nil %>
37
43
  <%= submit_tag t('doorkeeper.authorizations.buttons.deny'), class: "btn btn-danger btn-lg btn-block" %>
38
44
  <% end %>
39
45
  </div>
@@ -4,27 +4,29 @@
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 %>
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
+ <% if respond_to?(:root_path) %>
21
+ <li class="nav-item">
22
+ <%= link_to t('doorkeeper.layouts.admin.nav.home'), root_path, class: 'nav-link' %>
23
+ </li>
23
24
  <% end %>
24
25
  </ul>
25
26
  </div>
26
- </div>
27
- <div class="container">
27
+ </nav>
28
+
29
+ <div class="doorkeeper-admin container">
28
30
  <%- if flash[:notice].present? %>
29
31
  <div class="alert alert-info">
30
32
  <%= flash[:notice] %>
@@ -11,9 +11,12 @@ en:
11
11
  redirect_uri:
12
12
  fragment_present: 'cannot contain a fragment.'
13
13
  invalid_uri: 'must be a valid URI.'
14
+ unspecified_scheme: 'must specify a scheme.'
14
15
  relative_uri: 'must be an absolute URI.'
15
16
  secured_uri: 'must be an HTTPS/SSL URI.'
16
17
  forbidden_uri: 'is forbidden by the server.'
18
+ scopes:
19
+ not_match_configured: "doesn't match configured on the server."
17
20
 
18
21
  doorkeeper:
19
22
  applications:
@@ -30,7 +33,7 @@ en:
30
33
  help:
31
34
  confidential: 'Application will be used where the client secret can be kept confidential. Native mobile apps and Single Page Apps are considered non-confidential.'
32
35
  redirect_uri: 'Use one line per URI'
33
- native_redirect_uri: 'Use %{native_redirect_uri} if you want to add localhost URIs for development purposes'
36
+ blank_redirect_uri: "Leave it blank if you configured your provider to use Client Credentials, Resource Owner Password Credentials or any other grant type that doesn't require redirect URI."
34
37
  scopes: 'Separate scopes with spaces. Leave blank to use the default scopes.'
35
38
  edit:
36
39
  title: 'Edit application'
@@ -40,19 +43,22 @@ en:
40
43
  name: 'Name'
41
44
  callback_url: 'Callback URL'
42
45
  confidential: 'Confidential?'
46
+ actions: 'Actions'
43
47
  confidentiality:
44
- yes: 'Yes'
45
- no: 'No'
48
+ 'yes': 'Yes'
49
+ 'no': 'No'
46
50
  new:
47
51
  title: 'New Application'
48
52
  show:
49
53
  title: 'Application: %{name}'
50
- application_id: 'Application Id'
54
+ application_id: 'UID'
51
55
  secret: 'Secret'
56
+ secret_hashed: 'Secret hashed'
52
57
  scopes: 'Scopes'
53
58
  confidential: 'Confidential'
54
59
  callback_urls: 'Callback urls'
55
60
  actions: 'Actions'
61
+ not_defined: 'Not defined'
56
62
 
57
63
  authorizations:
58
64
  buttons:
@@ -66,6 +72,8 @@ en:
66
72
  able_to: 'This application will be able to'
67
73
  show:
68
74
  title: 'Authorization code'
75
+ form_post:
76
+ title: 'Submit this form'
69
77
 
70
78
  authorized_applications:
71
79
  confirmations:
@@ -78,23 +86,32 @@ en:
78
86
  created_at: 'Created At'
79
87
  date_format: '%Y-%m-%d %H:%M:%S'
80
88
 
89
+ pre_authorization:
90
+ status: 'Pre-authorization'
91
+
81
92
  errors:
82
93
  messages:
83
94
  # Common error messages
84
- invalid_request: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
95
+ invalid_request:
96
+ unknown: 'The request is missing a required parameter, includes an unsupported parameter value, or is otherwise malformed.'
97
+ missing_param: 'Missing required parameter: %{value}.'
98
+ request_not_authorized: 'Request need to be authorized. Required parameter for authorizing request is missing or invalid.'
85
99
  invalid_redirect_uri: "The requested redirect uri is malformed or doesn't match client redirect URI."
86
100
  unauthorized_client: 'The client is not authorized to perform this request using this method.'
87
101
  access_denied: 'The resource owner or authorization server denied the request.'
88
102
  invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
103
+ invalid_code_challenge_method: 'The code challenge method must be plain or S256.'
89
104
  server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
90
105
  temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
91
106
 
92
107
  # Configuration error messages
93
108
  credential_flow_not_configured: 'Resource Owner Password Credentials flow failed due to Doorkeeper.configure.resource_owner_from_credentials being unconfigured.'
94
109
  resource_owner_authenticator_not_configured: 'Resource Owner find failed due to Doorkeeper.configure.resource_owner_authenticator being unconfigured.'
110
+ admin_authenticator_not_configured: 'Access to admin panel is forbidden due to Doorkeeper.configure.admin_authenticator being unconfigured.'
95
111
 
96
112
  # Access grant errors
97
113
  unsupported_response_type: 'The authorization server does not support this response type.'
114
+ unsupported_response_mode: 'The authorization server does not support this response mode.'
98
115
 
99
116
  # Access token errors
100
117
  invalid_client: 'Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method.'
@@ -105,6 +122,11 @@ en:
105
122
  revoked: "The access token was revoked"
106
123
  expired: "The access token expired"
107
124
  unknown: "The access token is invalid"
125
+ revoke:
126
+ unauthorized: "You are not authorized to revoke this token"
127
+
128
+ forbidden_token:
129
+ missing_scope: 'Access to this resource requires scope "%{oauth_scopes}".'
108
130
 
109
131
  flash:
110
132
  applications:
@@ -120,6 +142,7 @@ en:
120
142
 
121
143
  layouts:
122
144
  admin:
145
+ title: 'Doorkeeper'
123
146
  nav:
124
147
  oauth2_provider: 'OAuth2 Provider'
125
148
  applications: 'Applications'
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ class Config
5
+ # Abstract base class for Doorkeeper and it's extensions configuration
6
+ # builder. Instantiates and validates gem configuration.
7
+ #
8
+ class AbstractBuilder
9
+ attr_reader :config
10
+
11
+ # @param [Class] config class
12
+ #
13
+ def initialize(config = Config.new, &block)
14
+ @config = config
15
+ instance_eval(&block) if block_given?
16
+ end
17
+
18
+ # Builds and validates configuration.
19
+ #
20
+ # @return [Doorkeeper::Config] config instance
21
+ #
22
+ def build
23
+ @config.validate! if @config.respond_to?(:validate!)
24
+ @config
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ class Config
5
+ # Doorkeeper configuration option DSL
6
+ module Option
7
+ # Defines configuration option
8
+ #
9
+ # When you call option, it defines two methods. One method will take place
10
+ # in the +Config+ class and the other method will take place in the
11
+ # +Builder+ class.
12
+ #
13
+ # The +name+ parameter will set both builder method and config attribute.
14
+ # If the +:as+ option is defined, the builder method will be the specified
15
+ # option while the config attribute will be the +name+ parameter.
16
+ #
17
+ # If you want to introduce another level of config DSL you can
18
+ # define +builder_class+ parameter.
19
+ # Builder should take a block as the initializer parameter and respond to function +build+
20
+ # that returns the value of the config attribute.
21
+ #
22
+ # ==== Options
23
+ #
24
+ # * [:+as+] Set the builder method that goes inside +configure+ block
25
+ # * [+:default+] The default value in case no option was set
26
+ # * [+:builder_class+] Configuration option builder class
27
+ #
28
+ # ==== Examples
29
+ #
30
+ # option :name
31
+ # option :name, as: :set_name
32
+ # option :name, default: 'My Name'
33
+ # option :scopes builder_class: ScopesBuilder
34
+ #
35
+ def option(name, options = {})
36
+ attribute = options[:as] || name
37
+ attribute_builder = options[:builder_class]
38
+
39
+ builder_class.instance_eval do
40
+ if method_defined?(name)
41
+ Kernel.warn "[DOORKEEPER] Option #{name} already defined and will be overridden"
42
+ remove_method name
43
+ end
44
+
45
+ define_method name do |*args, &block|
46
+ if (deprecation_opts = options[:deprecated])
47
+ warning = "[DOORKEEPER] #{name} has been deprecated and will soon be removed"
48
+ warning = "#{warning}\n#{deprecation_opts.fetch(:message)}" if deprecation_opts.is_a?(Hash)
49
+
50
+ Kernel.warn(warning)
51
+ end
52
+
53
+ value = if attribute_builder
54
+ attribute_builder.new(&block).build
55
+ else
56
+ block || args.first
57
+ end
58
+
59
+ @config.instance_variable_set(:"@#{attribute}", value)
60
+ end
61
+ end
62
+
63
+ define_method attribute do |*_args|
64
+ if instance_variable_defined?(:"@#{attribute}")
65
+ instance_variable_get(:"@#{attribute}")
66
+ else
67
+ options[:default]
68
+ end
69
+ end
70
+
71
+ public attribute
72
+ end
73
+
74
+ def self.extended(base)
75
+ return if base.respond_to?(:builder_class)
76
+
77
+ raise Doorkeeper::MissingConfigurationBuilderClass, "Define `self.builder_class` method " \
78
+ "for #{base} that returns your custom Builder class to use options DSL!"
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ class Config
5
+ # Doorkeeper configuration validator.
6
+ #
7
+ module Validations
8
+ # Validates configuration options to be set properly.
9
+ #
10
+ def validate!
11
+ validate_reuse_access_token_value
12
+ validate_token_reuse_limit
13
+ validate_secret_strategies
14
+ end
15
+
16
+ private
17
+
18
+ # Determine whether +reuse_access_token+ and a non-restorable
19
+ # +token_secret_strategy+ have both been activated.
20
+ #
21
+ # In that case, disable reuse_access_token value and warn the user.
22
+ def validate_reuse_access_token_value
23
+ strategy = token_secret_strategy
24
+ return if !reuse_access_token || strategy.allows_restoring_secrets?
25
+
26
+ ::Rails.logger.warn(
27
+ "[DOORKEEPER] You have configured both reuse_access_token " \
28
+ "AND '#{strategy}' strategy which cannot restore tokens. " \
29
+ "This combination is unsupported. reuse_access_token will be disabled",
30
+ )
31
+ @reuse_access_token = false
32
+ end
33
+
34
+ # Validate that the provided strategies are valid for
35
+ # tokens and applications
36
+ def validate_secret_strategies
37
+ token_secret_strategy.validate_for(:token)
38
+ application_secret_strategy.validate_for(:application)
39
+ end
40
+
41
+ def validate_token_reuse_limit
42
+ return if !reuse_access_token ||
43
+ (token_reuse_limit > 0 && token_reuse_limit <= 100)
44
+
45
+ ::Rails.logger.warn(
46
+ "[DOORKEEPER] You have configured an invalid value for token_reuse_limit option. " \
47
+ "It will be set to default 100",
48
+ )
49
+ @token_reuse_limit = 100
50
+ end
51
+ end
52
+ end
53
+ end