doorkeeper 4.2.6 → 5.0.0.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (205) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +25 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  4. data/.gitignore +2 -1
  5. data/.hound.yml +2 -13
  6. data/.rubocop.yml +17 -0
  7. data/.travis.yml +19 -5
  8. data/Appraisals +8 -4
  9. data/CODE_OF_CONDUCT.md +46 -0
  10. data/Gemfile +1 -1
  11. data/NEWS.md +77 -0
  12. data/README.md +169 -34
  13. data/Rakefile +6 -0
  14. data/SECURITY.md +15 -0
  15. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  16. data/app/controllers/doorkeeper/application_controller.rb +2 -5
  17. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  18. data/app/controllers/doorkeeper/applications_controller.rb +47 -13
  19. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  20. data/app/controllers/doorkeeper/authorized_applications_controller.rb +15 -1
  21. data/app/controllers/doorkeeper/tokens_controller.rb +15 -7
  22. data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
  23. data/app/validators/redirect_uri_validator.rb +13 -2
  24. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  25. data/app/views/doorkeeper/applications/_form.html.erb +31 -19
  26. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  27. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  28. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  29. data/app/views/doorkeeper/applications/show.html.erb +8 -5
  30. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  31. data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
  32. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  33. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  34. data/config/locales/en.yml +18 -6
  35. data/doorkeeper.gemspec +6 -5
  36. data/gemfiles/rails_4_2.gemfile +6 -4
  37. data/gemfiles/rails_5_0.gemfile +4 -4
  38. data/gemfiles/rails_5_1.gemfile +6 -7
  39. data/gemfiles/rails_5_2.gemfile +12 -0
  40. data/gemfiles/rails_master.gemfile +14 -0
  41. data/lib/doorkeeper/config.rb +107 -68
  42. data/lib/doorkeeper/engine.rb +7 -3
  43. data/lib/doorkeeper/errors.rb +2 -5
  44. data/lib/doorkeeper/grape/helpers.rb +14 -9
  45. data/lib/doorkeeper/helpers/controller.rb +15 -6
  46. data/lib/doorkeeper/models/access_grant_mixin.rb +52 -23
  47. data/lib/doorkeeper/models/access_token_mixin.rb +51 -52
  48. data/lib/doorkeeper/models/application_mixin.rb +16 -30
  49. data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
  50. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  51. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  52. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  53. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  54. data/lib/doorkeeper/oauth/authorization/token.rb +41 -20
  55. data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
  56. data/lib/doorkeeper/oauth/base_request.rb +22 -7
  57. data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
  58. data/lib/doorkeeper/oauth/client.rb +2 -2
  59. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -1
  60. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -2
  61. data/lib/doorkeeper/oauth/error.rb +2 -2
  62. data/lib/doorkeeper/oauth/error_response.rb +11 -4
  63. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  64. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  65. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
  66. data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
  67. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
  68. data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
  69. data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
  70. data/lib/doorkeeper/oauth/scopes.rb +19 -9
  71. data/lib/doorkeeper/oauth/token.rb +6 -3
  72. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  73. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  74. data/lib/doorkeeper/oauth.rb +13 -0
  75. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  76. data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
  77. data/lib/doorkeeper/orm/active_record/application.rb +34 -0
  78. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  79. data/lib/doorkeeper/orm/active_record.rb +21 -8
  80. data/lib/doorkeeper/rails/helpers.rb +7 -10
  81. data/lib/doorkeeper/rails/routes.rb +21 -7
  82. data/lib/doorkeeper/rake/db.rake +40 -0
  83. data/lib/doorkeeper/rake/setup.rake +6 -0
  84. data/lib/doorkeeper/rake.rb +14 -0
  85. data/lib/doorkeeper/request/password.rb +1 -11
  86. data/lib/doorkeeper/request.rb +29 -23
  87. data/lib/doorkeeper/validations.rb +3 -2
  88. data/lib/doorkeeper/version.rb +14 -1
  89. data/lib/doorkeeper.rb +6 -17
  90. data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
  91. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  92. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  93. data/lib/generators/doorkeeper/migration_generator.rb +26 -9
  94. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  95. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
  96. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  97. data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
  98. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
  99. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  100. data/lib/generators/doorkeeper/templates/initializer.rb +88 -10
  101. data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
  102. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  103. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  104. data/spec/controllers/applications_controller_spec.rb +141 -17
  105. data/spec/controllers/authorizations_controller_spec.rb +255 -20
  106. data/spec/controllers/protected_resources_controller_spec.rb +44 -35
  107. data/spec/controllers/token_info_controller_spec.rb +17 -21
  108. data/spec/controllers/tokens_controller_spec.rb +142 -10
  109. data/spec/dummy/app/assets/config/manifest.js +2 -0
  110. data/spec/dummy/config/environments/test.rb +4 -5
  111. data/spec/dummy/config/initializers/doorkeeper.rb +18 -1
  112. data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
  113. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  114. data/spec/dummy/config/routes.rb +3 -42
  115. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  116. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  117. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
  118. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
  119. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
  120. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  121. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
  122. data/spec/dummy/db/schema.rb +38 -37
  123. data/spec/factories.rb +1 -1
  124. data/spec/generators/application_owner_generator_spec.rb +25 -6
  125. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  126. data/spec/generators/install_generator_spec.rb +1 -1
  127. data/spec/generators/migration_generator_spec.rb +25 -4
  128. data/spec/generators/pkce_generator_spec.rb +43 -0
  129. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  130. data/spec/generators/views_generator_spec.rb +1 -1
  131. data/spec/grape/grape_integration_spec.rb +135 -0
  132. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
  133. data/spec/lib/config_spec.rb +170 -22
  134. data/spec/lib/doorkeeper_spec.rb +1 -126
  135. data/spec/lib/models/expirable_spec.rb +0 -3
  136. data/spec/lib/models/revocable_spec.rb +2 -4
  137. data/spec/lib/models/scopes_spec.rb +0 -4
  138. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  139. data/spec/lib/oauth/authorization_code_request_spec.rb +63 -13
  140. data/spec/lib/oauth/base_request_spec.rb +19 -10
  141. data/spec/lib/oauth/base_response_spec.rb +1 -1
  142. data/spec/lib/oauth/client/credentials_spec.rb +5 -5
  143. data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
  144. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  145. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  146. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  147. data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
  148. data/spec/lib/oauth/client_spec.rb +0 -3
  149. data/spec/lib/oauth/code_request_spec.rb +5 -5
  150. data/spec/lib/oauth/error_response_spec.rb +0 -3
  151. data/spec/lib/oauth/error_spec.rb +1 -3
  152. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  153. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  154. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  155. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
  156. data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
  157. data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
  158. data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
  159. data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
  160. data/spec/lib/oauth/scopes_spec.rb +28 -4
  161. data/spec/lib/oauth/token_request_spec.rb +10 -13
  162. data/spec/lib/oauth/token_response_spec.rb +0 -1
  163. data/spec/lib/oauth/token_spec.rb +37 -14
  164. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  165. data/spec/lib/request/strategy_spec.rb +0 -1
  166. data/spec/lib/server_spec.rb +10 -0
  167. data/spec/models/doorkeeper/access_grant_spec.rb +2 -2
  168. data/spec/models/doorkeeper/access_token_spec.rb +118 -60
  169. data/spec/models/doorkeeper/application_spec.rb +101 -23
  170. data/spec/requests/applications/applications_request_spec.rb +94 -6
  171. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  172. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  173. data/spec/requests/endpoints/token_spec.rb +15 -6
  174. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
  175. data/spec/requests/flows/authorization_code_spec.rb +198 -1
  176. data/spec/requests/flows/client_credentials_spec.rb +73 -5
  177. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  178. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  179. data/spec/requests/flows/password_spec.rb +160 -24
  180. data/spec/requests/flows/refresh_token_spec.rb +6 -6
  181. data/spec/requests/flows/revoke_token_spec.rb +26 -26
  182. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  183. data/spec/requests/protected_resources/metal_spec.rb +2 -2
  184. data/spec/requests/protected_resources/private_api_spec.rb +2 -2
  185. data/spec/routing/custom_controller_routes_spec.rb +63 -7
  186. data/spec/routing/default_routes_spec.rb +6 -2
  187. data/spec/routing/scoped_routes_spec.rb +16 -2
  188. data/spec/spec_helper.rb +54 -3
  189. data/spec/spec_helper_integration.rb +2 -63
  190. data/spec/support/dependencies/factory_bot.rb +2 -0
  191. data/spec/support/doorkeeper_rspec.rb +19 -0
  192. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  193. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  194. data/spec/support/helpers/model_helper.rb +9 -4
  195. data/spec/support/helpers/request_spec_helper.rb +10 -6
  196. data/spec/support/helpers/url_helper.rb +15 -10
  197. data/spec/support/http_method_shim.rb +12 -16
  198. data/spec/support/shared/controllers_shared_context.rb +2 -6
  199. data/spec/support/shared/models_shared_examples.rb +4 -4
  200. data/spec/validators/redirect_uri_validator_spec.rb +58 -7
  201. data/spec/version/version_spec.rb +15 -0
  202. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  203. metadata +73 -19
  204. data/spec/controllers/application_metal_controller.rb +0 -10
  205. data/spec/support/dependencies/factory_girl.rb +0 -2
