doorkeeper 5.1.2 → 5.2.6

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 (106) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +1 -1
  3. data/CHANGELOG.md +880 -0
  4. data/CONTRIBUTING.md +11 -9
  5. data/Dangerfile +2 -2
  6. data/Dockerfile +29 -0
  7. data/Gemfile +3 -2
  8. data/NEWS.md +1 -819
  9. data/README.md +11 -3
  10. data/RELEASING.md +6 -5
  11. data/app/controllers/doorkeeper/application_controller.rb +1 -1
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -1
  13. data/app/controllers/doorkeeper/applications_controller.rb +1 -0
  14. data/app/controllers/doorkeeper/authorizations_controller.rb +14 -7
  15. data/app/controllers/doorkeeper/tokens_controller.rb +32 -9
  16. data/app/views/doorkeeper/applications/_form.html.erb +0 -6
  17. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  18. data/config/locales/en.yml +8 -2
  19. data/doorkeeper.gemspec +9 -1
  20. data/gemfiles/rails_5_0.gemfile +1 -0
  21. data/gemfiles/rails_5_1.gemfile +1 -0
  22. data/gemfiles/rails_5_2.gemfile +1 -0
  23. data/gemfiles/rails_6_0.gemfile +2 -1
  24. data/gemfiles/rails_master.gemfile +1 -0
  25. data/lib/doorkeeper/config/option.rb +13 -7
  26. data/lib/doorkeeper/config.rb +89 -6
  27. data/lib/doorkeeper/errors.rb +13 -18
  28. data/lib/doorkeeper/grape/helpers.rb +5 -1
  29. data/lib/doorkeeper/helpers/controller.rb +23 -4
  30. data/lib/doorkeeper/models/access_token_mixin.rb +49 -7
  31. data/lib/doorkeeper/oauth/authorization/code.rb +11 -13
  32. data/lib/doorkeeper/oauth/authorization/token.rb +1 -1
  33. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -9
  34. data/lib/doorkeeper/oauth/base_request.rb +2 -0
  35. data/lib/doorkeeper/oauth/client_credentials/creator.rb +14 -0
  36. data/lib/doorkeeper/oauth/client_credentials/validation.rb +8 -0
  37. data/lib/doorkeeper/oauth/code_request.rb +5 -11
  38. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  39. data/lib/doorkeeper/oauth/error_response.rb +1 -1
  40. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +18 -4
  41. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  42. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  43. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  44. data/lib/doorkeeper/oauth/pre_authorization.rb +73 -37
  45. data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -10
  46. data/lib/doorkeeper/oauth/token_introspection.rb +23 -13
  47. data/lib/doorkeeper/oauth/token_request.rb +4 -18
  48. data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
  49. data/lib/doorkeeper/orm/active_record/access_token.rb +2 -2
  50. data/lib/doorkeeper/orm/active_record/application.rb +13 -5
  51. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
  52. data/lib/doorkeeper/orm/active_record.rb +18 -3
  53. data/lib/doorkeeper/request/authorization_code.rb +2 -0
  54. data/lib/doorkeeper/request.rb +6 -11
  55. data/lib/doorkeeper/server.rb +2 -6
  56. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  57. data/lib/doorkeeper/version.rb +2 -2
  58. data/lib/doorkeeper.rb +4 -0
  59. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +6 -6
  60. data/lib/generators/doorkeeper/templates/initializer.rb +118 -33
  61. data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
  62. data/spec/controllers/applications_controller_spec.rb +93 -0
  63. data/spec/controllers/authorizations_controller_spec.rb +143 -62
  64. data/spec/controllers/protected_resources_controller_spec.rb +3 -3
  65. data/spec/controllers/tokens_controller_spec.rb +205 -37
  66. data/spec/dummy/config/application.rb +3 -1
  67. data/spec/dummy/config/initializers/doorkeeper.rb +54 -9
  68. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +1 -1
  69. data/spec/lib/config_spec.rb +58 -1
  70. data/spec/lib/oauth/authorization_code_request_spec.rb +13 -1
  71. data/spec/lib/oauth/base_request_spec.rb +33 -16
  72. data/spec/lib/oauth/client_credentials/creator_spec.rb +3 -0
  73. data/spec/lib/oauth/code_request_spec.rb +27 -28
  74. data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -2
  75. data/spec/lib/oauth/invalid_request_response_spec.rb +75 -0
  76. data/spec/lib/oauth/pre_authorization_spec.rb +76 -66
  77. data/spec/lib/oauth/refresh_token_request_spec.rb +1 -0
  78. data/spec/lib/oauth/token_request_spec.rb +20 -17
  79. data/spec/lib/server_spec.rb +0 -12
  80. data/spec/models/doorkeeper/access_grant_spec.rb +21 -2
  81. data/spec/models/doorkeeper/access_token_spec.rb +35 -4
  82. data/spec/models/doorkeeper/application_spec.rb +10 -0
  83. data/spec/requests/endpoints/authorization_spec.rb +21 -5
  84. data/spec/requests/endpoints/token_spec.rb +1 -1
  85. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
  86. data/spec/requests/flows/authorization_code_spec.rb +93 -27
  87. data/spec/requests/flows/client_credentials_spec.rb +38 -0
  88. data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
  89. data/spec/requests/flows/implicit_grant_spec.rb +9 -8
  90. data/spec/requests/flows/password_spec.rb +37 -0
  91. data/spec/requests/flows/refresh_token_spec.rb +1 -1
  92. data/spec/requests/flows/revoke_token_spec.rb +19 -11
  93. data/spec/support/doorkeeper_rspec.rb +1 -1
  94. data/spec/support/helpers/request_spec_helper.rb +14 -2
  95. data/spec/validators/redirect_uri_validator_spec.rb +40 -15
  96. metadata +16 -15
  97. data/.coveralls.yml +0 -1
  98. data/.github/ISSUE_TEMPLATE.md +0 -25
  99. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  100. data/.gitignore +0 -20
  101. data/.gitlab-ci.yml +0 -16
  102. data/.hound.yml +0 -3
  103. data/.rspec +0 -1
  104. data/.rubocop.yml +0 -50
  105. data/.travis.yml +0 -35
  106. data/app/validators/redirect_uri_validator.rb +0 -50
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Doorkeeper.configure do
4
- # Change the ORM that doorkeeper will use (needs plugins)
4
+ # Change the ORM that doorkeeper will use (requires ORM extensions installed).
5
+ # Check the list of supported ORMs here: https://github.com/doorkeeper-gem/doorkeeper#orms
5
6
  orm :active_record
