doorkeeper 5.0.3 → 5.1.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 (215) hide show
  1. checksums.yaml +4 -4
  2. data/.hound.yml +2 -1
  3. data/.rubocop.yml +37 -4
  4. data/.travis.yml +11 -21
  5. data/Appraisals +29 -7
  6. data/Dangerfile +5 -2
  7. data/Gemfile +19 -5
  8. data/NEWS.md +81 -21
  9. data/README.md +75 -485
  10. data/Rakefile +10 -8
  11. data/app/controllers/doorkeeper/application_controller.rb +1 -2
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -13
  13. data/app/controllers/doorkeeper/applications_controller.rb +20 -8
  14. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  15. data/app/controllers/doorkeeper/token_info_controller.rb +2 -2
  16. data/app/controllers/doorkeeper/tokens_controller.rb +11 -11
  17. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  18. data/app/validators/redirect_uri_validator.rb +5 -2
  19. data/app/views/doorkeeper/applications/_form.html.erb +6 -0
  20. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  21. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  22. data/bin/console +16 -0
  23. data/config/locales/en.yml +1 -0
  24. data/doorkeeper.gemspec +24 -21
  25. data/gemfiles/rails_5_0.gemfile +9 -4
  26. data/gemfiles/rails_5_1.gemfile +9 -4
  27. data/gemfiles/rails_5_2.gemfile +10 -5
  28. data/gemfiles/rails_6_0.gemfile +17 -0
  29. data/gemfiles/rails_master.gemfile +9 -9
  30. data/lib/doorkeeper/config/option.rb +64 -0
  31. data/lib/doorkeeper/config.rb +191 -75
  32. data/lib/doorkeeper/engine.rb +1 -1
  33. data/lib/doorkeeper/grape/authorization_decorator.rb +4 -4
  34. data/lib/doorkeeper/grape/helpers.rb +3 -3
  35. data/lib/doorkeeper/helpers/controller.rb +3 -2
  36. data/lib/doorkeeper/models/access_grant_mixin.rb +20 -3
  37. data/lib/doorkeeper/models/access_token_mixin.rb +63 -19
  38. data/lib/doorkeeper/models/application_mixin.rb +43 -1
  39. data/lib/doorkeeper/models/concerns/expirable.rb +4 -2
  40. data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
  41. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  42. data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
  43. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  44. data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
  45. data/lib/doorkeeper/oauth/authorization/code.rb +2 -2
  46. data/lib/doorkeeper/oauth/authorization/token.rb +12 -7
  47. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
  48. data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -4
  49. data/lib/doorkeeper/oauth/client.rb +1 -1
  50. data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -4
  51. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  52. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  53. data/lib/doorkeeper/oauth/error_response.rb +10 -6
  54. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  55. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
  56. data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -1
  57. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -1
  58. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -1
  59. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  60. data/lib/doorkeeper/oauth/pre_authorization.rb +11 -5
  61. data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
  62. data/lib/doorkeeper/oauth/scopes.rb +5 -3
  63. data/lib/doorkeeper/oauth/token.rb +2 -2
  64. data/lib/doorkeeper/oauth/token_introspection.rb +74 -8
  65. data/lib/doorkeeper/oauth/token_response.rb +9 -9
  66. data/lib/doorkeeper/oauth.rb +5 -5
  67. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
  68. data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
  69. data/lib/doorkeeper/orm/active_record/application.rb +21 -57
  70. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
  71. data/lib/doorkeeper/orm/active_record.rb +6 -6
  72. data/lib/doorkeeper/rails/helpers.rb +1 -1
  73. data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
  74. data/lib/doorkeeper/rails/routes.rb +11 -11
  75. data/lib/doorkeeper/rake/db.rake +13 -13
  76. data/lib/doorkeeper/rake.rb +1 -1
  77. data/lib/doorkeeper/request.rb +1 -1
  78. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  79. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  80. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  81. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  82. data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
  83. data/lib/doorkeeper/version.rb +3 -3
  84. data/lib/doorkeeper.rb +69 -60
  85. data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
  86. data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
  87. data/lib/generators/doorkeeper/install_generator.rb +11 -9
  88. data/lib/generators/doorkeeper/migration_generator.rb +9 -9
  89. data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
  90. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
  91. data/lib/generators/doorkeeper/templates/initializer.rb +120 -13
  92. data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -7
  93. data/lib/generators/doorkeeper/views_generator.rb +6 -4
  94. data/spec/controllers/application_metal_controller_spec.rb +24 -10
  95. data/spec/controllers/applications_controller_spec.rb +54 -52
  96. data/spec/controllers/authorizations_controller_spec.rb +139 -145
  97. data/spec/controllers/protected_resources_controller_spec.rb +78 -76
  98. data/spec/controllers/token_info_controller_spec.rb +14 -12
  99. data/spec/controllers/tokens_controller_spec.rb +167 -108
  100. data/spec/dummy/Rakefile +3 -1
  101. data/spec/dummy/app/controllers/application_controller.rb +3 -1
  102. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +2 -0
  103. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
  104. data/spec/dummy/app/controllers/home_controller.rb +5 -3
  105. data/spec/dummy/app/controllers/metal_controller.rb +2 -0
  106. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
  107. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  108. data/spec/dummy/app/models/user.rb +2 -0
  109. data/spec/dummy/config/application.rb +25 -1
  110. data/spec/dummy/config/environments/development.rb +2 -0
  111. data/spec/dummy/config/environments/production.rb +2 -0
  112. data/spec/dummy/config/environments/test.rb +3 -1
  113. data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
  114. data/spec/dummy/config/initializers/doorkeeper.rb +5 -2
  115. data/spec/dummy/config/initializers/secret_token.rb +3 -1
  116. data/spec/dummy/config/initializers/session_store.rb +3 -1
  117. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  118. data/spec/dummy/config.ru +3 -1
  119. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +17 -10
  120. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
  121. data/spec/dummy/db/schema.rb +1 -1
  122. data/spec/dummy/script/rails +5 -3
  123. data/spec/factories.rb +8 -6
  124. data/spec/generators/application_owner_generator_spec.rb +13 -26
  125. data/spec/generators/confidential_applications_generator_spec.rb +12 -28
  126. data/spec/generators/install_generator_spec.rb +17 -15
  127. data/spec/generators/migration_generator_spec.rb +13 -26
  128. data/spec/generators/pkce_generator_spec.rb +11 -26
  129. data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
  130. data/spec/generators/templates/routes.rb +2 -0
  131. data/spec/generators/views_generator_spec.rb +14 -12
  132. data/spec/grape/grape_integration_spec.rb +34 -32
  133. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
  134. data/spec/lib/config_spec.rb +268 -99
  135. data/spec/lib/doorkeeper_spec.rb +3 -1
  136. data/spec/lib/models/expirable_spec.rb +22 -8
  137. data/spec/lib/models/reusable_spec.rb +40 -0
  138. data/spec/lib/models/revocable_spec.rb +8 -6
  139. data/spec/lib/models/scopes_spec.rb +27 -13
  140. data/spec/lib/models/secret_storable_spec.rb +135 -0
  141. data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
  142. data/spec/lib/oauth/authorization_code_request_spec.rb +34 -11
  143. data/spec/lib/oauth/base_request_spec.rb +20 -8
  144. data/spec/lib/oauth/base_response_spec.rb +3 -1
  145. data/spec/lib/oauth/client/credentials_spec.rb +24 -22
  146. data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
  147. data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
  148. data/spec/lib/oauth/client_credentials/validation_spec.rb +20 -15
  149. data/spec/lib/oauth/client_credentials_integration_spec.rb +7 -5
  150. data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
  151. data/spec/lib/oauth/client_spec.rb +15 -13
  152. data/spec/lib/oauth/code_request_spec.rb +8 -6
  153. data/spec/lib/oauth/code_response_spec.rb +9 -7
  154. data/spec/lib/oauth/error_response_spec.rb +19 -11
  155. data/spec/lib/oauth/error_spec.rb +4 -2
  156. data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
  157. data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
  158. data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
  159. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -95
  160. data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
  161. data/spec/lib/oauth/password_access_token_request_spec.rb +79 -30
  162. data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
  163. data/spec/lib/oauth/refresh_token_request_spec.rb +36 -33
  164. data/spec/lib/oauth/scopes_spec.rb +63 -61
  165. data/spec/lib/oauth/token_request_spec.rb +79 -24
  166. data/spec/lib/oauth/token_response_spec.rb +40 -38
  167. data/spec/lib/oauth/token_spec.rb +60 -44
  168. data/spec/lib/request/strategy_spec.rb +3 -1
  169. data/spec/lib/secret_storing/base_spec.rb +60 -0
  170. data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
  171. data/spec/lib/secret_storing/plain_spec.rb +44 -0
  172. data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
  173. data/spec/lib/server_spec.rb +16 -14
  174. data/spec/lib/stale_records_cleaner_spec.rb +17 -17
  175. data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
  176. data/spec/models/doorkeeper/access_token_spec.rb +198 -73
  177. data/spec/models/doorkeeper/application_spec.rb +280 -288
  178. data/spec/requests/applications/applications_request_spec.rb +98 -66
  179. data/spec/requests/applications/authorized_applications_spec.rb +20 -18
  180. data/spec/requests/endpoints/authorization_spec.rb +25 -23
  181. data/spec/requests/endpoints/token_spec.rb +38 -36
  182. data/spec/requests/flows/authorization_code_errors_spec.rb +26 -24
  183. data/spec/requests/flows/authorization_code_spec.rb +193 -151
  184. data/spec/requests/flows/client_credentials_spec.rb +54 -52
  185. data/spec/requests/flows/implicit_grant_errors_spec.rb +10 -8
  186. data/spec/requests/flows/implicit_grant_spec.rb +27 -25
  187. data/spec/requests/flows/password_spec.rb +59 -55
  188. data/spec/requests/flows/refresh_token_spec.rb +45 -43
  189. data/spec/requests/flows/revoke_token_spec.rb +40 -54
  190. data/spec/requests/flows/skip_authorization_spec.rb +23 -21
  191. data/spec/requests/protected_resources/metal_spec.rb +7 -5
  192. data/spec/requests/protected_resources/private_api_spec.rb +35 -33
  193. data/spec/routing/custom_controller_routes_spec.rb +71 -65
  194. data/spec/routing/default_routes_spec.rb +22 -20
  195. data/spec/routing/scoped_routes_spec.rb +20 -18
  196. data/spec/spec_helper.rb +15 -13
  197. data/spec/spec_helper_integration.rb +3 -1
  198. data/spec/support/dependencies/factory_bot.rb +3 -1
  199. data/spec/support/doorkeeper_rspec.rb +3 -1
  200. data/spec/support/helpers/access_token_request_helper.rb +3 -1
  201. data/spec/support/helpers/authorization_request_helper.rb +4 -2
  202. data/spec/support/helpers/config_helper.rb +2 -0
  203. data/spec/support/helpers/model_helper.rb +3 -1
  204. data/spec/support/helpers/request_spec_helper.rb +5 -3
  205. data/spec/support/helpers/url_helper.rb +9 -7
  206. data/spec/support/http_method_shim.rb +4 -9
  207. data/spec/support/orm/active_record.rb +3 -1
  208. data/spec/support/shared/controllers_shared_context.rb +18 -16
  209. data/spec/support/shared/hashing_shared_context.rb +36 -0
  210. data/spec/support/shared/models_shared_examples.rb +12 -10
  211. data/spec/validators/redirect_uri_validator_spec.rb +74 -45
  212. data/spec/version/version_spec.rb +7 -5
  213. metadata +60 -26
  214. data/gemfiles/rails_4_2.gemfile +0 -13
  215. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
