doorkeeper 4.4.3 → 5.0.3

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 (223) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.gitlab-ci.yml +16 -0
  4. data/.travis.yml +7 -0
  5. data/Appraisals +2 -2
  6. data/Dangerfile +64 -0
  7. data/Gemfile +1 -1
  8. data/NEWS.md +98 -8
  9. data/README.md +110 -12
  10. data/Rakefile +6 -0
  11. data/UPGRADE.md +2 -0
  12. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  13. data/app/controllers/doorkeeper/application_controller.rb +6 -3
  14. data/app/controllers/doorkeeper/application_metal_controller.rb +6 -0
  15. data/app/controllers/doorkeeper/applications_controller.rb +46 -24
  16. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  17. data/app/controllers/doorkeeper/authorized_applications_controller.rb +21 -2
  18. data/app/controllers/doorkeeper/token_info_controller.rb +2 -0
  19. data/app/controllers/doorkeeper/tokens_controller.rb +4 -6
  20. data/app/helpers/doorkeeper/dashboard_helper.rb +9 -7
  21. data/app/validators/redirect_uri_validator.rb +5 -2
  22. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  23. data/app/views/doorkeeper/applications/_form.html.erb +25 -24
  24. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  25. data/app/views/doorkeeper/applications/index.html.erb +17 -7
  26. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  27. data/app/views/doorkeeper/applications/show.html.erb +6 -6
  28. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  29. data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
  30. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  31. data/config/locales/en.yml +10 -1
  32. data/doorkeeper.gemspec +25 -26
  33. data/gemfiles/rails_5_2.gemfile +1 -1
  34. data/gemfiles/rails_master.gemfile +4 -1
  35. data/lib/doorkeeper/config.rb +81 -40
  36. data/lib/doorkeeper/engine.rb +6 -0
  37. data/lib/doorkeeper/errors.rb +17 -3
  38. data/lib/doorkeeper/grape/authorization_decorator.rb +2 -0
  39. data/lib/doorkeeper/grape/helpers.rb +3 -1
  40. data/lib/doorkeeper/helpers/controller.rb +9 -2
  41. data/lib/doorkeeper/models/access_grant_mixin.rb +73 -0
  42. data/lib/doorkeeper/models/access_token_mixin.rb +44 -25
  43. data/lib/doorkeeper/models/application_mixin.rb +2 -0
  44. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  45. data/lib/doorkeeper/models/concerns/expirable.rb +2 -0
  46. data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
  47. data/lib/doorkeeper/models/concerns/ownership.rb +2 -0
  48. data/lib/doorkeeper/models/concerns/revocable.rb +2 -0
  49. data/lib/doorkeeper/models/concerns/scopes.rb +3 -1
  50. data/lib/doorkeeper/oauth/authorization/code.rb +33 -8
  51. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  52. data/lib/doorkeeper/oauth/authorization/token.rb +38 -14
  53. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
  54. data/lib/doorkeeper/oauth/authorization_code_request.rb +29 -2
  55. data/lib/doorkeeper/oauth/base_request.rb +22 -9
  56. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  57. data/lib/doorkeeper/oauth/client/credentials.rb +3 -1
  58. data/lib/doorkeeper/oauth/client.rb +1 -1
  59. data/lib/doorkeeper/oauth/client_credentials/creator.rb +4 -1
  60. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -2
  61. data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -5
  62. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -3
  63. data/lib/doorkeeper/oauth/code_request.rb +2 -0
  64. data/lib/doorkeeper/oauth/code_response.rb +2 -0
  65. data/lib/doorkeeper/oauth/error.rb +2 -0
  66. data/lib/doorkeeper/oauth/error_response.rb +21 -3
  67. data/lib/doorkeeper/oauth/forbidden_token_response.rb +9 -2
  68. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
  69. data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -0
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +5 -2
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +18 -0
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +43 -11
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +16 -3
  75. data/lib/doorkeeper/oauth/scopes.rb +3 -1
  76. data/lib/doorkeeper/oauth/token.rb +7 -2
  77. data/lib/doorkeeper/oauth/token_introspection.rb +4 -2
  78. data/lib/doorkeeper/oauth/token_request.rb +2 -0
  79. data/lib/doorkeeper/oauth/token_response.rb +6 -2
  80. data/lib/doorkeeper/oauth.rb +13 -0
  81. data/lib/doorkeeper/orm/active_record/application.rb +75 -12
  82. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  83. data/lib/doorkeeper/orm/active_record.rb +4 -0
  84. data/lib/doorkeeper/rails/helpers.rb +6 -4
  85. data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
  86. data/lib/doorkeeper/rails/routes/mapping.rb +2 -0
  87. data/lib/doorkeeper/rails/routes.rb +23 -8
  88. data/lib/doorkeeper/rake/db.rake +40 -0
  89. data/lib/doorkeeper/rake/setup.rake +6 -0
  90. data/lib/doorkeeper/rake.rb +14 -0
  91. data/lib/doorkeeper/request/authorization_code.rb +1 -1
  92. data/lib/doorkeeper/request/client_credentials.rb +1 -1
  93. data/lib/doorkeeper/request/code.rb +1 -1
  94. data/lib/doorkeeper/request/password.rb +1 -1
  95. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  96. data/lib/doorkeeper/request/strategy.rb +2 -0
  97. data/lib/doorkeeper/request/token.rb +1 -1
  98. data/lib/doorkeeper/request.rb +29 -34
  99. data/lib/doorkeeper/server.rb +2 -0
  100. data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
  101. data/lib/doorkeeper/validations.rb +2 -0
  102. data/lib/doorkeeper/version.rb +6 -24
  103. data/lib/doorkeeper.rb +20 -17
  104. data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
  105. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  106. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  107. data/lib/generators/doorkeeper/migration_generator.rb +23 -18
  108. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  109. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
  110. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  111. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  112. data/lib/generators/doorkeeper/templates/initializer.rb +96 -13
  113. data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -3
  114. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  115. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  116. data/spec/controllers/applications_controller_spec.rb +123 -14
  117. data/spec/controllers/authorizations_controller_spec.rb +334 -51
  118. data/spec/controllers/protected_resources_controller_spec.rb +60 -18
  119. data/spec/controllers/token_info_controller_spec.rb +4 -12
  120. data/spec/controllers/tokens_controller_spec.rb +17 -20
  121. data/spec/dummy/Rakefile +1 -1
  122. data/spec/dummy/app/assets/config/manifest.js +2 -0
  123. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +1 -1
  124. data/spec/dummy/app/controllers/home_controller.rb +1 -2
  125. data/spec/dummy/config/application.rb +1 -1
  126. data/spec/dummy/config/boot.rb +2 -4
  127. data/spec/dummy/config/environment.rb +1 -1
  128. data/spec/dummy/config/environments/test.rb +5 -6
  129. data/spec/dummy/config/initializers/doorkeeper.rb +12 -6
  130. data/spec/dummy/config/initializers/new_framework_defaults.rb +2 -0
  131. data/spec/dummy/config/initializers/secret_token.rb +1 -1
  132. data/spec/dummy/config/routes.rb +3 -42
  133. data/spec/dummy/config.ru +1 -1
  134. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +4 -4
  135. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
  136. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  137. data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
  138. data/spec/dummy/db/schema.rb +36 -36
  139. data/spec/dummy/script/rails +4 -3
  140. data/spec/factories.rb +6 -6
  141. data/spec/generators/application_owner_generator_spec.rb +1 -1
  142. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  143. data/spec/generators/install_generator_spec.rb +5 -2
  144. data/spec/generators/migration_generator_spec.rb +1 -1
  145. data/spec/generators/pkce_generator_spec.rb +43 -0
  146. data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
  147. data/spec/generators/templates/routes.rb +0 -1
  148. data/spec/generators/views_generator_spec.rb +2 -2
  149. data/spec/grape/grape_integration_spec.rb +2 -2
  150. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  151. data/spec/lib/config_spec.rb +105 -39
  152. data/spec/lib/doorkeeper_spec.rb +6 -131
  153. data/spec/lib/models/expirable_spec.rb +0 -3
  154. data/spec/lib/models/revocable_spec.rb +0 -2
  155. data/spec/lib/models/scopes_spec.rb +0 -4
  156. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  157. data/spec/lib/oauth/authorization_code_request_spec.rb +17 -7
  158. data/spec/lib/oauth/base_request_spec.rb +49 -11
  159. data/spec/lib/oauth/base_response_spec.rb +1 -1
  160. data/spec/lib/oauth/client/credentials_spec.rb +2 -4
  161. data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
  162. data/spec/lib/oauth/client_credentials/issuer_spec.rb +24 -7
  163. data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
  164. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  165. data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
  166. data/spec/lib/oauth/client_spec.rb +0 -3
  167. data/spec/lib/oauth/code_request_spec.rb +5 -3
  168. data/spec/lib/oauth/code_response_spec.rb +1 -1
  169. data/spec/lib/oauth/error_response_spec.rb +0 -3
  170. data/spec/lib/oauth/error_spec.rb +0 -2
  171. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  172. data/spec/lib/oauth/helpers/scope_checker_spec.rb +8 -11
  173. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  174. data/spec/lib/oauth/helpers/uri_checker_spec.rb +22 -13
  175. data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
  176. data/spec/lib/oauth/password_access_token_request_spec.rb +53 -6
  177. data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
  178. data/spec/lib/oauth/refresh_token_request_spec.rb +22 -14
  179. data/spec/lib/oauth/scopes_spec.rb +0 -3
  180. data/spec/lib/oauth/token_request_spec.rb +8 -9
  181. data/spec/lib/oauth/token_response_spec.rb +0 -1
  182. data/spec/lib/oauth/token_spec.rb +40 -14
  183. data/spec/lib/request/strategy_spec.rb +0 -1
  184. data/spec/lib/server_spec.rb +7 -7
  185. data/spec/lib/stale_records_cleaner_spec.rb +89 -0
  186. data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
  187. data/spec/models/doorkeeper/access_token_spec.rb +80 -32
  188. data/spec/models/doorkeeper/application_spec.rb +293 -221
  189. data/spec/requests/applications/applications_request_spec.rb +134 -1
  190. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  191. data/spec/requests/endpoints/authorization_spec.rb +3 -3
  192. data/spec/requests/endpoints/token_spec.rb +7 -5
  193. data/spec/requests/flows/authorization_code_errors_spec.rb +2 -2
  194. data/spec/requests/flows/authorization_code_spec.rb +258 -2
  195. data/spec/requests/flows/client_credentials_spec.rb +46 -6
  196. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  197. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  198. data/spec/requests/flows/password_spec.rb +61 -3
  199. data/spec/requests/flows/refresh_token_spec.rb +59 -2
  200. data/spec/requests/flows/revoke_token_spec.rb +20 -20
  201. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  202. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  203. data/spec/requests/protected_resources/private_api_spec.rb +3 -3
  204. data/spec/routing/custom_controller_routes_spec.rb +59 -7
  205. data/spec/routing/default_routes_spec.rb +2 -2
  206. data/spec/routing/scoped_routes_spec.rb +16 -2
  207. data/spec/spec_helper.rb +54 -3
  208. data/spec/spec_helper_integration.rb +2 -74
  209. data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
  210. data/spec/support/doorkeeper_rspec.rb +20 -0
  211. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  212. data/spec/support/helpers/model_helper.rb +8 -4
  213. data/spec/support/helpers/request_spec_helper.rb +10 -2
  214. data/spec/support/helpers/url_helper.rb +18 -14
  215. data/spec/support/http_method_shim.rb +12 -16
  216. data/spec/support/shared/controllers_shared_context.rb +56 -0
  217. data/spec/validators/redirect_uri_validator_spec.rb +9 -3
  218. data/spec/version/version_spec.rb +3 -3
  219. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  220. metadata +54 -35
  221. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
  222. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
  223. data/spec/controllers/application_metal_controller.rb +0 -10