6
7
 
7
8
  # This block will be called to check whether the resource owner is authenticated or not.
@@ -9,7 +10,7 @@ Doorkeeper.configure do
9
10
  raise "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
10
11
  # Put your resource owner authentication logic here.
11
12
  # Example implementation:
12
- # User.find_by_id(session[:user_id]) || redirect_to(new_user_session_url)
13
+ # User.find_by(id: session[:user_id]) || redirect_to(new_user_session_url)
13
14
  end
14
15
 
15
16
  # If you didn't skip applications controller from Doorkeeper routes in your application routes.rb
@@ -39,18 +40,18 @@ Doorkeeper.configure do
39
40
  #
40
41
  # enforce_content_type
41
42
 
42
- # Authorization Code expiration time (default 10 minutes).
43
+ # Authorization Code expiration time (default: 10 minutes).
43
44
  #
44
45
  # authorization_code_expires_in 10.minutes
45
46
 
46
- # Access token expiration time (default 2 hours).
47
- # If you want to disable expiration, set this to nil.
47
+ # Access token expiration time (default: 2 hours).
48
+ # If you want to disable expiration, set this to `nil`.
48
49
  #
49
50
  # access_token_expires_in 2.hours
50
51
 
51
52
  # Assign custom TTL for access tokens. Will be used instead of access_token_expires_in
52
53
  # option if defined. In case the block returns `nil` value Doorkeeper fallbacks to
53
- # `access_token_expires_in` configuration option value. If you really need to issue a
54
+ # +access_token_expires_in+ configuration option value. If you really need to issue a
54
55
  # non-expiring access token (which is not recommended) then you need to return
55
56
  # Float::INFINITY from this block.
56
57
  #
