doorkeeper 5.1.0 → 5.3.0

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 (163) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +3 -3
  3. data/CHANGELOG.md +881 -0
  4. data/CONTRIBUTING.md +11 -9
  5. data/Dangerfile +2 -2
  6. data/Dockerfile +29 -0
  7. data/Gemfile +4 -3
  8. data/NEWS.md +1 -814
  9. data/README.md +11 -3
  10. data/RELEASING.md +6 -5
  11. data/app/controllers/doorkeeper/application_controller.rb +2 -2
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  13. data/app/controllers/doorkeeper/applications_controller.rb +1 -0
  14. data/app/controllers/doorkeeper/authorizations_controller.rb +16 -9
  15. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  16. data/app/controllers/doorkeeper/tokens_controller.rb +32 -9
  17. data/app/views/doorkeeper/applications/_form.html.erb +0 -6
  18. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  19. data/config/locales/en.yml +8 -2
  20. data/doorkeeper.gemspec +9 -1
  21. data/gemfiles/rails_5_0.gemfile +3 -2
  22. data/gemfiles/rails_5_1.gemfile +3 -2
  23. data/gemfiles/rails_5_2.gemfile +3 -2
  24. data/gemfiles/rails_6_0.gemfile +4 -3
  25. data/gemfiles/rails_master.gemfile +3 -2
  26. data/lib/doorkeeper/config/option.rb +13 -7
  27. data/lib/doorkeeper/config.rb +157 -42
  28. data/lib/doorkeeper/errors.rb +13 -18
  29. data/lib/doorkeeper/grape/helpers.rb +6 -2
  30. data/lib/doorkeeper/helpers/controller.rb +28 -7
  31. data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
  32. data/lib/doorkeeper/models/access_token_mixin.rb +99 -20
  33. data/lib/doorkeeper/models/application_mixin.rb +3 -3
  34. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  35. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  36. data/lib/doorkeeper/models/concerns/revocable.rb +0 -27
  37. data/lib/doorkeeper/oauth/authorization/code.rb +12 -14
  38. data/lib/doorkeeper/oauth/authorization/token.rb +10 -7
  39. data/lib/doorkeeper/oauth/authorization_code_request.rb +31 -15
  40. data/lib/doorkeeper/oauth/base_request.rb +10 -4
  41. data/lib/doorkeeper/oauth/client.rb +7 -8
  42. data/lib/doorkeeper/oauth/client_credentials/creator.rb +23 -2
  43. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
  44. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +10 -2
  45. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  46. data/lib/doorkeeper/oauth/code_request.rb +5 -11
  47. data/lib/doorkeeper/oauth/code_response.rb +4 -4
  48. data/lib/doorkeeper/oauth/error.rb +1 -1
  49. data/lib/doorkeeper/oauth/error_response.rb +6 -6
  50. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +7 -5
  51. data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
  52. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -5
  53. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  54. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
  55. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  56. data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
  57. data/lib/doorkeeper/oauth/pre_authorization.rb +76 -38
  58. data/lib/doorkeeper/oauth/refresh_token_request.rb +17 -14
  59. data/lib/doorkeeper/oauth/token.rb +2 -2
  60. data/lib/doorkeeper/oauth/token_introspection.rb +26 -16
  61. data/lib/doorkeeper/oauth/token_request.rb +4 -18
  62. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  63. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  64. data/lib/doorkeeper/orm/active_record/application.rb +5 -83
  65. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +53 -0
  66. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +47 -0
  67. data/lib/doorkeeper/orm/active_record/mixins/application.rb +128 -0
  68. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
  69. data/lib/doorkeeper/orm/active_record.rb +21 -6
  70. data/lib/doorkeeper/rails/helpers.rb +4 -4
  71. data/lib/doorkeeper/rails/routes.rb +5 -7
  72. data/lib/doorkeeper/rake/db.rake +3 -3
  73. data/lib/doorkeeper/request/authorization_code.rb +5 -3
  74. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  75. data/lib/doorkeeper/request/password.rb +2 -2
  76. data/lib/doorkeeper/request/refresh_token.rb +3 -3
  77. data/lib/doorkeeper/request.rb +7 -12
  78. data/lib/doorkeeper/server.rb +3 -7
  79. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  80. data/lib/doorkeeper/version.rb +1 -1
  81. data/lib/doorkeeper.rb +6 -3
  82. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  83. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  84. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  85. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  86. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
  87. data/lib/generators/doorkeeper/templates/initializer.rb +149 -33
  88. data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
  89. data/spec/controllers/application_metal_controller_spec.rb +1 -1
  90. data/spec/controllers/applications_controller_spec.rb +95 -1
  91. data/spec/controllers/authorizations_controller_spec.rb +156 -75
  92. data/spec/controllers/protected_resources_controller_spec.rb +28 -20
  93. data/spec/controllers/token_info_controller_spec.rb +1 -1
  94. data/spec/controllers/tokens_controller_spec.rb +206 -38
  95. data/spec/dummy/config/application.rb +3 -1
  96. data/spec/dummy/config/initializers/doorkeeper.rb +54 -9
  97. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -3
  98. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +1 -1
  99. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +1 -1
  100. data/spec/generators/install_generator_spec.rb +1 -1
  101. data/spec/generators/previous_refresh_token_generator_spec.rb +2 -2
  102. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  103. data/spec/lib/config_spec.rb +104 -7
  104. data/spec/lib/doorkeeper_spec.rb +1 -1
  105. data/spec/lib/models/revocable_spec.rb +3 -3
  106. data/spec/lib/oauth/authorization_code_request_spec.rb +129 -115
  107. data/spec/lib/oauth/base_request_spec.rb +154 -135
  108. data/spec/lib/oauth/base_response_spec.rb +27 -29
  109. data/spec/lib/oauth/client/credentials_spec.rb +1 -1
  110. data/spec/lib/oauth/client_credentials/creator_spec.rb +43 -3
  111. data/spec/lib/oauth/client_credentials/issuer_spec.rb +12 -12
  112. data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
  113. data/spec/lib/oauth/client_credentials_integration_spec.rb +16 -18
  114. data/spec/lib/oauth/client_credentials_request_spec.rb +78 -80
  115. data/spec/lib/oauth/client_spec.rb +26 -26
  116. data/spec/lib/oauth/code_request_spec.rb +34 -35
  117. data/spec/lib/oauth/code_response_spec.rb +21 -25
  118. data/spec/lib/oauth/error_response_spec.rb +42 -44
  119. data/spec/lib/oauth/error_spec.rb +12 -14
  120. data/spec/lib/oauth/forbidden_token_response_spec.rb +11 -13
  121. data/spec/lib/oauth/helpers/scope_checker_spec.rb +30 -18
  122. data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -2
  123. data/spec/lib/oauth/invalid_request_response_spec.rb +73 -0
  124. data/spec/lib/oauth/invalid_token_response_spec.rb +32 -34
  125. data/spec/lib/oauth/password_access_token_request_spec.rb +145 -147
  126. data/spec/lib/oauth/pre_authorization_spec.rb +161 -153
  127. data/spec/lib/oauth/refresh_token_request_spec.rb +138 -138
  128. data/spec/lib/oauth/scopes_spec.rb +104 -106
  129. data/spec/lib/oauth/token_request_spec.rb +117 -110
  130. data/spec/lib/oauth/token_response_spec.rb +71 -73
  131. data/spec/lib/oauth/token_spec.rb +121 -123
  132. data/spec/lib/server_spec.rb +0 -12
  133. data/spec/models/doorkeeper/access_grant_spec.rb +21 -4
  134. data/spec/models/doorkeeper/access_token_spec.rb +42 -11
  135. data/spec/models/doorkeeper/application_spec.rb +114 -77
  136. data/spec/requests/applications/applications_request_spec.rb +1 -1
  137. data/spec/requests/endpoints/authorization_spec.rb +26 -8
  138. data/spec/requests/endpoints/token_spec.rb +1 -1
  139. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
  140. data/spec/requests/flows/authorization_code_spec.rb +123 -45
  141. data/spec/requests/flows/client_credentials_spec.rb +38 -0
  142. data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
  143. data/spec/requests/flows/implicit_grant_spec.rb +9 -8
  144. data/spec/requests/flows/password_spec.rb +67 -10
  145. data/spec/requests/flows/refresh_token_spec.rb +20 -20
  146. data/spec/requests/flows/revoke_token_spec.rb +37 -23
  147. data/spec/spec_helper.rb +1 -4
  148. data/spec/support/doorkeeper_rspec.rb +1 -1
  149. data/spec/support/helpers/request_spec_helper.rb +14 -2
  150. data/spec/support/shared/controllers_shared_context.rb +33 -23
  151. data/spec/validators/redirect_uri_validator_spec.rb +41 -16
  152. metadata +19 -16
  153. data/.coveralls.yml +0 -1
  154. data/.github/ISSUE_TEMPLATE.md +0 -25
  155. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  156. data/.gitignore +0 -20
  157. data/.gitlab-ci.yml +0 -16
  158. data/.hound.yml +0 -3
  159. data/.rspec +0 -1
  160. data/.rubocop.yml +0 -50
  161. data/.travis.yml +0 -35
  162. data/app/validators/redirect_uri_validator.rb +0 -50
  163. data/spec/support/http_method_shim.rb +0 -29