@@ -1,24 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  class ApplicationsController < Doorkeeper::ApplicationController
3
- layout 'doorkeeper/admin'
5
+ layout 'doorkeeper/admin' unless Doorkeeper.configuration.api_only
4
6
 
5
7
  before_action :authenticate_admin!
6
- before_action :set_application, only: [:show, :edit, :update, :destroy]
8
+ before_action :set_application, only: %i[show edit update destroy]
7
9
 
8
10
  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
11
+ @applications = Application.ordered_by(:created_at)
12
+
13
+ respond_to do |format|
14
+ format.html
15
+ format.json { head :no_content }
16
+ end
19
17
  end
20
18
 
21
- def show; end
19
+ def show
20
+ respond_to do |format|
21
+ format.html
22
+ format.json { render json: @application, as_owner: true }
23
+ end
24
+ end
22
25
 
23
26
  def new
24
27
  @application = Application.new
@@ -26,28 +29,47 @@ module Doorkeeper
26
29
 
27
30
  def create
28
31
  @application = Application.new(application_params)
32
+
29
33
  if @application.save
30
- flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :create])
31
- redirect_to oauth_application_url(@application)
34
+ flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications create])
35
+
36
+ respond_to do |format|
37
+ format.html { redirect_to oauth_application_url(@application) }
38
+ format.json { render json: @application, as_owner: true }
39
+ end
32
40
  else