@@ -1,4 +1,6 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  describe Doorkeeper do
4
6
  describe "#authenticate" do
@@ -1,6 +1,8 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'Expirable' do
3
+ require "spec_helper"
4
+
5
+ describe "Expirable" do
4
6
  subject do
5
7
  Class.new do
6
8
  include Doorkeeper::Models::Expirable
@@ -12,36 +14,48 @@ describe 'Expirable' do
12
14
  end
13
15
 
14
16
  describe :expired? do
15
- it 'is not expired if time has not passed' do
17
+ it "is not expired if time has not passed" do
16
18
  allow(subject).to receive(:expires_in).and_return(2.minutes)
17
19
  expect(subject).not_to be_expired
18
20
  end
19
21
 
20
- it 'is expired if time has passed' do
22
+ it "is expired if time has passed" do
21
23
  allow(subject).to receive(:expires_in).and_return(10.seconds)
22
24
  expect(subject).to be_expired
23
25
  end
24
26
 
25
- it 'is not expired if expires_in is not set' do
27
+ it "is not expired if expires_in is not set" do
26
28
  allow(subject).to receive(:expires_in).and_return(nil)
27
29
  expect(subject).not_to be_expired
28
30
  end
29
31
  end
30
32
 
31
33
  describe :expires_in_seconds do