@@ -65,12 +66,13 @@ Doorkeeper.configure do
65
66
  # end
66
67
 
67
68
  # Use a custom class for generating the access token.
68
- # See https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
69
+ # See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-access-token-generator
69
70
  #
70
71
  # access_token_generator '::Doorkeeper::JWT'
71
72
 
72
- # The controller Doorkeeper::ApplicationController inherits from.
73
- # Defaults to ActionController::Base.
73
+ # The controller +Doorkeeper::ApplicationController+ inherits from.
74
+ # Defaults to +ActionController::Base+ unless +api_only+ is set, which changes the default to
75
+ # +ActionController::API+. The return value of this option must be a stringified class name.
74
76
  # See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
75
77
  #
76
78
  # base_controller 'ApplicationController'
@@ -86,6 +88,14 @@ Doorkeeper.configure do
86
88
  #
87
89
  # reuse_access_token
88
90
 
91
+ # In case you enabled `reuse_access_token` option Doorkeeper will try to find matching
92
+ # token using `matching_token_for` Access Token API that searches for valid records
93
+ # in batches in order not to pollute the memory with all the database records. By default
94
+ # Doorkeeper uses batch size of 10 000 records. You can increase or decrease this value
95
+ # depending on your needs and server capabilities.
96
+ #
97
+ # token_lookup_batch_size 10_000
98
+
89
99
  # Set a limit for token_reuse if using reuse_access_token option
90
100
  #
91
101
  # This option limits token_reusability to some extent.
@@ -128,11 +138,10 @@ Doorkeeper.configure do
128
138
  #
129
139
  # hash_application_secrets using: '::Doorkeeper::SecretStoring::BCrypt'
130
140
 
131
- # When the above option is enabled,
132
- # and a hashed token or secret is not found,
133
- # you can allow to fall back to another strategy.
134
- # For users upgrading doorkeeper and wishing to enable hashing,
135
- # you will probably want to enable the fallback to plain tokens.
141
+ # When the above option is enabled, and a hashed token or secret is not found,
142
+ # you can allow to fall back to another strategy. For users upgrading
143
+ # doorkeeper and wishing to enable hashing, you will probably want to enable
144
+ # the fallback to plain tokens.
136
145
  #
137
146
  # This will ensure that old access tokens and secrets
138
147
  # will remain valid even if the hashing above is enabled.
@@ -141,8 +150,8 @@ Doorkeeper.configure do
141
150
 
142
151
  # Issue access tokens with refresh token (disabled by default), you may also
143
152
  # pass a block which accepts `context` to customize when to give a refresh
144
- # token or not. Similar to `custom_access_token_expires_in`, `context` has
145
- # the properties:
153
+ # token or not. Similar to +custom_access_token_expires_in+, `context` has
154
+ # the following properties:
146
155
  #
147
156
  # `client` - the OAuth client application (see Doorkeeper::OAuth::Client)
148
157
  # `grant_type` - the grant type of the request (see Doorkeeper::OAuth)
@@ -151,7 +160,7 @@ Doorkeeper.configure do
151
160
  # use_refresh_token
152
161
 
153
162
  # Provide support for an owner to be assigned to each registered application (disabled by default)
154
- # Optional parameter confirmation: true (default false) if you want to enforce ownership of
163
+ # Optional parameter confirmation: true (default: false) if you want to enforce ownership of
155
164
  # a registered application
156
165
  # NOTE: you must also run the rails g doorkeeper:application_owner generator
157
166
  # to provide the necessary support
@@ -160,22 +169,22 @@ Doorkeeper.configure do
160
169
 
161
170
  # Define access token scopes for your provider
162
171
  # For more information go to
163
- # https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
172
+ # https://doorkeeper.gitbook.io/guides/ruby-on-rails/scopes
164
173
  #
165
174
  # default_scopes :public
166
175
  # optional_scopes :write, :update
167
176
 
168
- # Define scopes_by_grant_type to restrict only certain scopes for grant_type
177
+ # Allows to restrict only certain scopes for grant_type.
169
178
  # By default, all the scopes will be available for all the grant types.
170
179
  #
171
180
  # Keys to this hash should be the name of grant_type and
