doorkeeper 5.0.2 → 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 (214) hide show
  1. checksums.yaml +5 -5
  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 +80 -19
  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 +17 -5
  14. data/app/controllers/doorkeeper/token_info_controller.rb +2 -2
  15. data/app/controllers/doorkeeper/tokens_controller.rb +11 -11
  16. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  17. data/app/validators/redirect_uri_validator.rb +5 -2
  18. data/app/views/doorkeeper/applications/_form.html.erb +6 -0
  19. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  20. data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
  21. data/bin/console +16 -0
  22. data/config/locales/en.yml +1 -0
  23. data/doorkeeper.gemspec +24 -21
  24. data/gemfiles/rails_5_0.gemfile +9 -4
  25. data/gemfiles/rails_5_1.gemfile +9 -4
  26. data/gemfiles/rails_5_2.gemfile +10 -5
  27. data/gemfiles/rails_6_0.gemfile +17 -0
  28. data/gemfiles/rails_master.gemfile +9 -9
  29. data/lib/doorkeeper/config/option.rb +64 -0
  30. data/lib/doorkeeper/config.rb +191 -75
  31. data/lib/doorkeeper/engine.rb +1 -1
  32. data/lib/doorkeeper/grape/authorization_decorator.rb +4 -4
  33. data/lib/doorkeeper/grape/helpers.rb +3 -3
  34. data/lib/doorkeeper/helpers/controller.rb +3 -2
  35. data/lib/doorkeeper/models/access_grant_mixin.rb +20 -3
  36. data/lib/doorkeeper/models/access_token_mixin.rb +63 -19
  37. data/lib/doorkeeper/models/application_mixin.rb +43 -1
  38. data/lib/doorkeeper/models/concerns/expirable.rb +4 -2
  39. data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
  40. data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
  41. data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
  42. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  43. data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
  44. data/lib/doorkeeper/oauth/authorization/code.rb +2 -2
  45. data/lib/doorkeeper/oauth/authorization/token.rb +12 -7
  46. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
  47. data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -4
  48. data/lib/doorkeeper/oauth/client.rb +1 -1
  49. data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -4
  50. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  51. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  52. data/lib/doorkeeper/oauth/error_response.rb +10 -6
  53. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  54. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
  55. data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -1
  56. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -1
  57. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -1
  58. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  59. data/lib/doorkeeper/oauth/pre_authorization.rb +11 -5
  60. data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
  61. data/lib/doorkeeper/oauth/scopes.rb +5 -3
  62. data/lib/doorkeeper/oauth/token.rb +2 -2
  63. data/lib/doorkeeper/oauth/token_introspection.rb +74 -8
  64. data/lib/doorkeeper/oauth/token_response.rb +9 -9
  65. data/lib/doorkeeper/oauth.rb +5 -5
  66. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
  67. data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
  68. data/lib/doorkeeper/orm/active_record/application.rb +26 -7
  69. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
  70. data/lib/doorkeeper/orm/active_record.rb +6 -6
  71. data/lib/doorkeeper/rails/helpers.rb +1 -1
  72. data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
  73. data/lib/doorkeeper/rails/routes.rb +11 -11
  74. data/lib/doorkeeper/rake/db.rake +13 -13
  75. data/lib/doorkeeper/rake.rb +1 -1
  76. data/lib/doorkeeper/request.rb +1 -1
  77. data/lib/doorkeeper/secret_storing/base.rb +64 -0
  78. data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
  79. data/lib/doorkeeper/secret_storing/plain.rb +33 -0
  80. data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
  81. data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
  82. data/lib/doorkeeper/version.rb +3 -3
  83. data/lib/doorkeeper.rb +69 -60
  84. data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
  85. data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
  86. data/lib/generators/doorkeeper/install_generator.rb +11 -9
  87. data/lib/generators/doorkeeper/migration_generator.rb +9 -9
  88. data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
  89. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
  90. data/lib/generators/doorkeeper/templates/initializer.rb +120 -13
  91. data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -7
  92. data/lib/generators/doorkeeper/views_generator.rb +6 -4
  93. data/spec/controllers/application_metal_controller_spec.rb +24 -10
  94. data/spec/controllers/applications_controller_spec.rb +54 -52
  95. data/spec/controllers/authorizations_controller_spec.rb +139 -145
  96. data/spec/controllers/protected_resources_controller_spec.rb +78 -76
  97. data/spec/controllers/token_info_controller_spec.rb +14 -12
  98. data/spec/controllers/tokens_controller_spec.rb +167 -108
  99. data/spec/dummy/Rakefile +3 -1
  100. data/spec/dummy/app/controllers/application_controller.rb +3 -1
  101. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +2 -0
  102. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
  103. data/spec/dummy/app/controllers/home_controller.rb +5 -3
  104. data/spec/dummy/app/controllers/metal_controller.rb +2 -0
  105. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
  106. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  107. data/spec/dummy/app/models/user.rb +2 -0
  108. data/spec/dummy/config/application.rb +25 -1
  109. data/spec/dummy/config/environments/development.rb +2 -0
  110. data/spec/dummy/config/environments/production.rb +2 -0
  111. data/spec/dummy/config/environments/test.rb +3 -1
  112. data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
  113. data/spec/dummy/config/initializers/doorkeeper.rb +5 -2
  114. data/spec/dummy/config/initializers/secret_token.rb +3 -1
  115. data/spec/dummy/config/initializers/session_store.rb +3 -1
  116. data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
  117. data/spec/dummy/config.ru +3 -1
  118. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +17 -10
  119. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
  120. data/spec/dummy/db/schema.rb +1 -1
  121. data/spec/dummy/script/rails +5 -3
  122. data/spec/factories.rb +8 -6
  123. data/spec/generators/application_owner_generator_spec.rb +13 -26
  124. data/spec/generators/confidential_applications_generator_spec.rb +12 -28
  125. data/spec/generators/install_generator_spec.rb +17 -15
  126. data/spec/generators/migration_generator_spec.rb +13 -26
  127. data/spec/generators/pkce_generator_spec.rb +11 -26
  128. data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
  129. data/spec/generators/templates/routes.rb +2 -0
  130. data/spec/generators/views_generator_spec.rb +14 -12
  131. data/spec/grape/grape_integration_spec.rb +34 -32
  132. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
  133. data/spec/lib/config_spec.rb +268 -99
  134. data/spec/lib/doorkeeper_spec.rb +3 -1
  135. data/spec/lib/models/expirable_spec.rb +22 -8
  136. data/spec/lib/models/reusable_spec.rb +40 -0
  137. data/spec/lib/models/revocable_spec.rb +8 -6
  138. data/spec/lib/models/scopes_spec.rb +27 -13
  139. data/spec/lib/models/secret_storable_spec.rb +135 -0
  140. data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
  141. data/spec/lib/oauth/authorization_code_request_spec.rb +34 -11
  142. data/spec/lib/oauth/base_request_spec.rb +20 -8
  143. data/spec/lib/oauth/base_response_spec.rb +3 -1
  144. data/spec/lib/oauth/client/credentials_spec.rb +24 -22
  145. data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
  146. data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
  147. data/spec/lib/oauth/client_credentials/validation_spec.rb +20 -15
  148. data/spec/lib/oauth/client_credentials_integration_spec.rb +7 -5
  149. data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
  150. data/spec/lib/oauth/client_spec.rb +15 -13
  151. data/spec/lib/oauth/code_request_spec.rb +8 -6
  152. data/spec/lib/oauth/code_response_spec.rb +9 -7
  153. data/spec/lib/oauth/error_response_spec.rb +19 -11
  154. data/spec/lib/oauth/error_spec.rb +4 -2
  155. data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
  156. data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
  157. data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
  158. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -95
  159. data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
  160. data/spec/lib/oauth/password_access_token_request_spec.rb +79 -30
  161. data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
  162. data/spec/lib/oauth/refresh_token_request_spec.rb +36 -33
  163. data/spec/lib/oauth/scopes_spec.rb +63 -61
  164. data/spec/lib/oauth/token_request_spec.rb +79 -24
  165. data/spec/lib/oauth/token_response_spec.rb +40 -38
  166. data/spec/lib/oauth/token_spec.rb +60 -44
  167. data/spec/lib/request/strategy_spec.rb +3 -1
  168. data/spec/lib/secret_storing/base_spec.rb +60 -0
  169. data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
  170. data/spec/lib/secret_storing/plain_spec.rb +44 -0
  171. data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
  172. data/spec/lib/server_spec.rb +16 -14
  173. data/spec/lib/stale_records_cleaner_spec.rb +17 -17
  174. data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
  175. data/spec/models/doorkeeper/access_token_spec.rb +198 -73
  176. data/spec/models/doorkeeper/application_spec.rb +142 -45
  177. data/spec/requests/applications/applications_request_spec.rb +98 -66
  178. data/spec/requests/applications/authorized_applications_spec.rb +20 -18
  179. data/spec/requests/endpoints/authorization_spec.rb +25 -23
  180. data/spec/requests/endpoints/token_spec.rb +38 -36
  181. data/spec/requests/flows/authorization_code_errors_spec.rb +26 -24
  182. data/spec/requests/flows/authorization_code_spec.rb +193 -151
  183. data/spec/requests/flows/client_credentials_spec.rb +54 -52
  184. data/spec/requests/flows/implicit_grant_errors_spec.rb +10 -8
  185. data/spec/requests/flows/implicit_grant_spec.rb +27 -25
  186. data/spec/requests/flows/password_spec.rb +59 -55
  187. data/spec/requests/flows/refresh_token_spec.rb +45 -43
  188. data/spec/requests/flows/revoke_token_spec.rb +40 -54
  189. data/spec/requests/flows/skip_authorization_spec.rb +23 -21
  190. data/spec/requests/protected_resources/metal_spec.rb +7 -5
  191. data/spec/requests/protected_resources/private_api_spec.rb +35 -33
  192. data/spec/routing/custom_controller_routes_spec.rb +71 -65
  193. data/spec/routing/default_routes_spec.rb +22 -20
  194. data/spec/routing/scoped_routes_spec.rb +20 -18
  195. data/spec/spec_helper.rb +15 -13
  196. data/spec/spec_helper_integration.rb +3 -1
  197. data/spec/support/dependencies/factory_bot.rb +3 -1
  198. data/spec/support/doorkeeper_rspec.rb +3 -1
  199. data/spec/support/helpers/access_token_request_helper.rb +3 -1
  200. data/spec/support/helpers/authorization_request_helper.rb +4 -2
  201. data/spec/support/helpers/config_helper.rb +2 -0
  202. data/spec/support/helpers/model_helper.rb +3 -1
  203. data/spec/support/helpers/request_spec_helper.rb +5 -3
  204. data/spec/support/helpers/url_helper.rb +9 -7
  205. data/spec/support/http_method_shim.rb +4 -9
  206. data/spec/support/orm/active_record.rb +3 -1
  207. data/spec/support/shared/controllers_shared_context.rb +18 -16
  208. data/spec/support/shared/hashing_shared_context.rb +36 -0
  209. data/spec/support/shared/models_shared_examples.rb +12 -10
  210. data/spec/validators/redirect_uri_validator_spec.rb +74 -45
  211. data/spec/version/version_spec.rb +7 -5
  212. metadata +61 -28
  213. data/gemfiles/rails_4_2.gemfile +0 -13
  214. data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