32
- it 'should return the amount of time remaining until the token is expired' do
34
+ it "should return the amount of time remaining until the token is expired" do
33
35
  allow(subject).to receive(:expires_in).and_return(2.minutes)
34
36
  expect(subject.expires_in_seconds).to eq(60)
35
37
  end
36
38
 
37
- it 'should return 0 when expired' do
39
+ it "should return 0 when expired" do
38
40
  allow(subject).to receive(:expires_in).and_return(30.seconds)
39
41
  expect(subject.expires_in_seconds).to eq(0)
40
42
  end
41
43
 
42
- it 'should return nil when expires_in is nil' do
44
+ it "should return nil when expires_in is nil" do
43
45
  allow(subject).to receive(:expires_in).and_return(nil)
44
46
  expect(subject.expires_in_seconds).to be_nil
45
47
  end
46
48
  end
49
+
50
+ describe :expires_at do
51
+ it "should return the expiration time of the token" do
52
+ allow(subject).to receive(:expires_in).and_return(2.minutes)
53
+ expect(subject.expires_at).to be_a(Time)
54
+ end
55
+
56
+ it "should return nil when expires_in is nil" do
57
+ allow(subject).to receive(:expires_in).and_return(nil)
58
+ expect(subject.expires_at).to be_nil
59
+ end
60
+ end
47
61
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe "Reusable" do
6
+ subject do
7
+ Class.new do
8
+ include Doorkeeper::Models::Reusable
9
+ end.new
10
+ end
11
+
12
+ describe :reusable? do
13
+ it "is reusable if its expires_in is nil" do
14
+ allow(subject).to receive(:expired?).and_return(false)
15
+ allow(subject).to receive(:expires_in).and_return(nil)
16
+ expect(subject).to be_reusable
17
+ end
18
+
19
+ it "is reusable if its expiry has crossed reusable limit" do
20
+ allow(subject).to receive(:expired?).and_return(false)
21
+ allow(Doorkeeper.configuration).to receive(:token_reuse_limit).and_return(90)
22
+ allow(subject).to receive(:expires_in).and_return(100.seconds)
23
+ allow(subject).to receive(:expires_in_seconds).and_return(20.seconds)
24
+ expect(subject).to be_reusable
25
+ end
26
+
27
+ it "is not reusable if its expiry has crossed reusable limit" do
28
+ allow(subject).to receive(:expired?).and_return(false)
29
+ allow(Doorkeeper.configuration).to receive(:token_reuse_limit).and_return(90)
30
+ allow(subject).to receive(:expires_in).and_return(100.seconds)
31
+ allow(subject).to receive(:expires_in_seconds).and_return(5.seconds)
32
+ expect(subject).not_to be_reusable
33
+ end
34
+
35
+ it "is not reusable if it is already expired" do
36
+ allow(subject).to receive(:expired?).and_return(true)
37
+ expect(subject).not_to be_reusable
38
+ end
39
+ end
40
+ end
@@ -1,6 +1,8 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'Revocable' do
3
+ require "spec_helper"
4
+
5
+ describe "Revocable" do
4
6
  subject do