172
181
  # values should be the array of scopes for that grant type.
173
- # Note: scopes should be from configured_scopes(i.e. deafult or optional)
182
+ # Note: scopes should be from configured_scopes (i.e. default or optional)
174
183
  #
175
184
  # scopes_by_grant_type password: [:write], client_credentials: [:update]
176
185
 
177
186
  # Forbids creating/updating applications with arbitrary scopes that are
178
- # not in configuration, i.e. `default_scopes` or `optional_scopes`.
187
+ # not in configuration, i.e. +default_scopes+ or +optional_scopes+.
179
188
  # (disabled by default)
180
189
  #
181
190
  # enforce_configured_scopes
@@ -196,15 +205,6 @@ Doorkeeper.configure do
196
205
  #
197
206
  # access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
198
207
 
199
- # Change the native redirect uri for client apps
200
- # When clients register with the following redirect uri, they won't be redirected to
201
- # any server and the authorizationcode will be displayed within the provider
202
- # The value can be any string. Use nil to disable this feature. When disabled, clients
203
- # must providea valid URL
204
- # (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
205
- #
206
- # native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
207
-
208
208
  # Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
209
209
  # by default in non-development environments). OAuth2 delegates security in
210
210
  # communication to the HTTPS protocol so it is wise to keep this enabled.
@@ -246,7 +246,7 @@ Doorkeeper.configure do
246
246
  # is invalid, expired, revoked or has invalid scopes.
247
247
  #
248
248
  # If you want to render error response yourself (i.e. rescue exceptions),
249
- # set handle_auth_errors to `:raise` and rescue Doorkeeper::Errors::InvalidToken
249
+ # set +handle_auth_errors+ to `:raise` and rescue Doorkeeper::Errors::InvalidToken
250
250
  # or following specific errors:
251
251
  #
252
252
  # Doorkeeper::Errors::TokenForbidden, Doorkeeper::Errors::TokenExpired,
@@ -290,6 +290,37 @@ Doorkeeper.configure do
290
290
  #
291
291
  # grant_flows %w[authorization_code client_credentials]
292
292
 
293
+ # Allows to customize OAuth grant flows that +each+ application support.
294
+ # You can configure a custom block (or use a class respond to `#call`) that must
295
+ # return `true` in case Application instance supports requested OAuth grant flow
296
+ # during the authorization request to the server. This configuration +doesn't+
297
+ # set flows per application, it only allows to check if application supports
298
+ # specific grant flow.
299
+ #
300
+ # For example you can add an additional database column to `oauth_applications` table,
301
+ # say `t.array :grant_flows, default: []`, and store allowed grant flows that can
302
+ # be used with this application there. Then when authorization requested Doorkeeper
303
+ # will call this block to check if specific Application (passed with client_id and/or
304
+ # client_secret) is allowed to perform the request for the specific grant type
305
+ # (authorization, password, client_credentials, etc).
306
+ #
307
+ # Example of the block:
308
+ #
309
+ # ->(flow, client) { client.grant_flows.include?(flow) }
310
+ #
311
+ # In case this option invocation result is `false`, Doorkeeper server returns
312
+ # :unauthorized_client error and stops the request.
313
+ #
314
+ # @param allow_grant_flow_for_client [Proc] Block or any object respond to #call
315
+ # @return [Boolean] `true` if allow or `false` if forbid the request
316
+ #
317
+ # allow_grant_flow_for_client do |grant_flow, client|
318
+ # # `grant_flows` is an Array column with grant
319
+ # # flows that application supports
320
+ #
321
+ # client.grant_flows.include?(grant_flow)
322
+ # end
323
+
293
324
  # Hook into the strategies' request & response life-cycle in case your
294
325
  # application needs advanced customization or logging:
295
326
  #
@@ -305,7 +336,7 @@ Doorkeeper.configure do
305
336
  # or add any other functionality.
306
337
  #
307
338
  # before_successful_authorization do |controller|
308
- # Rails.logger.info(params.inspect)
339
+ # Rails.logger.info(controller.request.params.inspect)
309
340
  # end
310
341
  #
311
342
  # after_successful_authorization do |controller|