@@ -1,5 +1,7 @@
1
- shared_context 'valid token', token: :valid do
2
- let(:token_string) { '1A2B3C4D' }
1
+ # frozen_string_literal: true
2
+
3
+ shared_context "valid token", token: :valid do
4
+ let(:token_string) { "1A2B3C4D" }
3
5
 
4
6
  let :token do
5
7
  double(Doorkeeper::AccessToken,
@@ -14,8 +16,8 @@ shared_context 'valid token', token: :valid do
14
16
  end
15
17
  end
16
18
 
17
- shared_context 'invalid token', token: :invalid do
18
- let(:token_string) { '1A2B3C4D' }
19
+ shared_context "invalid token", token: :invalid do
20
+ let(:token_string) { "1A2B3C4D" }
19
21
 
20
22
  let :token do
21
23
  double(Doorkeeper::AccessToken,
@@ -31,22 +33,22 @@ shared_context 'invalid token', token: :invalid do
31
33
  end
32
34
  end
33
35
 
34
- shared_context 'authenticated resource owner' do
36
+ shared_context "authenticated resource owner" do
35
37
  before do
36
38
  user = double(:resource, id: 1)
37
39
  allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { user } }
38
40
  end
39
41
  end
40
42
 
41
- shared_context 'not authenticated resource owner' do
43
+ shared_context "not authenticated resource owner" do
42
44
  before do
43
- allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { redirect_to '/' } }
45
+ allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { redirect_to "/" } }
44
46
  end