33
- render :new
41
+ respond_to do |format|
42
+ format.html { render :new }
43
+ format.json { render json: { errors: @application.errors.full_messages }, status: :unprocessable_entity }
44
+ end
34
45
  end
35
46
  end
36
47
 
37
48
  def edit; end
38
49
 
39
50
  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)
51
+ if @application.update(application_params)
52
+ flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications update])
53
+
54
+ respond_to do |format|
55
+ format.html { redirect_to oauth_application_url(@application) }
56
+ format.json { render json: @application, as_owner: true }
57
+ end
43
58
  else
44
- render :edit
59
+ respond_to do |format|
60
+ format.html { render :edit }
61
+ format.json { render json: { errors: @application.errors.full_messages }, status: :unprocessable_entity }
62
+ end
45
63
  end
46
64
  end
47
65
 
48
66
  def destroy
49
- flash[:notice] = I18n.t(:notice, scope: [:doorkeeper, :flash, :applications, :destroy]) if @application.destroy
50
- redirect_to oauth_applications_url
67
+ flash[:notice] = I18n.t(:notice, scope: %i[doorkeeper flash applications destroy]) if @application.destroy
68
+
69
+ respond_to do |format|
70
+ format.html { redirect_to oauth_applications_url }
71
+ format.json { head :no_content }
72
+ end
51
73
  end