@@ -1,29 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rails/generators'
1
4
  require 'rails/generators/active_record'
2
5
 
3
- class Doorkeeper::PreviousRefreshTokenGenerator < Rails::Generators::Base
4
- include Rails::Generators::Migration
5
- source_root File.expand_path('../templates', __FILE__)
6
- desc 'Support revoke refresh token on access token use'
6
+ module Doorkeeper
7
+ class PreviousRefreshTokenGenerator < ::Rails::Generators::Base
8
+ include ::Rails::Generators::Migration
9
+ source_root File.expand_path('templates', __dir__)
10
+ desc 'Support revoke refresh token on access token use'
7
11
 
8
- def self.next_migration_number(path)
9
- ActiveRecord::Generators::Base.next_migration_number(path)
10
- end
12
+ def self.next_migration_number(path)
13
+ ActiveRecord::Generators::Base.next_migration_number(path)
14
+ end
11
15
 
12
- def previous_refresh_token
13
- if no_previous_refresh_token_column?
14
- migration_template(
15
- 'add_previous_refresh_token_to_access_tokens.rb',
16
- 'db/migrate/add_previous_refresh_token_to_access_tokens.rb'
17
- )
16
+ def previous_refresh_token
17
+ if no_previous_refresh_token_column?
18
+ migration_template(
19
+ 'add_previous_refresh_token_to_access_tokens.rb.erb',
20
+ 'db/migrate/add_previous_refresh_token_to_access_tokens.rb'
21
+ )
22
+ end
18
23
  end