5
7
  Class.new do
6
8
  include Doorkeeper::Models::Revocable
@@ -8,7 +10,7 @@ describe 'Revocable' do
8
10
  end
9
11
 
10
12
  describe :revoke do
11
- it 'updates :revoked_at attribute with current time' do
13
+ it "updates :revoked_at attribute with current time" do
12
14
  utc = double utc: double
13
15
  clock = double now: utc
14
16
  expect(subject).to receive(:update_attribute).with(:revoked_at, clock.now.utc)
@@ -17,17 +19,17 @@ describe 'Revocable' do
17
19
  end
18
20
 
19
21
  describe :revoked? do
20
- it 'is revoked if :revoked_at has passed' do
22
+ it "is revoked if :revoked_at has passed" do
21
23
  allow(subject).to receive(:revoked_at).and_return(Time.now.utc - 1000)
22
24
  expect(subject).to be_revoked
23
25
  end
24
26
 
25
- it 'is not revoked if :revoked_at has not passed' do
27
+ it "is not revoked if :revoked_at has not passed" do
26
28
  allow(subject).to receive(:revoked_at).and_return(Time.now.utc + 1000)
27
29
  expect(subject).not_to be_revoked
28
30
  end
29
31
 
30
- it 'is not revoked if :revoked_at is not set' do
32
+ it "is not revoked if :revoked_at is not set" do
31
33
  allow(subject).to receive(:revoked_at).and_return(nil)