45
47
  end
46
48
 
47
- shared_context 'valid authorization request' do
49
+ shared_context "valid authorization request" do
48
50
  let :authorization do
49
- double(:authorization, valid?: true, authorize: true, success_redirect_uri: 'http://something.com/cb?code=token')
51
+ double(:authorization, valid?: true, authorize: true, success_redirect_uri: "http://something.com/cb?code=token")
50
52
  end
51
53
 
52
54
  before do
@@ -54,7 +56,7 @@ shared_context 'valid authorization request' do
54
56
  end
55
57
  end
56
58
 
57
- shared_context 'invalid authorization request' do
59
+ shared_context "invalid authorization request" do
58
60
  let :authorization do
59
61
  double(:authorization, valid?: false, authorize: false, redirect_on_error?: false)
60
62
  end
@@ -64,9 +66,9 @@ shared_context 'invalid authorization request' do
64
66
  end
65
67
  end
66
68
 
67
- shared_context 'expired token', token: :expired do
69
+ shared_context "expired token", token: :expired do
68
70
  let :token_string do
69
- '1A2B3C4DEXP'
71
+ "1A2B3C4DEXP"
70
72
  end
71
73
 
72
74
  let :token do
@@ -83,9 +85,9 @@ shared_context 'expired token', token: :expired do
83
85
  end