52
74
 
53
75
  private
@@ -57,8 +79,8 @@ module Doorkeeper
57
79
  end
58
80
 
59
81
  def application_params
60
- params.require(:doorkeeper_application).
61
- permit(:name, :redirect_uri, :scopes, :confidential)
82
+ params.require(:doorkeeper_application)
83
+ .permit(:name, :redirect_uri, :scopes, :confidential)
62
84
  end
63
85
  end
64
86
  end
@@ -1,23 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  class AuthorizationsController < Doorkeeper::ApplicationController
3
5
  before_action :authenticate_resource_owner!
4
6
 
5
7
  def new
6
8
  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
9
+ render_success
13
10
  else
14
- render :error
11
+ render_error
15
12
  end
16
13
  end
17
14
 
18
15
  # TODO: Handle raise invalid authorization
19
16
  def create
20
- redirect_or_render authorization.authorize
17
+ redirect_or_render authorize_response
21
18
  end
22
19
 
23
20
  def destroy
@@ -26,15 +23,43 @@ module Doorkeeper
26
23
 
27
24
  private
28
25
 
26
+ def render_success
27
+ if skip_authorization? || matching_token?
28
+ redirect_or_render authorize_response
29
+ elsif Doorkeeper.configuration.api_only
30
+ render json: pre_auth
31
+ else
32
+ render :new
33
+ end
34
+ end
35
+
36
+ def render_error
37
+ if Doorkeeper.configuration.api_only
38
+ render json: pre_auth.error_response.body,
39
+ status: :bad_request
40
+ else
41
+ render :error
42
+ end
43
+ end
44
+
29
45
  def matching_token?