32
34
  expect(subject).not_to be_revoked
33
35
  end
@@ -1,39 +1,53 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
2
 
3
- describe 'Doorkeeper::Models::Scopes' do
3
+ require "spec_helper"
4
+
5
+ describe "Doorkeeper::Models::Scopes" do
4
6
  subject do
5
- Class.new(Hash) do
7
+ Class.new(Struct.new(:scopes)) do
6
8
  include Doorkeeper::Models::Scopes
7
9
  end.new
8
10
  end
9
11
 
10
12
  before do
11
- subject[:scopes] = 'public admin'
13
+ subject[:scopes] = "public admin"
12
14
  end
13
15
 
14
16
  describe :scopes do
15
- it 'is a `Scopes` class' do
17
+ it "is a `Scopes` class" do
16
18
  expect(subject.scopes).to be_a(Doorkeeper::OAuth::Scopes)
17
19
  end
18
20
 
19
- it 'includes scopes' do
20
- expect(subject.scopes).to include('public')
21
+ it "includes scopes" do
22
+ expect(subject.scopes).to include("public")
23
+ end
24
+ end
25
+
26
+ describe :scopes= do
27
+ it "accepts String" do
28
+ subject.scopes = "private admin"
29
+ expect(subject.scopes_string).to eq("private admin")
30
+ end
31
+
32
+ it "accepts Array" do
33
+ subject.scopes = %w[private admin]
34
+ expect(subject.scopes_string).to eq("private admin")
21
35
  end
22
36
  end
23
37
 
24
38
  describe :scopes_string do
25
- it 'is a `Scopes` class' do
26
- expect(subject.scopes_string).to eq('public admin')
39
+ it "is a `Scopes` class" do
40
+ expect(subject.scopes_string).to eq("public admin")
27
41
  end
28
42
  end
29
43
 
30
44
  describe :includes_scope? do
31
- it 'should return true if at least one scope is included' do
32
- expect(subject.includes_scope?('public', 'private')).to be true
45
+ it "should return true if at least one scope is included" do
46
+ expect(subject.includes_scope?("public", "private")).to be true
33
47
  end
34
48
 
35
- it 'should return false if no scopes are included' do
36
- expect(subject.includes_scope?('teacher', 'student')).to be false
49
+ it "should return false if no scopes are included" do
50
+ expect(subject.includes_scope?("teacher", "student")).to be false
37
51
  end
38
52
  end
39
53
  end