84
86
  end
85
87
 
86
- shared_context 'revoked token', token: :revoked do
88
+ shared_context "revoked token", token: :revoked do
87
89
  let :token_string do
88
- '1A2B3C4DREV'
90
+ "1A2B3C4DREV"
89
91
  end
90
92
 
91
93
  let :token do
@@ -102,9 +104,9 @@ shared_context 'revoked token', token: :revoked do
102
104
  end
103
105
  end
104
106
 
105
- shared_context 'forbidden token', token: :forbidden do
107
+ shared_context "forbidden token", token: :forbidden do
106
108
  let :token_string do
107
- '1A2B3C4DFORB'
109
+ "1A2B3C4DFORB"
108
110
  end
109
111
 
110
112
  let :token do
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ shared_context "with token hashing enabled" do
4
+ let(:hashed_or_plain_token_func) do
5
+ Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
6
+ end
7
+
8
+ before do
9
+ Doorkeeper.configure do
10
+ hash_token_secrets
11
+ end
12
+ end
13
+ end
14
+
15
+ shared_context "with token hashing and fallback lookup enabled" do
16
+ let(:hashed_or_plain_token_func) do
17
+ Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
18
+ end
19
+
20
+ before do
21
+ Doorkeeper.configure do
22
+ hash_token_secrets fallback: :plain
23
+ end
24
+ end
25
+ end
26
+
27
+ shared_context "with application hashing enabled" do
28
+ let(:hashed_or_plain_token_func) do
29
+ Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
30
+ end
31
+ before do
32
+ Doorkeeper.configure do
33
+ hash_application_secrets
34
+ end
35
+ end
36
+ end
@@ -1,46 +1,48 @@
1
- shared_examples 'an accessible token' do
1
+ # frozen_string_literal: true
2
+
3
+ shared_examples "an accessible token" do
2
4
  describe :accessible? do