@@ -323,7 +354,61 @@ Doorkeeper.configure do
323
354
  # client.superapp? or resource_owner.admin?
324
355
  # end
325
356
 
326
- # WWW-Authenticate Realm (default "Doorkeeper").
357
+ # Configure custom constraints for the Token Introspection request.
358
+ # By default this configuration option allows to introspect a token by another
359
+ # token of the same application, OR to introspect the token that belongs to
360
+ # authorized client (from authenticated client) OR when token doesn't
361
+ # belong to any client (public token). Otherwise requester has no access to the
362
+ # introspection and it will return response as stated in the RFC.
363
+ #
364
+ # Block arguments:
365
+ #
366
+ # @param token [Doorkeeper::AccessToken]
367
+ # token to be introspected
368
+ #
369
+ # @param authorized_client [Doorkeeper::Application]
370
+ # authorized client (if request is authorized using Basic auth with
371
+ # Client Credentials for example)
372
+ #
373
+ # @param authorized_token [Doorkeeper::AccessToken]
374
+ # Bearer token used to authorize the request
375
+ #
376
+ # In case the block returns `nil` or `false` introspection responses with 401 status code
377
+ # when using authorized token to introspect, or you'll get 200 with { "active": false } body
378
+ # when using authorized client to introspect as stated in the
379
+ # RFC 7662 section 2.2. Introspection Response.
380
+ #
381
+ # Using with caution:
382
+ # Keep in mind that these three parameters pass to block can be nil as following case:
383
+ # `authorized_client` is nil if and only if `authorized_token` is present, and vice versa.
384
+ # `token` will be nil if and only if `authorized_token` is present.
385
+ # So remember to use `&` or check if it is present before calling method on
386
+ # them to make sure you doesn't get NoMethodError exception.
387
+ #
388
+ # You can define your custom check:
389
+ #
390
+ # allow_token_introspection do |token, authorized_client, authorized_token|
391
+ # if authorized_token
392
+ # # customize: require `introspection` scope
393
+ # authorized_token.application == token&.application ||
394
+ # authorized_token.scopes.include?("introspection")
395
+ # elsif token.application
396
+ # # `protected_resource` is a new database boolean column, for example
397
+ # authorized_client == token.application || authorized_client.protected_resource?
398
+ # else
399
+ # # public token (when token.application is nil, token doesn't belong to any application)
400
+ # true
401
+ # end
402
+ # end
403
+ #
404
+ # Or you can completely disable any token introspection:
405
+ #
406
+ # allow_token_introspection false
407
+ #
408
+ # If you need to block the request at all, then configure your routes.rb or web-server
409
+ # like nginx to forbid the request.
410
+
411
+ # WWW-Authenticate Realm (default: "Doorkeeper").
327
412
  #
328
413
  # realm "Doorkeeper"
329
414
  end
@@ -24,7 +24,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
24
24
  t.text :redirect_uri, null: false
25
25
  t.datetime :created_at, null: false
26
26
  t.datetime :revoked_at
27
- t.string :scopes
27
+ t.string :scopes, null: false, default: ''
28
28
  end
29
29
 
30
30
  add_index :oauth_access_grants, :token, unique: true
@@ -36,6 +36,9 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
36
36
 
37
37
  create_table :oauth_access_tokens do |t|
38
38
  t.references :resource_owner, index: true
39
+
40
+ # Remove `null: false` if you are planning to use Password
41
+ # Credentials Grant flow that doesn't require an application.
39
42
  t.references :application, null: false
40
43
 
41
44
  # If you use a custom token generator you may need to change this column
@@ -26,6 +26,10 @@ module Doorkeeper
26
26
 
27
27
  expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
28
28
 
29
+ application = Application.last
30
+ secret_from_response = json_response["secret"]
31
+ expect(application.secret_matches?(secret_from_response)).to be_truthy
32
+
29
33
  expect(json_response["name"]).to eq("Example")
30
34
  expect(json_response["redirect_uri"]).to eq("https://example.com")
31
35
  end
@@ -44,6 +48,21 @@ module Doorkeeper
44
48
  expect(json_response).to include("errors")
45
49
  end
46
50
 