@@ -0,0 +1,135 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe "SecretStorable" do
6
+ let(:clazz) do
7
+ Class.new do
8
+ include Doorkeeper::Models::SecretStorable
9
+
10
+ def self.find_by(*)
11
+ raise "stub this"
12
+ end
13
+
14
+ def update_column(*)
15
+ raise "stub this"
16
+ end
17
+
18
+ def token
19
+ raise "stub this"
20
+ end
21
+ end
22
+ end
23
+ let(:strategy) { clazz.secret_strategy }
24
+
25
+ describe :find_by_plaintext_token do
26
+ subject { clazz.send(:find_by_plaintext_token, "attr", "input") }
27
+
28
+ it "forwards to the secret_strategy" do
29
+ expect(strategy)
30
+ .to receive(:transform_secret)
31
+ .with("input")
32
+ .and_return "found"
33
+
34
+ expect(clazz)
35
+ .to receive(:find_by)
36
+ .with("attr" => "found")
37
+ .and_return "result"
38
+
39
+ expect(subject).to eq "result"
40
+ end
41
+
42
+ it "calls find_by_fallback_token if not found" do
43
+ expect(clazz)
44
+ .to receive(:find_by)
45
+ .with("attr" => "input")
46
+ .and_return nil
47
+
48
+ expect(clazz)
49
+ .to receive(:find_by_fallback_token)
50
+ .with("attr", "input")
51
+ .and_return "fallback"
52
+
53
+ expect(subject).to eq "fallback"
54
+ end
55
+ end
56
+
57
+ describe :find_by_fallback_token do
58
+ subject { clazz.send(:find_by_fallback_token, "attr", "input") }
59
+ let(:fallback) { double(::Doorkeeper::SecretStoring::Plain) }
60
+
61
+ it "returns nil if none defined" do
62
+ expect(clazz.fallback_secret_strategy).to eq nil
63
+ expect(subject).to eq nil
64
+ end
65
+
66
+ context "if a fallback strategy is defined" do
67
+ before do
68
+ allow(clazz).to receive(:fallback_secret_strategy).and_return(fallback)
69
+ end
70
+
71
+ context "if a resource is defined" do
72
+ let(:resource) { double("Token model") }
73
+
74
+ it "calls the strategy for lookup" do
75
+ expect(clazz)
76
+ .to receive(:find_by)
77
+ .with("attr" => "fallback")
78
+ .and_return(resource)
79
+
80
+ expect(fallback)
81
+ .to receive(:transform_secret)
82
+ .with("input")
83
+ .and_return("fallback")
84
+
85
+ # store_secret will call the resource
86
+ expect(resource)
87
+ .to receive(:attr=)
88
+ .with("new value")
89
+
90
+ # It will upgrade the secret automtically using the current strategy
91
+ expect(strategy)
92
+ .to receive(:transform_secret)
93
+ .with("input")
94
+ .and_return("new value")
95
+
96
+ expect(resource).to receive(:update).with("attr" => "new value")
97
+ expect(subject).to eq resource
98
+ end
99
+ end
100
+
101
+ context "if a resource is not defined" do
102
+ before do
103
+ allow(clazz).to receive(:fallback_secret_strategy).and_return(fallback)
104
+ end
105
+
106
+ it "returns nil" do
107
+ expect(clazz)
108
+ .to receive(:find_by)
109
+ .with("attr" => "fallback")
110
+ .and_return(nil)
111
+
112
+ expect(fallback)
113
+ .to receive(:transform_secret)
114
+ .with("input")
115
+ .and_return("fallback")
116
+
117
+ # It does not find a token even with the fallback method
118
+ expect(subject).to be_nil
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ describe :secret_strategy do
125
+ it "defaults to plain strategy" do
126
+ expect(strategy).to eq Doorkeeper::SecretStoring::Plain
127
+ end
128
+ end
129
+
130
+ describe :fallback_secret_strategy do
131
+ it "defaults to nil" do
132
+ expect(clazz.fallback_secret_strategy).to eq nil
133
+ end
134
+ end
135
+ end
@@ -1,36 +1,38 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Doorkeeper::OAuth::Authorization
4
6
  describe URIBuilder do
5
7
  subject { URIBuilder }
6
8
 
7
9
  describe :uri_with_query do
8
- it 'returns the uri with query' do
9
- uri = subject.uri_with_query 'http://example.com/', parameter: 'value'
10
- expect(uri).to eq('http://example.com/?parameter=value')
10
+ it "returns the uri with query" do
11
+ uri = subject.uri_with_query "http://example.com/", parameter: "value"
12
+ expect(uri).to eq("http://example.com/?parameter=value")
11
13
  end
12
14
 