3
- it 'is accessible if token is not expired' do
5
+ it "is accessible if token is not expired" do
4
6
  allow(subject).to receive(:expired?).and_return(false)
5
7
  should be_accessible
6
8
  end
7
9
 
8
- it 'is not accessible if token is expired' do
10
+ it "is not accessible if token is expired" do
9
11
  allow(subject).to receive(:expired?).and_return(true)
10
12
  should_not be_accessible
11
13
  end
12
14
  end
13
15
  end
14
16
 
15
- shared_examples 'a revocable token' do
17
+ shared_examples "a revocable token" do
16
18
  describe :accessible? do
17
19
  before { subject.save! }
18
20
 
19
- it 'is accessible if token is not revoked' do
21
+ it "is accessible if token is not revoked" do
20
22
  expect(subject).to be_accessible
21
23
  end
22
24
 
23
- it 'is not accessible if token is revoked' do
25
+ it "is not accessible if token is revoked" do
24
26
  subject.revoke
25
27
  expect(subject).not_to be_accessible
26
28
  end
27
29
  end
28
30
  end
29
31
 
30
- shared_examples 'a unique token' do
32
+ shared_examples "a unique token" do
31
33
  describe :token do
32
- it 'is generated before validation' do
34
+ it "is generated before validation" do
33
35
  expect { subject.valid? }.to change { subject.token }.from(nil)
34
36
  end
35
37
 
36
- it 'is not valid if token exists' do
38
+ it "is not valid if token exists" do
37
39
  token1 = FactoryBot.create factory_name
38
40
  token2 = FactoryBot.create factory_name
39
41
  token2.token = token1.token
40
42
  expect(token2).not_to be_valid
41
43
  end
42
44
 
43
- it 'expects database to throw an error when tokens are the same' do
45
+ it "expects database to throw an error when tokens are the same" do
44
46
  token1 = FactoryBot.create factory_name
45
47
  token2 = FactoryBot.create factory_name
46
48
  token2.token = token1.token
@@ -1,12 +1,14 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  describe RedirectUriValidator do
4
6
  subject do
5
7
  FactoryBot.create(:application)
6
8
  end
7
9
 
8
- it 'is valid when the uri is a uri' do
9
- subject.redirect_uri = 'https://example.com/callback'
10
+ it "is valid when the uri is a uri" do
11
+ subject.redirect_uri = "https://example.com/callback"
10
12
  expect(subject).to be_valid
11
13
  end
12
14
 
@@ -15,115 +17,142 @@ describe RedirectUriValidator do
15
17
  # the system browser.
16
18
  #
17
19
  # @see https://www.oauth.com/oauth2-servers/redirect-uris/redirect-uris-native-apps/
18
- it 'is valid when the uri is custom native URI' do
19
- subject.redirect_uri = 'myapp://callback'
20
+ it "is valid when the uri is custom native URI" do
21
+ subject.redirect_uri = "myapp://callback"
20
22
  expect(subject).to be_valid
21
23
  end
22
24
 
23
- it 'is valid when the uri has a query parameter' do
24
- subject.redirect_uri = 'https://example.com/abcd?xyz=123'
25
+ it "is valid when the uri has a query parameter" do
26
+ subject.redirect_uri = "https://example.com/abcd?xyz=123"
25
27
  expect(subject).to be_valid
26
28
  end
27
29
 
28
- it 'accepts native redirect uri' do
29
- subject.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
30
+ it "accepts native redirect uri" do
31
+ subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
30
32
  expect(subject).to be_valid
31
33
  end
32
34
 
33
- it 'rejects if test uri is disabled' do
35
+ it "rejects if test uri is disabled" do
34
36
  allow(RedirectUriValidator).to receive(:native_redirect_uri).and_return(nil)
35
- subject.redirect_uri = 'urn:some:test'
37
+ subject.redirect_uri = "urn:some:test"
36
38
  expect(subject).not_to be_valid