@@ -13,6 +13,78 @@ module Doorkeeper
13
13
  let(:uid) { SecureRandom.hex(8) }
14
14
  let(:secret) { SecureRandom.hex(8) }
15
15
 
16
+ it "is invalid without a name" do
17
+ new_application.name = nil
18
+ expect(new_application).not_to be_valid
19
+ end
20
+
21
+ it "is invalid without determining confidentiality" do
22
+ new_application.confidential = nil
23
+ expect(new_application).not_to be_valid
24
+ end
25
+
26
+ it "generates uid on create" do
27
+ expect(new_application.uid).to be_nil
28
+ new_application.save
29
+ expect(new_application.uid).not_to be_nil
30
+ end
31
+
32
+ it "generates uid on create if an empty string" do
33
+ new_application.uid = ""
34
+ new_application.save
35
+ expect(new_application.uid).not_to be_blank
36
+ end
37
+
38
+ it "generates uid on create unless one is set" do
39
+ new_application.uid = uid
40
+ new_application.save
41
+ expect(new_application.uid).to eq(uid)
42
+ end
43
+
44
+ it "is invalid without uid" do
45
+ new_application.save
46
+ new_application.uid = nil
47
+ expect(new_application).not_to be_valid
48
+ end
49
+
50
+ it "checks uniqueness of uid" do
51
+ app1 = FactoryBot.create(:application)
52
+ app2 = FactoryBot.create(:application)
53
+ app2.uid = app1.uid
54
+ expect(app2).not_to be_valid
55
+ end
56
+
57
+ it "expects database to throw an error when uids are the same" do
58
+ app1 = FactoryBot.create(:application)
59
+ app2 = FactoryBot.create(:application)
60
+ app2.uid = app1.uid
61
+ expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
62
+ end
63
+
64
+ it "generate secret on create" do
65
+ expect(new_application.secret).to be_nil
66
+ new_application.save
67
+ expect(new_application.secret).not_to be_nil
68
+ end
69
+
70
+ it "generate secret on create if is blank string" do
71
+ new_application.secret = ""
72
+ new_application.save
73
+ expect(new_application.secret).not_to be_blank
74
+ end
75
+
76
+ it "generate secret on create unless one is set" do
77
+ new_application.secret = secret
78
+ new_application.save
79
+ expect(new_application.secret).to eq(secret)
80
+ end
81
+
82
+ it "is invalid without secret" do
83
+ new_application.save
84
+ new_application.secret = nil
85
+ expect(new_application).not_to be_valid
86
+ end
87
+
16
88
  context "application_owner is enabled" do