13
- it 'rejects nil values' do
14
- uri = subject.uri_with_query 'http://example.com/', parameter: ''
15
- expect(uri).to eq('http://example.com/?')
15
+ it "rejects nil values" do
16
+ uri = subject.uri_with_query "http://example.com/", parameter: ""
17
+ expect(uri).to eq("http://example.com/?")
16
18
  end
17
19
 
18
- it 'preserves original query parameters' do
19
- uri = subject.uri_with_query 'http://example.com/?query1=value', parameter: 'value'
20
+ it "preserves original query parameters" do
21
+ uri = subject.uri_with_query "http://example.com/?query1=value", parameter: "value"
20
22
  expect(uri).to match(/query1=value/)
21
23
  expect(uri).to match(/parameter=value/)
22
24
  end
23
25
  end
24
26
 
25
27
  describe :uri_with_fragment do
26
- it 'returns uri with parameters as fragments' do
27
- uri = subject.uri_with_fragment 'http://example.com/', parameter: 'value'
28
- expect(uri).to eq('http://example.com/#parameter=value')
28
+ it "returns uri with parameters as fragments" do
29
+ uri = subject.uri_with_fragment "http://example.com/", parameter: "value"
30
+ expect(uri).to eq("http://example.com/#parameter=value")
29
31
  end
30
32
 
31
- it 'preserves original query parameters' do
32
- uri = subject.uri_with_fragment 'http://example.com/?query1=value1', parameter: 'value'
33
- expect(uri).to eq('http://example.com/?query1=value1#parameter=value')
33
+ it "preserves original query parameters" do
34
+ uri = subject.uri_with_fragment "http://example.com/?query1=value1", parameter: "value"
35
+ expect(uri).to eq("http://example.com/?query1=value1#parameter=value")
34
36
  end
35
37
  end
36
38
  end
@@ -1,4 +1,6 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Doorkeeper::OAuth
4
6
  describe AuthorizationCodeRequest do
@@ -16,11 +18,15 @@ module Doorkeeper::OAuth
16
18
  let(:redirect_uri) { client.redirect_uri }
17
19
  let(:params) { { redirect_uri: redirect_uri } }
18
20
 
21
+ before do
22
+ allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
23
+ end
24
+
19
25
  subject do
20
26
  AuthorizationCodeRequest.new server, grant, client, params
21
27
  end
22
28
 
23
- it 'issues a new token for the client' do
29
+ it "issues a new token for the client" do
24
30
  expect do
25
31
  subject.authorize
26
32
  end.to change { client.reload.access_tokens.count }.by(1)
@@ -33,36 +39,36 @@ module Doorkeeper::OAuth
33
39
  expect(Doorkeeper::AccessToken.last.scopes).to eq(grant.scopes)
34
40
  end
35
41
 
36
- it 'revokes the grant' do
42
+ it "revokes the grant" do
37
43
  expect { subject.authorize }.to(change { grant.reload.accessible? })
38
44
  end
39
45
 
40
- it 'requires the grant to be accessible' do
46
+ it "requires the grant to be accessible" do
41
47
  grant.revoke
42
48
  subject.validate
43
49
  expect(subject.error).to eq(:invalid_grant)
44
50
  end
45
51
 
46
- it 'requires the grant' do
52
+ it "requires the grant" do
47
53
  subject.grant = nil
48
54
  subject.validate
49
55
  expect(subject.error).to eq(:invalid_grant)
50
56
  end
51
57
 
52
- it 'requires the client' do
58
+ it "requires the client" do
53
59
  subject.client = nil
54
60
  subject.validate
55
61
  expect(subject.error).to eq(:invalid_client)
56
62
  end
57
63
 
58
- it 'requires the redirect_uri' do
64
+ it "requires the redirect_uri" do
59
65
  subject.redirect_uri = nil
60
66
  subject.validate
61
67
  expect(subject.error).to eq(:invalid_request)
62
68
  end
63
69
 
64
70
  it "matches the redirect_uri with grant's one" do
65
- subject.redirect_uri = 'http://other.com'
71
+ subject.redirect_uri = "http://other.com"
66
72
  subject.validate
67
73
  expect(subject.error).to eq(:invalid_grant)
68
74
  end
@@ -73,7 +79,7 @@ module Doorkeeper::OAuth
73
79
  expect(subject.error).to eq(:invalid_grant)