37
39
  end
38
40
 
39
- it 'is invalid when the uri is not a uri' do
40
- subject.redirect_uri = ']'
41
+ it "is invalid when the uri is not a uri" do
42
+ subject.redirect_uri = "]"
41
43
  expect(subject).not_to be_valid
42
- expect(subject.errors[:redirect_uri].first).to eq('must be a valid URI.')
44
+ expect(subject.errors[:redirect_uri].first).to eq("must be a valid URI.")
43
45
  end
44
46
 
45
- it 'is invalid when the uri is relative' do
46
- subject.redirect_uri = '/abcd'
47
+ it "is invalid when the uri is relative" do
48
+ subject.redirect_uri = "/abcd"
47
49
  expect(subject).not_to be_valid
48
- expect(subject.errors[:redirect_uri].first).to eq('must be an absolute URI.')
50
+ expect(subject.errors[:redirect_uri].first).to eq("must be an absolute URI.")
49
51
  end
50
52
 
51
- it 'is invalid when the uri has a fragment' do
52
- subject.redirect_uri = 'https://example.com/abcd#xyz'
53
+ it "is invalid when the uri has a fragment" do
54
+ subject.redirect_uri = "https://example.com/abcd#xyz"
53
55
  expect(subject).not_to be_valid
54
- expect(subject.errors[:redirect_uri].first).to eq('cannot contain a fragment.')
56
+ expect(subject.errors[:redirect_uri].first).to eq("cannot contain a fragment.")
55
57
  end
56
58
 
57
- context 'force secured uri' do
58
- it 'accepts an valid uri' do
59
- subject.redirect_uri = 'https://example.com/callback'
59
+ context "force secured uri" do
60
+ it "accepts an valid uri" do
61
+ subject.redirect_uri = "https://example.com/callback"
60
62
  expect(subject).to be_valid
61
63
  end
62
64
 
63
- it 'accepts native redirect uri' do
64
- subject.redirect_uri = 'urn:ietf:wg:oauth:2.0:oob'
65
+ it "accepts native redirect uri" do
66
+ subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
65
67
  expect(subject).to be_valid
66
68
  end
67
69
 
68
- it 'accepts app redirect uri' do
69
- subject.redirect_uri = 'some-awesome-app://oauth/callback'
70
+ it "accepts app redirect uri" do
71
+ subject.redirect_uri = "some-awesome-app://oauth/callback"
70
72
  expect(subject).to be_valid
71
73
  end
72
74
 
73
- it 'accepts a non secured protocol when disabled' do
74
- subject.redirect_uri = 'http://example.com/callback'
75
+ it "accepts a non secured protocol when disabled" do
76
+ subject.redirect_uri = "http://example.com/callback"
75
77
  allow(Doorkeeper.configuration).to receive(
76
78
  :force_ssl_in_redirect_uri
77
79
  ).and_return(false)
78
80
  expect(subject).to be_valid
79
81
  end
80
82
 
81
- it 'accepts a non secured protocol when conditional option defined' do
83
+ it "accepts a non secured protocol when conditional option defined" do
82
84
  Doorkeeper.configure do
83
85
  orm DOORKEEPER_ORM
84
- force_ssl_in_redirect_uri { |uri| uri.host != 'localhost' }
86
+ force_ssl_in_redirect_uri { |uri| uri.host != "localhost" }
85
87
  end
86
88
 
87
- application = FactoryBot.build(:application, redirect_uri: 'http://localhost/callback')
89
+ application = FactoryBot.build(:application, redirect_uri: "http://localhost/callback")
88
90
  expect(application).to be_valid
89
91
 
90
- application = FactoryBot.build(:application, redirect_uri: 'https://test.com/callback')
92
+ application = FactoryBot.build(:application, redirect_uri: "https://test.com/callback")
91
93
  expect(application).to be_valid
92
94
 