17
89
  before do
18
90
  Doorkeeper.configure do
@@ -48,40 +120,6 @@ module Doorkeeper
48
120
  end
49
121
  end
50
122
 
51
- it "is invalid without a name" do
52
- new_application.name = nil
53
- expect(new_application).not_to be_valid
54
- end
55
-
56
- it "is invalid without determining confidentiality" do
57
- new_application.confidential = nil
58
- expect(new_application).not_to be_valid
59
- end
60
-
61
- it "generates uid on create" do
62
- expect(new_application.uid).to be_nil
63
- new_application.save
64
- expect(new_application.uid).not_to be_nil
65
- end
66
-
67
- it "generates uid on create if an empty string" do
68
- new_application.uid = ""
69
- new_application.save
70
- expect(new_application.uid).not_to be_blank
71
- end
72
-
73
- it "generates uid on create unless one is set" do
74
- new_application.uid = uid
75
- new_application.save
76
- expect(new_application.uid).to eq(uid)
77
- end
78
-
79
- it "is invalid without uid" do
80
- new_application.save
81
- new_application.uid = nil
82
- expect(new_application).not_to be_valid
83
- end
84
-
85
123
  context "redirect URI" do
86
124
  context "when grant flows allow blank redirect URI" do
87
125
  before do
@@ -127,44 +165,6 @@ module Doorkeeper
127
165
  end