30
- AccessToken.matching_token_for pre_auth.client,
31
- current_resource_owner.id,
32
- pre_auth.scopes
46
+ AccessToken.matching_token_for(
47
+ pre_auth.client,
48
+ current_resource_owner.id,
49
+ pre_auth.scopes
50
+ )
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
@@ -1,14 +1,33 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  class AuthorizedApplicationsController < Doorkeeper::ApplicationController
3
5
  before_action :authenticate_resource_owner!
4
6
 
5
7
  def index
6
8
  @applications = Application.authorized_for(current_resource_owner)
9
+
10
+ respond_to do |format|
11
+ format.html
12
+ format.json { render json: @applications, current_resource_owner: current_resource_owner }
13
+ end
7
14
  end
8
15
 
9
16
  def destroy
10
- 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])
17
+ Application.revoke_tokens_and_grants_for(
18
+ params[:id],
19
+ current_resource_owner
20
+ )
21
+
22
+ respond_to do |format|
23
+ format.html do
24
+ redirect_to oauth_authorized_applications_url, notice: I18n.t(
25
+ :notice, scope: %i[doorkeeper flash authorized_applications destroy]
26
+ )
27
+ end
28
+
29
+ format.json { render :no_content }
30
+ end
12
31
  end
13
32
  end
14
33
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  class TokenInfoController < Doorkeeper::ApplicationMetalController
3
5
  def show
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  class TokensController < Doorkeeper::ApplicationMetalController
3
5
  def create
@@ -17,9 +19,7 @@ module Doorkeeper
17
19
  # Doorkeeper does not use the token_type_hint logic described in the
18
20
  # RFC 7009 due to the refresh token implementation that is a field in
19
21
  # the access token model.
20
- if authorized?
21
- revoke_token
22
- end
22
+ revoke_token if authorized?
23
23
 
24
24
  # The authorization server responds with HTTP status code 200 if the token
25
25
  # has been revoked successfully or if the client submitted an invalid
@@ -71,9 +71,7 @@ module Doorkeeper
71
71
  end
72
72
 
73
73
  def revoke_token
74
- if token.accessible?
75
- token.revoke
76
- end
74
+ token.revoke if token.accessible?
77
75
  end
78
76
 
79
77
  def token
@@ -1,15 +1,17 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module DashboardHelper
3
5
  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
6
+ return if object.errors[method].blank?
10
7
 
11
- safe_join(output)
8
+ output = object.errors[method].map do |msg|
9
+ content_tag(:span, class: 'form-text') do
10
+ msg.capitalize
11
+ end
12
12
  end
13
+
14
+ safe_join(output)
13
15
  end
14
16
 
15
17
  def doorkeeper_submit_path(application)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'uri'
2
4
 
3
5
  class RedirectUriValidator < ActiveModel::EachValidator
@@ -34,11 +36,12 @@ class RedirectUriValidator < ActiveModel::EachValidator
34
36
 
35
37
  def invalid_ssl_uri?(uri)
36
38
  forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
39
+ non_https = uri.try(:scheme) == 'http'
37
40
 
38
41
  if forces_ssl.respond_to?(:call)
39
- forces_ssl.call(uri)
42
+ forces_ssl.call(uri) && non_https
40
43
  else
41
- forces_ssl && uri.try(:scheme) == 'http'
44
+ forces_ssl && non_https
42
45
  end
43
46
  end
44
47
  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'