93
- application = FactoryBot.build(:application, redirect_uri: 'http://localhost2/callback')
95
+ application = FactoryBot.build(:application, redirect_uri: "http://localhost2/callback")
94
96
  expect(application).not_to be_valid
95
97
 
96
- application = FactoryBot.build(:application, redirect_uri: 'https://test.com/callback')
98
+ application = FactoryBot.build(:application, redirect_uri: "https://test.com/callback")
97
99
  expect(application).to be_valid
98
100
  end
99
101
 
100
- it 'forbids redirect uri if required' do
101
- subject.redirect_uri = 'javascript://document.cookie'
102
+ it "forbids redirect uri if required" do
103
+ subject.redirect_uri = "javascript://document.cookie"
102
104
 
103
105
  Doorkeeper.configure do
104
106
  orm DOORKEEPER_ORM
105
- forbid_redirect_uri { |uri| uri.scheme == 'javascript' }
107
+ forbid_redirect_uri { |uri| uri.scheme == "javascript" }
106
108
  end
107
109
 
108
110
  expect(subject).to be_invalid
109
- expect(subject.errors[:redirect_uri].first).to eq('is forbidden by the server.')
111
+ expect(subject.errors[:redirect_uri].first).to eq("is forbidden by the server.")
110
112
 
111
- subject.redirect_uri = 'https://localhost/callback'
113
+ subject.redirect_uri = "https://localhost/callback"
112
114
  expect(subject).to be_valid
113
115
  end
114
116
 
115
- it 'invalidates the uri when the uri does not use a secure protocol' do
116
- subject.redirect_uri = 'http://example.com/callback'
117
+ it "invalidates the uri when the uri does not use a secure protocol" do
118
+ subject.redirect_uri = "http://example.com/callback"
117
119
  expect(subject).not_to be_valid
118
120
  error = subject.errors[:redirect_uri].first
119
- expect(error).to eq('must be an HTTPS/SSL URI.')
121
+ expect(error).to eq("must be an HTTPS/SSL URI.")
120
122
  end
121
123
  end
122
124
 
123
- context 'multiple redirect uri' do
124
- it 'invalidates the second uri when the first uri is native uri' do
125
+ context "multiple redirect uri" do
126
+ it "invalidates the second uri when the first uri is native uri" do
125
127
  subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob\nexample.com/callback"
126
128
  expect(subject).to be_invalid
127
129
  end
128
130
  end
131
+
132
+ context "blank redirect URI" do
133
+ it "forbids blank redirect uri by default" do
134
+ subject.redirect_uri = ""
135
+
136
+ expect(subject).to be_invalid
137
+ expect(subject.errors[:redirect_uri]).not_to be_blank
138
+ end
139
+
140
+ it "forbids blank redirect uri by custom condition" do
141
+ Doorkeeper.configure do
142
+ orm DOORKEEPER_ORM
143
+ allow_blank_redirect_uri do |_grant_flows, application|
144
+ application.name == "admin app"
145
+ end
146
+ end
147
+
148
+ subject.name = "test app"
149
+ subject.redirect_uri = ""
150
+
151
+ expect(subject).to be_invalid
152
+ expect(subject.errors[:redirect_uri]).not_to be_blank
153
+
154
+ subject.name = "admin app"
155
+ expect(subject).to be_valid
156
+ end
157
+ end
129
158
  end
@@ -1,14 +1,16 @@
1
- require 'spec_helper'
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
2
4
 
3
5
  describe Doorkeeper::VERSION do
4
- context '#gem_version' do
5
- it 'returns Gem::Version instance' do
6
+ context "#gem_version" do
7
+ it "returns Gem::Version instance" do
6
8
  expect(Doorkeeper.gem_version).to be_an_instance_of(Gem::Version)
7
9
  end
8
10
  end
9
11
 
10
- context 'VERSION' do
11
- it 'returns gem version string' do
12
+ context "VERSION" do
13
+ it "returns gem version string" do
12
14
  expect(Doorkeeper::VERSION::STRING).to match(/^\d+\.\d+\.\d+(\.\w+)?$/)
13
15
  end
14
16
  end