128
166
  end
129
167
 
130
- it "checks uniqueness of uid" do
131
- app1 = FactoryBot.create(:application)
132
- app2 = FactoryBot.create(:application)
133
- app2.uid = app1.uid
134
- expect(app2).not_to be_valid
135
- end
136
-
137
- it "expects database to throw an error when uids are the same" do
138
- app1 = FactoryBot.create(:application)
139
- app2 = FactoryBot.create(:application)
140
- app2.uid = app1.uid
141
- expect { app2.save!(validate: false) }.to raise_error(uniqueness_error)
142
- end
143
-
144
- it "generate secret on create" do
145
- expect(new_application.secret).to be_nil
146
- new_application.save
147
- expect(new_application.secret).not_to be_nil
148
- end
149
-
150
- it "generate secret on create if is blank string" do
151
- new_application.secret = ""
152
- new_application.save
153
- expect(new_application.secret).not_to be_blank
154
- end
155
-
156
- it "generate secret on create unless one is set" do
157
- new_application.secret = secret
158
- new_application.save
159
- expect(new_application.secret).to eq(secret)
160
- end
161
-
162
- it "is invalid without secret" do
163
- new_application.save
164
- new_application.secret = nil
165
- expect(new_application).not_to be_valid
166
- end
167
-
168
168
  context "with hashing enabled" do
169
169
  include_context "with application hashing enabled"
170
170
  let(:app) { FactoryBot.create :application }
@@ -238,7 +238,7 @@ module Doorkeeper
238
238
  end
239
239
  end
240
240
 
241
- describe :ordered_by do
241
+ describe "#ordered_by" do
242
242
  let(:applications) { FactoryBot.create_list(:application, 5) }
243
243
 
244
244
  context "when a direction is not specified" do
@@ -271,7 +271,17 @@ module Doorkeeper
271
271
  end
272
272
  end
273
273
 
274
- describe :authorized_for do
274
+ describe "#renew_secret" do
275
+ let(:app) { FactoryBot.create :application }
276
+
277
+ it "should generate a new secret" do
278
+ old_secret = app.secret
279
+ app.renew_secret
280
+ expect(old_secret).not_to eq(app.secret)
281
+ end
282
+ end
283
+
284
+ describe "#authorized_for" do
275
285
  let(:resource_owner) { double(:resource_owner, id: 10) }
276
286
 
277
287
  it "is empty if the application is not authorized for anyone" do
@@ -303,7 +313,7 @@ module Doorkeeper
303
313
  end
304
314
  end
305
315
 
306
- describe :revoke_tokens_and_grants_for do
316
+ describe "#revoke_tokens_and_grants_for" do
307
317
  it "revokes all access tokens and access grants" do
308
318
  application_id = 42
309
319
  resource_owner = double
@@ -316,7 +326,7 @@ module Doorkeeper
316
326
  end
317
327
  end
318
328
 
319
- describe :by_uid_and_secret do
329
+ describe "#by_uid_and_secret" do
320
330
  context "when application is private/confidential" do
321
331
  it "finds the application via uid/secret" do
322
332
  app = FactoryBot.create :application
@@ -350,7 +360,7 @@ module Doorkeeper
350
360
  end
351
361
  end
352
362
 
353
- describe :confidential? do
363
+ describe "#confidential?" do
354
364
  subject { FactoryBot.create(:application, confidential: confidential).confidential? }
355
365
 
356
366
  context "when application is private/confidential" do
@@ -363,5 +373,32 @@ module Doorkeeper
363
373
  it { expect(subject).to eq(false) }
364
374
  end
365
375
  end