19
- end
20
24
 
21
- private
25
+ private
22
26
 
23
- def no_previous_refresh_token_column?
24
- !ActiveRecord::Base.connection.column_exists?(
25
- :oauth_access_tokens,
26
- :previous_refresh_token
27
- )
27
+ def migration_version
28
+ if ActiveRecord::VERSION::MAJOR >= 5
29
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
30
+ end
31
+ end
32
+
33
+ def no_previous_refresh_token_column?
34
+ !ActiveRecord::Base.connection.column_exists?(
35
+ :oauth_access_tokens,
36
+ :previous_refresh_token
37
+ )
38
+ end
28
39
  end
29
40
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddConfidentialToApplications < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ add_column(
6
+ :oauth_applications,
7
+ :confidential,
8
+ :boolean,
9
+ null: false,
10
+ default: true
11
+ )
12
+ end
13
+ end
@@ -1,4 +1,4 @@
1
- class AddOwnerToApplication < ActiveRecord::Migration
1
+ class AddOwnerToApplication < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  add_column :oauth_applications, :owner_id, :integer, null: true
4
4
  add_column :oauth_applications, :owner_type, :string, null: true
@@ -1,4 +1,4 @@
1
- class AddPreviousRefreshTokenToAccessTokens < ActiveRecord::Migration
1
+ class AddPreviousRefreshTokenToAccessTokens < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  add_column(
4
4
  :oauth_access_tokens,
@@ -0,0 +1,6 @@
1
+ class EnablePkce < ActiveRecord::Migration<%= migration_version %>
2
+ def change
3
+ add_column :oauth_access_grants, :code_challenge, :string, null: true
4
+ add_column :oauth_access_grants, :code_challenge_method, :string, null: true
5
+ end
6
+ end
@@ -4,69 +4,106 @@ Doorkeeper.configure do
4
4
 
5
5
  # This block will be called to check whether the resource owner is authenticated or not.
6
6
  resource_owner_authenticator do
7
- fail "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
7
+ raise "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
8
8
  # Put your resource owner authentication logic here.
9
9
  # Example implementation:
10
10
  # User.find_by_id(session[:user_id]) || redirect_to(new_user_session_url)
11
11
  end
12
12
 
13
- # If you want to restrict access to the web interface for adding oauth authorized applications, you need to declare the block below.
13
+ # If you want to restrict access to the web interface for adding oauth authorized applications,
14
+ # you need to declare the block below.
15
+ #
14
16
  # admin_authenticator do
15
17
  # # Put your admin authentication logic here.
16
18
  # # Example implementation:
17
19
  # Admin.find_by_id(session[:admin_id]) || redirect_to(new_admin_session_url)
18
20
  # end
19
21
 
22
+ # If you are planning to use Doorkeeper in Rails 5 API-only application, then you might
23
+ # want to use API mode that will skip all the views management and change the way how
24
+ # Doorkeeper responds to a requests.
25
+ #
26
+ # api_only
27
+
28
+ # Enforce token request content type to application/x-www-form-urlencoded.
29
+ # It is not enabled by default to not break prior versions of the gem.
30
+ #
31
+ # enforce_content_type
32
+
20
33
  # Authorization Code expiration time (default 10 minutes).
34
+ #
21
35
  # authorization_code_expires_in 10.minutes
22
36
 
23
37
  # Access token expiration time (default 2 hours).
24
38
  # If you want to disable expiration, set this to nil.
39
+ #
25
40
  # access_token_expires_in 2.hours
26
41
 
27
- # Assign a custom TTL for implicit grants.
28
- # custom_access_token_expires_in do |oauth_client|
29
- # oauth_client.application.additional_settings.implicit_oauth_expiration
42
+ # Assign custom TTL for access tokens. Will be used instead of access_token_expires_in
43
+ # option if defined. `context` has the following properties available
44
+ #
45
+ # `client` - the OAuth client application (see Doorkeeper::OAuth::Client)
46
+ # `grant_type` - the grant type of the request (see Doorkeeper::OAuth)
47
+ # `scopes` - the requested scopes (see Doorkeeper::OAuth::Scopes)
48
+ #
49
+ # custom_access_token_expires_in do |context|
50
+ # context.client.application.additional_settings.implicit_oauth_expiration
30
51
  # end
31
52
 
32
53
  # Use a custom class for generating the access token.
33
- # https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
54
+ # See https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
55
+ #
34
56
  # access_token_generator '::Doorkeeper::JWT'
35
57
 
36
58
  # The controller Doorkeeper::ApplicationController inherits from.
37
59
  # Defaults to ActionController::Base.
38
- # https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
60
+ # See https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
61
+ #
39
62
  # base_controller 'ApplicationController'
40
63
 
41
64
  # Reuse access token for the same resource owner within an application (disabled by default)
42
65
  # Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/383
66
+ #
43
67
  # reuse_access_token
44
68
 
45
69
  # Issue access tokens with refresh token (disabled by default)
70
+ #
46
71
  # use_refresh_token
47
72
 
73
+ # Forbids creating/updating applications with arbitrary scopes that are
74
+ # not in configuration, i.e. `default_scopes` or `optional_scopes`.
75
+ # (disabled by default)
76
+ #
77
+ # enforce_configured_scopes
78
+
48
79
  # Provide support for an owner to be assigned to each registered application (disabled by default)
49
80
  # Optional parameter confirmation: true (default false) if you want to enforce ownership of
50
81
  # a registered application
51
82
  # Note: you must also run the rails g doorkeeper:application_owner generator to provide the necessary support
83
+ #
52
84
  # enable_application_owner confirmation: false
53
85
 
54
86
  # Define access token scopes for your provider
55
87
  # For more information go to
56
88
  # https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
89
+ #
57
90
  # default_scopes :public
58
91
  # optional_scopes :write, :update
59
92
 
60
93
  # Change the way client credentials are retrieved from the request object.
61
94
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
62
95
  # falls back to the `:client_id` and `:client_secret` params from the `params` object.
63
- # Check out the wiki for more information on customization
96
+ # Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated
97
+ # for more information on customization
98
+ #
64
99
  # client_credentials :from_basic, :from_params
65
100
 
66
101
  # Change the way access token is authenticated from the request object.
67
102
  # By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
68
103
  # falls back to the `:access_token` or `:bearer_token` params from the `params` object.
69
- # Check out the wiki for more information on customization
104
+ # Check out https://github.com/doorkeeper-gem/doorkeeper/wiki/Changing-how-clients-are-authenticated
105
+ # for more information on customization
106
+ #
70
107
  # access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
71
108
 
72
109
  # Change the native redirect uri for client apps
@@ -80,7 +117,21 @@ Doorkeeper.configure do
80
117
  # by default in non-development environments). OAuth2 delegates security in
81
118
  # communication to the HTTPS protocol so it is wise to keep this enabled.
82
119
  #
120
+ # Callable objects such as proc, lambda, block or any object that responds to
121
+ # #call can be used in order to allow conditional checks (to allow non-SSL
122
+ # redirects to localhost for example).
123
+ #
83
124
  # force_ssl_in_redirect_uri !Rails.env.development?
125
+ #
126
+ # force_ssl_in_redirect_uri { |uri| uri.host != 'localhost' }
127
+
128
+ # Specify what redirect URI's you want to block during Application creation.
129
+ # Any redirect URI is whitelisted by default.
130
+ #
131
+ # You can use this option in order to forbid URI's with 'javascript' scheme
132
+ # for example.
133
+ #
134
+ # forbid_redirect_uri { |uri| uri.scheme.to_s.downcase == 'javascript' }
84
135
 
85
136
  # Specify what grant flows are enabled in array of Strings. The valid
86
137
  # strings and the flows they enable are:
@@ -98,15 +149,42 @@ Doorkeeper.configure do
98
149
  # http://tools.ietf.org/html/rfc6819#section-4.4.2
99
150
  # http://tools.ietf.org/html/rfc6819#section-4.4.3
100
151
  #
101
- # grant_flows %w(authorization_code client_credentials)
152
+ # grant_flows %w[authorization_code client_credentials]
153
+
154
+ # Hook into the strategies' request & response life-cycle in case your
155
+ # application needs advanced customization or logging:
156
+ #
157
+ # before_successful_strategy_response do |request|
158
+ # puts "BEFORE HOOK FIRED! #{request}"
159
+ # end
160
+ #
161
+ # after_successful_strategy_response do |request, response|
162
+ # puts "AFTER HOOK FIRED! #{request}, #{response}"
163
+ # end
164
+
165
+ # Hook into Authorization flow in order to implement Single Sign Out
166
+ # or add ny other functionality.
167
+ #
168
+ # before_successful_authorization do |controller|
169
+ # Rails.logger.info(params.inspect)
170
+ # end
171
+ #
172
+ # after_successful_authorization do |controller|
173
+ # controller.session[:logout_urls] <<
174
+ # Doorkeeper::Application
175
+ # .find_by(controller.request.params.slice(:redirect_uri))
176
+ # .logout_uri
177
+ # end
102
178
 
103
179
  # Under some circumstances you might want to have applications auto-approved,
104
180
  # so that the user skips the authorization step.
105
181
  # For example if dealing with a trusted application.
182
+ #
106
183
  # skip_authorization do |resource_owner, client|
107
184
  # client.superapp? or resource_owner.admin?
108
185
  # end
109
186
 
110
187
  # WWW-Authenticate Realm (default "Doorkeeper").
188
+ #
111
189
  # realm "Doorkeeper"
112
190
  end
@@ -1,4 +1,4 @@
1
- class CreateDoorkeeperTables < ActiveRecord::Migration
1
+ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
2
2
  def change
3
3
  create_table :oauth_applications do |t|
4
4
  t.string :name, null: false
@@ -6,6 +6,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration
6
6
  t.string :secret, null: false
7
7
  t.text :redirect_uri, null: false
8
8
  t.string :scopes, null: false, default: ''
9
+ t.boolean :confidential, null: false, default: true
9
10
  t.timestamps null: false
10
11
  end
11
12
 
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Doorkeeper
2
4
  module Generators
3
5
  class ViewsGenerator < ::Rails::Generators::Base
4
- source_root File.expand_path('../../../../app/views', __FILE__)
6
+ source_root File.expand_path('../../../app/views', __dir__)
5
7
 
6
8
  desc 'Copies default Doorkeeper views and layouts to your application.'
7
9
 
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper_integration'
4
+
5
+ describe Doorkeeper::ApplicationMetalController do
6
+ controller(Doorkeeper::ApplicationMetalController) do
7
+ def index
8
+ render json: {}, status: 200
9
+ end
10
+ end
11
+
12
+ it "lazy run hooks" do
13
+ i = 0
14
+ ActiveSupport.on_load(:doorkeeper_metal_controller) { i += 1 }
15
+
16
+ expect(i).to eq 1
17
+ end
18
+
19
+ describe 'enforce_content_type' do
20
+ before { allow(Doorkeeper.configuration).to receive(:enforce_content_type).and_return(flag) }
21
+
22
+ context 'enabled' do
23
+ let(:flag) { true }
24
+
25
+ it '200 for the correct media type' do
26
+ get :index, params: {}, as: :url_encoded_form
27
+ expect(response).to have_http_status 200
28
+ end
29
+
30
+ it 'returns a 415 for an incorrect media type' do
31
+ get :index, as: :json
32
+ expect(response).to have_http_status 415
33
+ end
34
+ end
35
+
36
+ context 'disabled' do
37
+ let(:flag) { false }
38
+
39
+ it 'returns a 200 for the correct media type' do
40
+ get :index, as: :url_encoded_form
41
+ expect(response).to have_http_status 200
42
+ end
43
+
44
+ it 'returns a 200 for an incorrect media type' do
45
+ get :index, as: :json
46
+ expect(response).to have_http_status 200
47
+ end
48
+ end
49
+ end
50
+ end
@@ -1,7 +1,99 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper
4
4
  describe ApplicationsController do
5
+ context 'JSON API' do
6
+ render_views
7
+
8
+ before do
9
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
10
+ allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
11
+ end
12
+
13
+ it 'creates an application' do
14
+ expect do
15
+ post :create, params: {
16
+ doorkeeper_application: {
17
+ name: 'Example',
18
+ redirect_uri: 'https://example.com'
19
+ }, format: :json
20
+ }
21
+ end.to change { Doorkeeper::Application.count }
22
+
23
+ expect(response).to be_successful
24
+
25
+ expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
26
+
27
+ expect(json_response['name']).to eq('Example')
28
+ expect(json_response['redirect_uri']).to eq('https://example.com')
29
+ end
30
+
31
+ it 'returns validation errors on wrong create params' do
32
+ expect do
33
+ post :create, params: {
34
+ doorkeeper_application: {
35
+ name: 'Example'
36
+ }, format: :json
37
+ }
38
+ end.not_to change { Doorkeeper::Application.count }
39
+
40
+ expect(response).to have_http_status(422)
41
+
42
+ expect(json_response).to include('errors')
43
+ end
44
+
45
+ it 'returns application info' do
46
+ application = FactoryBot.create(:application, name: 'Change me')
47
+
48
+ get :show, params: { id: application.id, format: :json }
49
+
50
+ expect(response).to be_successful
51
+
52
+ expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
53
+ end
54
+
55
+ it 'updates application' do
56
+ application = FactoryBot.create(:application, name: 'Change me')
57
+
58
+ put :update, params: {
59
+ id: application.id,
60
+ doorkeeper_application: {
61
+ name: 'Example App',
62
+ redirect_uri: 'https://example.com'
63
+ }, format: :json
64
+ }
65
+
66
+ expect(application.reload.name).to eq 'Example App'
67
+
68
+ expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
69
+ end
70
+
71
+ it 'returns validation errors on wrong update params' do
72
+ application = FactoryBot.create(:application, name: 'Change me')
73
+
74
+ put :update, params: {
75
+ id: application.id,
76
+ doorkeeper_application: {
77
+ name: 'Example App',
78
+ redirect_uri: 'localhost:3000'
79
+ }, format: :json
80
+ }
81
+
82
+ expect(response).to have_http_status(422)
83
+
84
+ expect(json_response).to include('errors')
85
+ end
86
+
87
+ it 'destroys an application' do
88
+ application = FactoryBot.create(:application)
89
+
90
+ delete :destroy, params: { id: application.id, format: :json }
91
+
92
+ expect(response).to have_http_status(204)
93
+ expect(Application.count).to be_zero
94
+ end
95
+ end
96
+
5
97
  context 'when admin is not authenticated' do
6
98
  before do
7
99
  allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(proc do
@@ -16,41 +108,73 @@ module Doorkeeper
16
108
 
17
109
  it 'does not create application' do
18
110
  expect do
19
- post :create, doorkeeper_application: {
20
- name: 'Example',
21
- redirect_uri: 'https://example.com' }
22
- end.to_not change { Doorkeeper::Application.count }
111
+ post :create,
112
+ params: {
113
+ doorkeeper_application: {
114
+ name: 'Example',
115
+ redirect_uri: 'https://example.com'
116
+ }
117
+ }
118
+ end.not_to change { Doorkeeper::Application.count }
23
119
  end
24
120
  end
25
121
 
26
122
  context 'when admin is authenticated' do
123
+ render_views
124
+
27
125
  before do
28
- allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(arg) { true })
126
+ allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
127
+ end
128
+
129
+ it 'sorts applications by created_at' do
130
+ first_application = FactoryBot.create(:application)
131
+ second_application = FactoryBot.create(:application)
132
+ expect(Doorkeeper::Application).to receive(:ordered_by).and_call_original
133
+
134
+ get :index
135
+
136
+ expect(response.body).to have_selector("tbody tr:first-child#application_#{first_application.id}")
137
+ expect(response.body).to have_selector("tbody tr:last-child#application_#{second_application.id}")
29
138
  end
30
139
 
31
140
  it 'creates application' do
32
141
  expect do
33
- post :create, doorkeeper_application: {
34
- name: 'Example',
35
- redirect_uri: 'https://example.com' }
142
+ post :create,
143
+ params: {
144
+ doorkeeper_application: {
145
+ name: 'Example',
146
+ redirect_uri: 'https://example.com'
147
+ }
148
+ }
36
149
  end.to change { Doorkeeper::Application.count }.by(1)
150
+
37
151
  expect(response).to be_redirect
38
152
  end
39
153
 
40
154
  it 'does not allow mass assignment of uid or secret' do
41
- application = FactoryGirl.create(:application)
42
- put :update, id: application.id, doorkeeper_application: {
43
- uid: '1A2B3C4D',
44
- secret: '1A2B3C4D' }
155
+ application = FactoryBot.create(:application)
156
+ put :update,
157
+ params: {
158
+ id: application.id,
159
+ doorkeeper_application: {
160
+ uid: '1A2B3C4D',
161
+ secret: '1A2B3C4D'
162
+ }
163
+ }
45
164
 
46
165
  expect(application.reload.uid).not_to eq '1A2B3C4D'
47
166
  end
48
167
 
49
168
  it 'updates application' do
50
- application = FactoryGirl.create(:application)
51
- put :update, id: application.id, doorkeeper_application: {
52
- name: 'Example',
53
- redirect_uri: 'https://example.com' }
169
+ application = FactoryBot.create(:application)
170
+ put :update,
171
+ params: {
172
+ id: application.id, doorkeeper_application: {
173
+ name: 'Example',
174
+ redirect_uri: 'https://example.com'
175
+ }
176
+ }
177
+
54
178
  expect(application.reload.name).to eq 'Example'
55
179
  end
56
180
  end