51
+ it "returns validations on wrong create params (unspecified scheme)" do
52
+ expect do
53
+ post :create, params: {
54
+ doorkeeper_application: {
55
+ name: "Example",
56
+ redirect_uri: "app.com:80",
57
+ }, format: :json,
58
+ }
59
+ end.not_to(change { Doorkeeper::Application.count })
60
+
61
+ expect(response).to have_http_status(422)
62
+
63
+ expect(json_response).to include("errors")
64
+ end
65
+
47
66
  it "returns application info" do
48
67
  application = FactoryBot.create(:application, name: "Change me")
49
68
 
@@ -121,6 +140,72 @@ module Doorkeeper
121
140
  end
122
141
 
123
142
  context "when admin is authenticated" do
143
+ context "when application secrets are hashed" do
144
+ before do
145
+ allow(Doorkeeper.configuration).to receive(:application_secret_strategy).and_return(Doorkeeper::SecretStoring::Sha256Hash)
146
+ end
147
+
148
+ it "shows the application secret after creating a new application" do
149
+ expect do
150
+ post :create, params: {
151
+ doorkeeper_application: {
152
+ name: "Example",
153
+ redirect_uri: "https://example.com",
154
+ },
155
+ }
156
+ end.to change { Doorkeeper::Application.count }.by(1)
157
+
158
+ application = Application.last
159
+
160
+ secret_from_flash = flash[:application_secret]
161
+ expect(secret_from_flash).not_to be_empty
162
+ expect(application.secret_matches?(secret_from_flash)).to be_truthy
163
+ expect(response).to redirect_to(controller.main_app.oauth_application_url(application.id))
164
+
165
+ get :show, params: { id: application.id, format: :html }
166
+
167
+ # We don't know the application secret here (because its hashed) so we can not assert its text on the page
168
+ # Instead, we read it from the page and then check if it matches the application secret
169
+ code_element = %r{<code.*id="secret".*>(.*)<\/code>}.match(response.body)
170
+ secret_from_page = code_element[1]
171
+
172
+ expect(response.body).to have_selector("code#application_id", text: application.uid)
173
+ expect(response.body).to have_selector("code#secret")
174
+ expect(secret_from_page).not_to be_empty
175
+ expect(application.secret_matches?(secret_from_page)).to be_truthy
176
+ end
177
+
178
+ it "does not show an application secret when application did already exist" do
179
+ application = FactoryBot.create(:application)
180
+ get :show, params: { id: application.id, format: :html }
181
+
182
+ expect(response.body).to have_selector("code#application_id", text: application.uid)
183
+ expect(response.body).to have_selector("code#secret", text: "")
184
+ end
185
+
186
+ it "returns the application details in a json response" do
187
+ expect do
188
+ post :create, params: {
189
+ doorkeeper_application: {
190
+ name: "Example",
191
+ redirect_uri: "https://example.com",
192
+ }, format: :json,
193
+ }
194
+ end.to(change { Doorkeeper::Application.count })
195
+
196
+ expect(response).to be_successful
197
+
198
+ expect(json_response).to include("id", "name", "uid", "secret", "redirect_uri", "scopes")
199
+
200
+ application = Application.last
201
+ secret_from_response = json_response["secret"]
202
+ expect(application.secret_matches?(secret_from_response)).to be_truthy
203
+
204
+ expect(json_response["name"]).to eq("Example")
205
+ expect(json_response["redirect_uri"]).to eq("https://example.com")
206
+ end
207
+ end
208
+
124
209
  render_views
125
210
 
126
211
  before do
@@ -151,6 +236,14 @@ module Doorkeeper
151
236
  expect(response).to be_redirect
152
237
  end
153
238
 
239
+ it "shows application details" do
240
+ application = FactoryBot.create(:application)
241
+ get :show, params: { id: application.id, format: :html }
242
+
243
+ expect(response.body).to have_selector("code#application_id", text: application.uid)
244
+ expect(response.body).to have_selector("code#secret", text: application.plaintext_secret)
245
+ end
246
+
154
247
  it "does not allow mass assignment of uid or secret" do
155
248
  application = FactoryBot.create(:application)
156
249
  put :update, params: {