376
+
377
+ describe "#as_json" do
378
+ let(:app) { FactoryBot.create :application, secret: "123123123" }
379
+
380
+ before do
381
+ allow(Doorkeeper.configuration)
382
+ .to receive(:application_secret_strategy).and_return(Doorkeeper::SecretStoring::Plain)
383
+ end
384
+
385
+ it "includes plaintext secret" do
386
+ expect(app.as_json).to include("secret" => "123123123")
387
+ end
388
+
389
+ it "respects custom options" do
390
+ expect(app.as_json(except: :secret)).not_to include("secret")
391
+ expect(app.as_json(only: :id)).to match("id" => app.id)
392
+ end
393
+
394
+ # AR specific
395
+ if DOORKEEPER_ORM == :active_record
396
+ it "correctly works with #to_json" do
397
+ ActiveRecord::Base.include_root_in_json = true
398
+ expect(app.to_json(include_root_in_json: true)).to match(/application.+?:\{/)
399
+ ActiveRecord::Base.include_root_in_json = false
400
+ end
401
+ end
402
+ end
366
403
  end
367
404
  end
@@ -91,7 +91,7 @@ feature "Adding applications" do
91
91
  i_should_see "Whoops! Check your form for possible errors"
92
92
  i_should_see Regexp.new(
93
93
  I18n.t("activerecord.errors.models.doorkeeper/application.attributes.scopes.not_match_configured"),
94
- true
94
+ true,
95
95
  )
96
96
  end
97
97
 
@@ -4,6 +4,7 @@ require "spec_helper"
4
4
 
5
5
  feature "Authorization endpoint" do
6
6
  background do
7
+ default_scopes_exist :default
7
8
  config_is_set(:authenticate_resource_owner) { User.first || redirect_to("/sign_in") }
8
9
  client_exists(name: "MyApp")
9
10
  end
@@ -34,16 +35,31 @@ feature "Authorization endpoint" do
34
35
  end
35
36
  end
36
37
 
37
- context "with a invalid request" do
38
+ context "with a invalid request's param" do
38
39
  background do
39
40
  create_resource_owner
40
41
  sign_in
41
42
  end
42
43
 
43
- scenario "displays the related error" do
44
- visit authorization_endpoint_url(client: @client, response_type: "")
45
- i_should_not_see "Authorize"
46
- i_should_see_translated_error_message :unsupported_response_type
44
+ context "when missing required param" do
45
+ scenario "displays invalid_request error when missing client" do
46
+ visit authorization_endpoint_url(client: nil, response_type: "code")
47
+ i_should_not_see "Authorize"
48
+ i_should_see_translated_invalid_request_error_message :missing_param, :client_id
49
+ end
50
+
51
+ scenario "displays invalid_request error when missing response_type param" do
52
+ visit authorization_endpoint_url(client: @client, response_type: "")
53
+ i_should_not_see "Authorize"
54
+ i_should_see_translated_invalid_request_error_message :missing_param, :response_type
55
+ end
56
+
57
+ scenario "displays invalid_request error when missing scope param and authorization server has no default scopes" do
58
+ config_is_set(:default_scopes, [])
59
+ visit authorization_endpoint_url(client: @client, response_type: "code", scope: "")
60
+ i_should_not_see "Authorize"
61
+ i_should_see_translated_invalid_request_error_message :missing_param, :scope
62
+ end
47
63
  end
48
64
 
49
65
  scenario "displays unsupported_response_type error when using a disabled response type" do
@@ -63,9 +79,11 @@ feature "Authorization endpoint" do
63
79
  scenario "raises exception on forged requests" do
64
80
  allowing_forgery_protection do
65
81
  expect do
66
- page.driver.post authorization_endpoint_url(client_id: @client.uid,
67
- redirect_uri: @client.redirect_uri,
68
- response_type: "code")
82
+ page.driver.post authorization_endpoint_url(
83
+ client_id: @client.uid,
84
+ redirect_uri: @client.redirect_uri,
85
+ response_type: "code",
86
+ )
69
87
  end.to raise_error(ActionController::InvalidAuthenticityToken)
70
88
  end
71
89
  end
@@ -70,6 +70,6 @@ describe "Token endpoint" do
70
70
 
71
71
  should_not_have_json "access_token"
72
72
  should_have_json "error", "invalid_request"
73
- should_have_json "error_description", translated_error_message("invalid_request")
73
+ should_have_json "error_description", translated_invalid_request_error_message(:missing_param, :grant_type)
74
74
  end
75
75
  end
@@ -5,6 +5,7 @@ require "spec_helper"
5
5
  feature "Authorization Code Flow Errors" do
6
6
  let(:client_params) { {} }
7
7
  background do
8
+ default_scopes_exist :default
8
9
  config_is_set(:authenticate_resource_owner) { User.first || redirect_to("/sign_in") }
9
10
  client_exists client_params
10
11
  create_resource_owner