74
80
  end
75
81
 
76
- it 'skips token creation if there is a matching one' do
82
+ it "skips token creation if there is a matching one reusable" do
77
83
  scopes = grant.scopes
78
84
 
79
85
  Doorkeeper.configure do
@@ -88,6 +94,23 @@ module Doorkeeper::OAuth
88
94
  expect { subject.authorize }.to_not(change { Doorkeeper::AccessToken.count })
89
95
  end
90
96
 
97
+ it "creates token if there is a matching one but non reusable" do
98
+ scopes = grant.scopes
99
+
100
+ Doorkeeper.configure do
101
+ orm DOORKEEPER_ORM
102
+ reuse_access_token
103
+ default_scopes(*scopes)
104
+ end
105
+
106
+ FactoryBot.create(:access_token, application_id: client.id,
107
+ resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s)
108
+
109
+ allow_any_instance_of(Doorkeeper::AccessToken).to receive(:reusable?).and_return(false)
110
+
111
+ expect { subject.authorize }.to change { Doorkeeper::AccessToken.count }.by(1)
112
+ end
113
+
91
114
  it "calls configured request callback methods" do
92
115
  expect(Doorkeeper.configuration.before_successful_strategy_response)
93
116
  .to receive(:call).with(subject).once
@@ -107,7 +130,7 @@ module Doorkeeper::OAuth
107
130
  end
108
131
 
109
132
  context "when redirect_uri is not an URI" do
110
- let(:redirect_uri) { '123d#!s' }
133
+ let(:redirect_uri) { "123d#!s" }
111
134
 
112
135
  it "responds with invalid_grant" do
113
136
  subject.validate
@@ -116,7 +139,7 @@ module Doorkeeper::OAuth
116
139
  end
117
140
 
118
141
  context "when redirect_uri is the native one" do
119
- let(:redirect_uri) { 'urn:ietf:wg:oauth:2.0:oob' }
142
+ let(:redirect_uri) { "urn:ietf:wg:oauth:2.0:oob" }
120
143
 
121
144
  it "invalidates when redirect_uri of the grant is not native" do
122
145
  subject.validate
@@ -1,19 +1,21 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Doorkeeper::OAuth
4
6
  describe BaseRequest do
5
7
  let(:access_token) do
6
8
  double :access_token,
7
- token: "some-token",
8
- expires_in: "3600",
9
+ plaintext_token: "some-token",
10
+ expires_in: "3600",
9
11
  expires_in_seconds: "300",
10
- scopes_string: "two scopes",
11
- refresh_token: "some-refresh-token",
12
- token_type: "bearer",
13
- created_at: 0
12
+ scopes_string: "two scopes",
13
+ plaintext_refresh_token: "some-refresh-token",
14
+ token_type: "bearer",
15
+ created_at: 0
14
16
  end
15
17
 
16
- let(:client) { double :client, id: '1' }
18
+ let(:client) { double :client, id: "1" }
17
19
 
18
20
  let(:scopes_array) { %w[public write] }
19
21
 
@@ -24,6 +26,10 @@ module Doorkeeper::OAuth
24
26
  refresh_token_enabled?: false
25
27
  end
26
28
 
29
+ before do
30
+ allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
31
+ end
32
+
27
33
  subject do
28
34
  BaseRequest.new
29
35
  end
@@ -111,6 +117,9 @@ module Doorkeeper::OAuth
111
117
  access_token_expires_in: 100,
112
118
  custom_access_token_expires_in: ->(context) { context.scopes == "public" ? 500 : nil },
113
119
  refresh_token_enabled?: false)
120
+
121
+ allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
122
+
114
123
  result = subject.find_or_create_access_token(
115
124
  client,
116
125
  "1",
@@ -127,6 +136,9 @@ module Doorkeeper::OAuth
127
136
  refresh_token_enabled?: lambda { |context|
128
137
  context.scopes == "public"
129
138
  })
139
+
140
+ allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
141
+
130
142
  result = subject.find_or_create_access_token(
131
143
  client,
132
144
  "1",
@@ -1,4 +1,6 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  module Doorkeeper::OAuth
4
6
  describe BaseResponse do