doorkeeper 4.4.3 → 5.0.3

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 (223) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +1 -0
  3. data/.gitlab-ci.yml +16 -0
  4. data/.travis.yml +7 -0
  5. data/Appraisals +2 -2
  6. data/Dangerfile +64 -0
  7. data/Gemfile +1 -1
  8. data/NEWS.md +98 -8
  9. data/README.md +110 -12
  10. data/Rakefile +6 -0
  11. data/UPGRADE.md +2 -0
  12. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  13. data/app/controllers/doorkeeper/application_controller.rb +6 -3
  14. data/app/controllers/doorkeeper/application_metal_controller.rb +6 -0
  15. data/app/controllers/doorkeeper/applications_controller.rb +46 -24
  16. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  17. data/app/controllers/doorkeeper/authorized_applications_controller.rb +21 -2
  18. data/app/controllers/doorkeeper/token_info_controller.rb +2 -0
  19. data/app/controllers/doorkeeper/tokens_controller.rb +4 -6
  20. data/app/helpers/doorkeeper/dashboard_helper.rb +9 -7
  21. data/app/validators/redirect_uri_validator.rb +5 -2
  22. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  23. data/app/views/doorkeeper/applications/_form.html.erb +25 -24
  24. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  25. data/app/views/doorkeeper/applications/index.html.erb +17 -7
  26. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  27. data/app/views/doorkeeper/applications/show.html.erb +6 -6
  28. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  29. data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
  30. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  31. data/config/locales/en.yml +10 -1
  32. data/doorkeeper.gemspec +25 -26
  33. data/gemfiles/rails_5_2.gemfile +1 -1
  34. data/gemfiles/rails_master.gemfile +4 -1
  35. data/lib/doorkeeper/config.rb +81 -40
  36. data/lib/doorkeeper/engine.rb +6 -0
  37. data/lib/doorkeeper/errors.rb +17 -3
  38. data/lib/doorkeeper/grape/authorization_decorator.rb +2 -0
  39. data/lib/doorkeeper/grape/helpers.rb +3 -1
  40. data/lib/doorkeeper/helpers/controller.rb +9 -2
  41. data/lib/doorkeeper/models/access_grant_mixin.rb +73 -0
  42. data/lib/doorkeeper/models/access_token_mixin.rb +44 -25
  43. data/lib/doorkeeper/models/application_mixin.rb +2 -0
  44. data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
  45. data/lib/doorkeeper/models/concerns/expirable.rb +2 -0
  46. data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
  47. data/lib/doorkeeper/models/concerns/ownership.rb +2 -0
  48. data/lib/doorkeeper/models/concerns/revocable.rb +2 -0
  49. data/lib/doorkeeper/models/concerns/scopes.rb +3 -1
  50. data/lib/doorkeeper/oauth/authorization/code.rb +33 -8
  51. data/lib/doorkeeper/oauth/authorization/context.rb +17 -0
  52. data/lib/doorkeeper/oauth/authorization/token.rb +38 -14
  53. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +2 -0
  54. data/lib/doorkeeper/oauth/authorization_code_request.rb +29 -2
  55. data/lib/doorkeeper/oauth/base_request.rb +22 -9
  56. data/lib/doorkeeper/oauth/base_response.rb +2 -0
  57. data/lib/doorkeeper/oauth/client/credentials.rb +3 -1
  58. data/lib/doorkeeper/oauth/client.rb +1 -1
  59. data/lib/doorkeeper/oauth/client_credentials/creator.rb +4 -1
  60. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -2
  61. data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -5
  62. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -3
  63. data/lib/doorkeeper/oauth/code_request.rb +2 -0
  64. data/lib/doorkeeper/oauth/code_response.rb +2 -0
  65. data/lib/doorkeeper/oauth/error.rb +2 -0
  66. data/lib/doorkeeper/oauth/error_response.rb +21 -3
  67. data/lib/doorkeeper/oauth/forbidden_token_response.rb +9 -2
  68. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
  69. data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -0
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +5 -2
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +18 -0
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +43 -11
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +16 -3
  75. data/lib/doorkeeper/oauth/scopes.rb +3 -1
  76. data/lib/doorkeeper/oauth/token.rb +7 -2
  77. data/lib/doorkeeper/oauth/token_introspection.rb +4 -2
  78. data/lib/doorkeeper/oauth/token_request.rb +2 -0
  79. data/lib/doorkeeper/oauth/token_response.rb +6 -2
  80. data/lib/doorkeeper/oauth.rb +13 -0
  81. data/lib/doorkeeper/orm/active_record/application.rb +75 -12
  82. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  83. data/lib/doorkeeper/orm/active_record.rb +4 -0
  84. data/lib/doorkeeper/rails/helpers.rb +6 -4
  85. data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
  86. data/lib/doorkeeper/rails/routes/mapping.rb +2 -0
  87. data/lib/doorkeeper/rails/routes.rb +23 -8
  88. data/lib/doorkeeper/rake/db.rake +40 -0
  89. data/lib/doorkeeper/rake/setup.rake +6 -0
  90. data/lib/doorkeeper/rake.rb +14 -0
  91. data/lib/doorkeeper/request/authorization_code.rb +1 -1
  92. data/lib/doorkeeper/request/client_credentials.rb +1 -1
  93. data/lib/doorkeeper/request/code.rb +1 -1
  94. data/lib/doorkeeper/request/password.rb +1 -1
  95. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  96. data/lib/doorkeeper/request/strategy.rb +2 -0
  97. data/lib/doorkeeper/request/token.rb +1 -1
  98. data/lib/doorkeeper/request.rb +29 -34
  99. data/lib/doorkeeper/server.rb +2 -0
  100. data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
  101. data/lib/doorkeeper/validations.rb +2 -0
  102. data/lib/doorkeeper/version.rb +6 -24
  103. data/lib/doorkeeper.rb +20 -17
  104. data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
  105. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  106. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  107. data/lib/generators/doorkeeper/migration_generator.rb +23 -18
  108. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  109. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
  110. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  111. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  112. data/lib/generators/doorkeeper/templates/initializer.rb +96 -13
  113. data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -3
  114. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  115. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  116. data/spec/controllers/applications_controller_spec.rb +123 -14
  117. data/spec/controllers/authorizations_controller_spec.rb +334 -51
  118. data/spec/controllers/protected_resources_controller_spec.rb +60 -18
  119. data/spec/controllers/token_info_controller_spec.rb +4 -12
  120. data/spec/controllers/tokens_controller_spec.rb +17 -20
  121. data/spec/dummy/Rakefile +1 -1
  122. data/spec/dummy/app/assets/config/manifest.js +2 -0
  123. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +1 -1
  124. data/spec/dummy/app/controllers/home_controller.rb +1 -2
  125. data/spec/dummy/config/application.rb +1 -1
  126. data/spec/dummy/config/boot.rb +2 -4
  127. data/spec/dummy/config/environment.rb +1 -1
  128. data/spec/dummy/config/environments/test.rb +5 -6
  129. data/spec/dummy/config/initializers/doorkeeper.rb +12 -6
  130. data/spec/dummy/config/initializers/new_framework_defaults.rb +2 -0
  131. data/spec/dummy/config/initializers/secret_token.rb +1 -1
  132. data/spec/dummy/config/routes.rb +3 -42
  133. data/spec/dummy/config.ru +1 -1
  134. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +4 -4
  135. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
  136. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  137. data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
  138. data/spec/dummy/db/schema.rb +36 -36
  139. data/spec/dummy/script/rails +4 -3
  140. data/spec/factories.rb +6 -6
  141. data/spec/generators/application_owner_generator_spec.rb +1 -1
  142. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  143. data/spec/generators/install_generator_spec.rb +5 -2
  144. data/spec/generators/migration_generator_spec.rb +1 -1
  145. data/spec/generators/pkce_generator_spec.rb +43 -0
  146. data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
  147. data/spec/generators/templates/routes.rb +0 -1
  148. data/spec/generators/views_generator_spec.rb +2 -2
  149. data/spec/grape/grape_integration_spec.rb +2 -2
  150. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  151. data/spec/lib/config_spec.rb +105 -39
  152. data/spec/lib/doorkeeper_spec.rb +6 -131
  153. data/spec/lib/models/expirable_spec.rb +0 -3
  154. data/spec/lib/models/revocable_spec.rb +0 -2
  155. data/spec/lib/models/scopes_spec.rb +0 -4
  156. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  157. data/spec/lib/oauth/authorization_code_request_spec.rb +17 -7
  158. data/spec/lib/oauth/base_request_spec.rb +49 -11
  159. data/spec/lib/oauth/base_response_spec.rb +1 -1
  160. data/spec/lib/oauth/client/credentials_spec.rb +2 -4
  161. data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
  162. data/spec/lib/oauth/client_credentials/issuer_spec.rb +24 -7
  163. data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
  164. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  165. data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
  166. data/spec/lib/oauth/client_spec.rb +0 -3
  167. data/spec/lib/oauth/code_request_spec.rb +5 -3
  168. data/spec/lib/oauth/code_response_spec.rb +1 -1
  169. data/spec/lib/oauth/error_response_spec.rb +0 -3
  170. data/spec/lib/oauth/error_spec.rb +0 -2
  171. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  172. data/spec/lib/oauth/helpers/scope_checker_spec.rb +8 -11
  173. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  174. data/spec/lib/oauth/helpers/uri_checker_spec.rb +22 -13
  175. data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
  176. data/spec/lib/oauth/password_access_token_request_spec.rb +53 -6
  177. data/spec/lib/oauth/pre_authorization_spec.rb +33 -4
  178. data/spec/lib/oauth/refresh_token_request_spec.rb +22 -14
  179. data/spec/lib/oauth/scopes_spec.rb +0 -3
  180. data/spec/lib/oauth/token_request_spec.rb +8 -9
  181. data/spec/lib/oauth/token_response_spec.rb +0 -1
  182. data/spec/lib/oauth/token_spec.rb +40 -14
  183. data/spec/lib/request/strategy_spec.rb +0 -1
  184. data/spec/lib/server_spec.rb +7 -7
  185. data/spec/lib/stale_records_cleaner_spec.rb +89 -0
  186. data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
  187. data/spec/models/doorkeeper/access_token_spec.rb +80 -32
  188. data/spec/models/doorkeeper/application_spec.rb +293 -221
  189. data/spec/requests/applications/applications_request_spec.rb +134 -1
  190. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  191. data/spec/requests/endpoints/authorization_spec.rb +3 -3
  192. data/spec/requests/endpoints/token_spec.rb +7 -5
  193. data/spec/requests/flows/authorization_code_errors_spec.rb +2 -2
  194. data/spec/requests/flows/authorization_code_spec.rb +258 -2
  195. data/spec/requests/flows/client_credentials_spec.rb +46 -6
  196. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  197. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  198. data/spec/requests/flows/password_spec.rb +61 -3
  199. data/spec/requests/flows/refresh_token_spec.rb +59 -2
  200. data/spec/requests/flows/revoke_token_spec.rb +20 -20
  201. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  202. data/spec/requests/protected_resources/metal_spec.rb +1 -1
  203. data/spec/requests/protected_resources/private_api_spec.rb +3 -3
  204. data/spec/routing/custom_controller_routes_spec.rb +59 -7
  205. data/spec/routing/default_routes_spec.rb +2 -2
  206. data/spec/routing/scoped_routes_spec.rb +16 -2
  207. data/spec/spec_helper.rb +54 -3
  208. data/spec/spec_helper_integration.rb +2 -74
  209. data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
  210. data/spec/support/doorkeeper_rspec.rb +20 -0
  211. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  212. data/spec/support/helpers/model_helper.rb +8 -4
  213. data/spec/support/helpers/request_spec_helper.rb +10 -2
  214. data/spec/support/helpers/url_helper.rb +18 -14
  215. data/spec/support/http_method_shim.rb +12 -16
  216. data/spec/support/shared/controllers_shared_context.rb +56 -0
  217. data/spec/validators/redirect_uri_validator_spec.rb +9 -3
  218. data/spec/version/version_spec.rb +3 -3
  219. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  220. metadata +54 -35
  221. data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
  222. data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
  223. data/spec/controllers/application_metal_controller.rb +0 -10
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper::OAuth
4
4
  describe RefreshTokenRequest do
@@ -9,7 +9,7 @@ module Doorkeeper::OAuth
9
9
  let(:server) do
10
10
  double :server,
11
11
  access_token_expires_in: 2.minutes,
12
- custom_access_token_expires_in: -> (_oauth_client) { nil }
12
+ custom_access_token_expires_in: ->(_context) { nil }
13
13
  end
14
14
 
15
15
  let(:refresh_token) do
@@ -24,20 +24,22 @@ module Doorkeeper::OAuth
24
24
  it 'issues a new token for the client' do
25
25
  expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
26
26
  # #sort_by used for MongoDB ORM extensions for valid ordering
27
- expect(client.reload.access_tokens.sort_by(&:created_at).last.expires_in).to eq(120)
27
+ expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(120)
28
28
  end
29
29
 
30
30
  it 'issues a new token for the client with custom expires_in' do
31
31
  server = double :server,
32
32
  access_token_expires_in: 2.minutes,
33
- custom_access_token_expires_in: ->(_oauth_client) { 1234 }
33
+ custom_access_token_expires_in: lambda { |context|
34
+ context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
35
+ }
34
36
 
35
37
  allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
36
38
 
37
39
  RefreshTokenRequest.new(server, refresh_token, credentials).authorize
38
40
 
39
41
  # #sort_by used for MongoDB ORM extensions for valid ordering
40
- expect(client.reload.access_tokens.sort_by(&:created_at).last.expires_in).to eq(1234)
42
+ expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
41
43
  end
42
44
 
43
45
  it 'revokes the previous token' do
@@ -45,8 +47,12 @@ module Doorkeeper::OAuth
45
47
  end
46
48
 
47
49
  it "calls configured request callback methods" do
48
- expect(Doorkeeper.configuration.before_successful_strategy_response).to receive(:call).with(subject).once
49
- expect(Doorkeeper.configuration.after_successful_strategy_response).to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
50
+ expect(Doorkeeper.configuration.before_successful_strategy_response)
51
+ .to receive(:call).with(subject).once
52
+
53
+ expect(Doorkeeper.configuration.after_successful_strategy_response)
54
+ .to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
55
+
50
56
  subject.authorize
51
57
  end
52
58
 
@@ -85,7 +91,9 @@ module Doorkeeper::OAuth
85
91
  let(:server) do
86
92
  double :server,
87
93
  access_token_expires_in: 2.minutes,
88
- custom_access_token_expires_in: ->(_oauth_client) { 1234 }
94
+ custom_access_token_expires_in: lambda { |context|
95
+ context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
96
+ }
89
97
  end
90
98
 
91
99
  before do
@@ -105,7 +113,7 @@ module Doorkeeper::OAuth
105
113
  subject.authorize
106
114
  expect(
107
115
  # #sort_by used for MongoDB ORM extensions for valid ordering
108
- client.access_tokens.sort_by(&:created_at).last.previous_refresh_token
116
+ client.access_tokens.max_by(&:created_at).previous_refresh_token
109
117
  ).to eq(refresh_token.refresh_token)
110
118
  end
111
119
  end
@@ -123,21 +131,21 @@ module Doorkeeper::OAuth
123
131
  context 'with scopes' do
124
132
  let(:refresh_token) do
125
133
  FactoryBot.create :access_token,
126
- use_refresh_token: true,
127
- scopes: 'public write'
134
+ use_refresh_token: true,
135
+ scopes: 'public write'
128
136
  end
129
137
  let(:parameters) { {} }
130
138
  subject { RefreshTokenRequest.new server, refresh_token, credentials, parameters }
131
139
 
132
140
  it 'transfers scopes from the old token to the new token' do
133
141
  subject.authorize
134
- expect(Doorkeeper::AccessToken.last.scopes).to eq([:public, :write])
142
+ expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public write])
135
143
  end
136
144
 
137
145
  it 'reduces scopes to the provided scopes' do
138
146
  parameters[:scopes] = 'public'
139
147
  subject.authorize
140
- expect(Doorkeeper::AccessToken.last.scopes).to eq([:public])
148
+ expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
141
149
  end
142
150
 
143
151
  it 'validates that scopes are included in the original access token' do
@@ -151,7 +159,7 @@ module Doorkeeper::OAuth
151
159
  parameters[:scopes] = 'public update'
152
160
  parameters[:scope] = 'public'
153
161
  subject.authorize
154
- expect(Doorkeeper::AccessToken.last.scopes).to eq([:public])
162
+ expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
155
163
  end
156
164
 
157
165
  it 'uses params[:scope] in favor of scopes if present (invalid)' do
@@ -1,7 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/core_ext/module/delegation'
3
- require 'active_support/core_ext/string'
4
- require 'doorkeeper/oauth/scopes'
5
2
 
6
3
  module Doorkeeper::OAuth
7
4
  describe Scopes do
@@ -1,10 +1,9 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper::OAuth
4
4
  describe TokenRequest do
5
5
  let :application do
6
- scopes = double(all: ['public'])
7
- double(:application, id: 9990, scopes: scopes)
6
+ FactoryBot.create(:application, scopes: 'public')
8
7
  end
9
8
 
10
9
  let :pre_auth do
@@ -39,7 +38,7 @@ module Doorkeeper::OAuth
39
38
 
40
39
  it 'does not create token when not authorizable' do
41
40
  allow(pre_auth).to receive(:authorizable?).and_return(false)
42
- expect { subject.authorize }.not_to change { Doorkeeper::AccessToken.count }
41
+ expect { subject.authorize }.not_to(change { Doorkeeper::AccessToken.count })
43
42
  end
44
43
 
45
44
  it 'returns a error response' do
@@ -51,8 +50,8 @@ module Doorkeeper::OAuth
51
50
  before do
52
51
  Doorkeeper.configure do
53
52
  orm DOORKEEPER_ORM
54
- custom_access_token_expires_in do |_oauth_client|
55
- 1234
53
+ custom_access_token_expires_in do |context|
54
+ context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
56
55
  end
57
56
  end
58
57
  end
@@ -75,7 +74,7 @@ module Doorkeeper::OAuth
75
74
  it 'creates a new token if scopes do not match' do
76
75
  allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
77
76
  FactoryBot.create(:access_token, application_id: pre_auth.client.id,
78
- resource_owner_id: owner.id, scopes: '')
77
+ resource_owner_id: owner.id, scopes: '')
79
78
  expect do
80
79
  subject.authorize
81
80
  end.to change { Doorkeeper::AccessToken.count }.by(1)
@@ -87,9 +86,9 @@ module Doorkeeper::OAuth
87
86
  allow(application.scopes).to receive(:all?).and_return(true)
88
87
 
89
88
  FactoryBot.create(:access_token, application_id: pre_auth.client.id,
90
- resource_owner_id: owner.id, scopes: 'public')
89
+ resource_owner_id: owner.id, scopes: 'public')
91
90
 
92
- expect { subject.authorize }.not_to change { Doorkeeper::AccessToken.count }
91
+ expect { subject.authorize }.not_to(change { Doorkeeper::AccessToken.count })
93
92
  end
94
93
  end
95
94
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'doorkeeper/oauth/token_response'
3
2
 
4
3
  module Doorkeeper::OAuth
5
4
  describe TokenResponse do
@@ -1,6 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'active_support/core_ext/string'
3
- require 'doorkeeper/oauth/token'
4
2
 
5
3
  module Doorkeeper
6
4
  unless defined?(AccessToken)
@@ -14,7 +12,7 @@ module Doorkeeper
14
12
  let(:request) { double.as_null_object }
15
13
 
16
14
  let(:method) do
17
- ->(request) { return 'token-value' }
15
+ ->(*) { 'token-value' }
18
16
  end
19
17
 
20
18
  it 'accepts anything that responds to #call' do
@@ -96,19 +94,47 @@ module Doorkeeper
96
94
  end
97
95
 
98
96
  describe :authenticate do
99
- it 'calls the finder if token was returned' do
100
- token = ->(_r) { 'token' }
101
- expect(AccessToken).to receive(:by_token).with('token')
102
- Token.authenticate double, token
97
+ context 'refresh tokens are disabled (default)' do
98
+ context 'refresh tokens are enabled' do
99
+ it 'does not revoke previous refresh_token if token was found' do
100
+ token = ->(_r) { 'token' }
101
+ expect(
102
+ AccessToken
103
+ ).to receive(:by_token).with('token').and_return(token)
104
+ expect(token).not_to receive(:revoke_previous_refresh_token!)
105
+ Token.authenticate double, token
106
+ end
107
+ end
108
+
109
+ it 'calls the finder if token was returned' do
110
+ token = ->(_r) { 'token' }
111
+ expect(AccessToken).to receive(:by_token).with('token')
112
+ Token.authenticate double, token
113
+ end
103
114
  end
104
115
 
105
- it 'revokes previous refresh_token if token was found' do
106
- token = ->(_r) { 'token' }
107
- expect(
108
- AccessToken
109
- ).to receive(:by_token).with('token').and_return(token)
110
- expect(token).to receive(:revoke_previous_refresh_token!)
111
- Token.authenticate double, token
116
+ context 'refresh tokens are enabled' do
117
+ before do
118
+ Doorkeeper.configure do
119
+ orm DOORKEEPER_ORM
120
+ use_refresh_token
121
+ end
122
+ end
123
+
124
+ it 'revokes previous refresh_token if token was found' do
125
+ token = ->(_r) { 'token' }
126
+ expect(
127
+ AccessToken
128
+ ).to receive(:by_token).with('token').and_return(token)
129
+ expect(token).to receive(:revoke_previous_refresh_token!)
130
+ Token.authenticate double, token
131
+ end
132
+
133
+ it 'calls the finder if token was returned' do
134
+ token = ->(_r) { 'token' }
135
+ expect(AccessToken).to receive(:by_token).with('token')
136
+ Token.authenticate double, token
137
+ end
112
138
  end
113
139
  end
114
140
  end
@@ -1,5 +1,4 @@
1
1
  require 'spec_helper'
2
- require 'doorkeeper/request/strategy'
3
2
 
4
3
  module Doorkeeper
5
4
  module Request
@@ -22,9 +22,9 @@ describe Doorkeeper::Server do
22
22
 
23
23
  context 'when only Authorization Code strategy is enabled' do
24
24
  before do
25
- allow(Doorkeeper.configuration).
26
- to receive(:grant_flows).
27
- and_return(['authorization_code'])
25
+ allow(Doorkeeper.configuration)
26
+ .to receive(:grant_flows)
27
+ .and_return(['authorization_code'])
28
28
  end
29
29
 
30
30
  it 'raises error when using the disabled Implicit strategy' do
@@ -46,10 +46,10 @@ describe Doorkeeper::Server do
46
46
  subject.authorization_request :code
47
47
  end
48
48
 
49
- it 'builds the request with composit strategy name' do
50
- allow(Doorkeeper.configuration).
51
- to receive(:authorization_response_types).
52
- and_return(['id_token token'])
49
+ it 'builds the request with composite strategy name' do
50
+ allow(Doorkeeper.configuration)
51
+ .to receive(:authorization_response_types)
52
+ .and_return(['id_token token'])
53
53
 
54
54
  stub_const 'Doorkeeper::Request::IdTokenToken', fake_class
55
55
  expect(fake_class).to receive(:new).with(subject)
@@ -0,0 +1,89 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Doorkeeper::StaleRecordsCleaner do
6
+ let(:cleaner) { described_class.new(model) }
7
+ let(:models_by_name) do
8
+ {
9
+ access_token: Doorkeeper::AccessToken,
10
+ access_grant: Doorkeeper::AccessGrant
11
+ }
12
+ end
13
+
14
+ context 'when ORM has no cleaner class' do
15
+ it 'raises an error' do
16
+ allow_any_instance_of(Doorkeeper::Config).to receive(:orm).and_return('hibernate')
17
+
18
+ expect do
19
+ described_class.for(Doorkeeper::AccessToken)
20
+ end.to raise_error(Doorkeeper::Errors::NoOrmCleaner, /has no cleaner/)
21
+ end
22
+ end
23
+
24
+ %i[access_token access_grant].each do |model_name|
25
+ context "(#{model_name})" do
26
+ let(:model) { models_by_name.fetch(model_name) }
27
+
28
+ describe '#clean_revoked' do
29
+ subject { cleaner.clean_revoked }
30
+
31
+ context 'with revoked record' do
32
+ before do
33
+ FactoryBot.create model_name, revoked_at: Time.current - 1.minute
34
+ end
35
+
36
+ it 'removes the record' do
37
+ expect { subject }.to change { model.count }.to(0)
38
+ end
39
+ end
40
+
41
+ context 'with record revoked in the future' do
42
+ before do
43
+ FactoryBot.create model_name, revoked_at: Time.current + 1.minute
44
+ end
45
+
46
+ it 'keeps the record' do
47
+ expect { subject }.not_to(change { model.count })
48
+ end
49
+ end
50
+
51
+ context 'with unrevoked record' do
52
+ before do
53
+ FactoryBot.create model_name, revoked_at: nil
54
+ end
55
+
56
+ it 'keeps the record' do
57
+ expect { subject }.not_to(change { model.count })
58
+ end
59
+ end
60
+ end
61
+
62
+ describe '#clean_expired' do
63
+ subject { cleaner.clean_expired(ttl) }
64
+ let(:ttl) { 500 }
65
+ let(:expiry_border) { ttl.seconds.ago }
66
+
67
+ context 'with record that is expired' do
68
+ before do
69
+ FactoryBot.create model_name, created_at: expiry_border - 1.minute
70
+ end
71
+
72
+ it 'removes the record' do
73
+ expect { subject }.to change { model.count }.to(0)
74
+ end
75
+ end
76
+
77
+ context 'with record that is not expired' do
78
+ before do
79
+ FactoryBot.create model_name, created_at: expiry_border + 1.minute
80
+ end
81
+
82
+ it 'keeps the record' do
83
+ expect { subject }.not_to(change { model.count })
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Doorkeeper::AccessGrant do
4
4
  subject { FactoryBot.build(:access_grant) }
@@ -33,4 +33,47 @@ describe Doorkeeper::AccessGrant do
33
33
  expect(subject).not_to be_valid
34
34
  end
35
35
  end
36
+
37
+ describe '.revoke_all_for' do
38
+ let(:resource_owner) { double(id: 100) }
39
+ let(:application) { FactoryBot.create :application }
40
+ let(:default_attributes) do
41
+ {
42
+ application: application,
43
+ resource_owner_id: resource_owner.id
44
+ }
45
+ end
46
+
47
+ it 'revokes all tokens for given application and resource owner' do
48
+ FactoryBot.create :access_grant, default_attributes
49
+
50
+ described_class.revoke_all_for(application.id, resource_owner)
51
+
52
+ described_class.all.each do |token|
53
+ expect(token).to be_revoked
54
+ end
55
+ end
56
+
57
+ it 'matches application' do
58
+ access_grant_for_different_app = FactoryBot.create(
59
+ :access_grant,
60
+ default_attributes.merge(application: FactoryBot.create(:application))
61
+ )
62
+
63
+ described_class.revoke_all_for(application.id, resource_owner)
64
+
65
+ expect(access_grant_for_different_app.reload).not_to be_revoked
66
+ end
67
+
68
+ it 'matches resource owner' do
69
+ access_grant_for_different_owner = FactoryBot.create(
70
+ :access_grant,
71
+ default_attributes.merge(resource_owner_id: 90)
72
+ )
73
+
74
+ described_class.revoke_all_for application.id, resource_owner
75
+
76
+ expect(access_grant_for_different_owner.reload).not_to be_revoked
77
+ end
78
+ end
36
79
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module Doorkeeper
4
4
  describe AccessToken do
@@ -13,8 +13,7 @@ module Doorkeeper
13
13
  end
14
14
 
15
15
  module CustomGeneratorArgs
16
- def self.generate
17
- end
16
+ def self.generate; end
18
17
  end
19
18
 
20
19
  describe :generate_token do
@@ -42,7 +41,7 @@ module Doorkeeper
42
41
  end
43
42
 
44
43
  token = FactoryBot.create :access_token
45
- expect(token.token).to match(%r{custom_generator_token_\d+})
44
+ expect(token.token).to match(/custom_generator_token_\d+/)
46
45
  end
47
46
 
48
47
  it 'allows the custom generator to access the application details' do
@@ -62,7 +61,7 @@ module Doorkeeper
62
61
  end
63
62
 
64
63
  token = FactoryBot.create :access_token
65
- expect(token.token).to match(%r{custom_generator_token_Application \d+})
64
+ expect(token.token).to match(/custom_generator_token_Application \d+/)
66
65
  end
67
66
 
68
67
  it 'allows the custom generator to access the scopes' do
@@ -144,7 +143,7 @@ module Doorkeeper
144
143
  end
145
144
 
146
145
  module CustomGeneratorArgs
147
- def self.generate(opts = {})
146
+ def self.generate(_opts = {})
148
147
  raise LoadError, 'custom behaviour'
149
148
  end
150
149
  end
@@ -214,11 +213,9 @@ module Doorkeeper
214
213
  end
215
214
 
216
215
  describe '#same_credential?' do
217
-
218
216
  context 'with default parameters' do
219
-
220
217
  let(:resource_owner_id) { 100 }
221
- let(:application) { FactoryBot.create :application }
218
+ let(:application) { FactoryBot.create :application }
222
219
  let(:default_attributes) do
223
220
  { application: application, resource_owner_id: resource_owner_id }
224
221
  end
@@ -233,7 +230,11 @@ module Doorkeeper
233
230
 
234
231
  context 'the second token has same owner and different app' do
235
232
  let(:other_application) { FactoryBot.create :application }
236
- let(:access_token2) { FactoryBot.create :access_token, application: other_application, resource_owner_id: resource_owner_id }
233
+ let(:access_token2) do
234
+ FactoryBot.create :access_token,
235
+ application: other_application,
236
+ resource_owner_id: resource_owner_id
237
+ end
237
238
 
238
239
  it 'fail' do
239
240
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -241,9 +242,10 @@ module Doorkeeper
241
242
  end
242
243
 
243
244
  context 'the second token has different owner and different app' do
244
-
245
245
  let(:other_application) { FactoryBot.create :application }
246
- let(:access_token2) { FactoryBot.create :access_token, application: other_application, resource_owner_id: 42 }
246
+ let(:access_token2) do
247
+ FactoryBot.create :access_token, application: other_application, resource_owner_id: 42
248
+ end
247
249
 
248
250
  it 'fail' do
249
251
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -251,7 +253,9 @@ module Doorkeeper
251
253
  end
252
254
 
253
255
  context 'the second token has different owner and same app' do
254
- let(:access_token2) { FactoryBot.create :access_token, application: application, resource_owner_id: 42 }
256
+ let(:access_token2) do
257
+ FactoryBot.create :access_token, application: application, resource_owner_id: 42
258
+ end
255
259
 
256
260
  it 'fail' do
257
261
  expect(access_token1.same_credential?(access_token2)).to be_falsey
@@ -306,15 +310,25 @@ module Doorkeeper
306
310
  end
307
311
 
308
312
  it 'matches application' do
309
- FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
313
+ access_token_for_different_app = FactoryBot.create(
314
+ :access_token,
315
+ default_attributes.merge(application: FactoryBot.create(:application))
316
+ )
317
+
310
318
  AccessToken.revoke_all_for application.id, resource_owner
311
- expect(AccessToken.all).not_to be_empty
319
+
320
+ expect(access_token_for_different_app.reload).not_to be_revoked
312
321
  end
313
322
 
314
323
  it 'matches resource owner' do
315
- FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 90)
324
+ access_token_for_different_owner = FactoryBot.create(
325
+ :access_token,
326
+ default_attributes.merge(resource_owner_id: 90)
327
+ )
328
+
316
329
  AccessToken.revoke_all_for application.id, resource_owner
317
- expect(AccessToken.all).not_to be_empty
330
+
331
+ expect(access_token_for_different_owner.reload).not_to be_revoked
318
332
  end
319
333
  end
320
334
 
@@ -330,6 +344,10 @@ module Doorkeeper
330
344
  }
331
345
  end
332
346
 
347
+ before do
348
+ default_scopes_exist(*scopes.all)
349
+ end
350
+
333
351
  it 'returns only one token' do
334
352
  token = FactoryBot.create :access_token, default_attributes
335
353
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
@@ -355,37 +373,45 @@ module Doorkeeper
355
373
  expect(last_token).to be_nil
356
374
  end
357
375
 
358
- it 'matches the application' do
376
+ it "excludes tokens with a different application" do
359
377
  FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
360
378
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
361
379
  expect(last_token).to be_nil
362
380
  end
363
381
 
364
- it 'matches the resource owner' do
382
+ it "excludes tokens with a different resource owner" do
365
383
  FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
366
384
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
367
385
  expect(last_token).to be_nil
368
386
  end
369
387
 
370
- it 'matches token with fewer scopes' do
388
+ it "excludes tokens with fewer scopes" do
371
389
  FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
372
390
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
373
391
  expect(last_token).to be_nil
374
392
  end
375
393
 
376
- it 'matches token with different scopes' do
394
+ it 'excludes tokens with different scopes' do
377
395
  FactoryBot.create :access_token, default_attributes.merge(scopes: 'public email')
378
396
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
379
397
  expect(last_token).to be_nil
380
398
  end
381
399
 
382
- it 'matches token with more scopes' do
400
+ it 'excludes tokens with additional scopes' do
383
401
  FactoryBot.create :access_token, default_attributes.merge(scopes: 'public write email')
384
402
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
385
403
  expect(last_token).to be_nil
386
404
  end
387
405
 
388
- it 'matches application scopes' do
406
+ it 'excludes tokens with scopes that are not present in server scopes' do
407
+ FactoryBot.create :access_token, default_attributes.merge(
408
+ application: application, scopes: 'public read'
409
+ )
410
+ last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
411
+ expect(last_token).to be_nil
412
+ end
413
+
414
+ it 'excludes tokens with scopes that are not present in application scopes' do
389
415
  application = FactoryBot.create :application, scopes: "private read"
390
416
  FactoryBot.create :access_token, default_attributes.merge(
391
417
  application: application
@@ -394,25 +420,47 @@ module Doorkeeper
394
420
  expect(last_token).to be_nil
395
421
  end
396
422
 
397
- it 'returns the last created token' do
423
+ it 'does not match token if empty scope requested and token/app scopes present' do
424
+ application = FactoryBot.create :application, scopes: "sample:scope"
425
+ app_params = {
426
+ application_id: application.id, scopes: "sample:scope",
427
+ resource_owner_id: 100
428
+ }
429
+ FactoryBot.create :access_token, app_params
430
+ empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
431
+ last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
432
+ expect(last_token).to be_nil
433
+ end
434
+
435
+ it 'matches token if empty scope requested and no token scopes present' do
436
+ empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
437
+ token = FactoryBot.create :access_token, default_attributes.merge(scopes: empty_scopes)
438
+ last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
439
+ expect(last_token).to eq(token)
440
+ end
441
+
442
+ it 'returns the last matching token' do
398
443
  FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
399
- token = FactoryBot.create :access_token, default_attributes
444
+ matching_token = FactoryBot.create :access_token, default_attributes
445
+ FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
446
+
400
447
  last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
401
- expect(last_token).to eq(token)
448
+ expect(last_token).to eq(matching_token)
402
449
  end
450
+ end
403
451
 
404
- it 'returns as_json hash' do
405
- token = FactoryBot.create :access_token, default_attributes
452
+ describe "#as_json" do
453
+ it "returns as_json hash" do
454
+ token = FactoryBot.create :access_token
406
455
  token_hash = {
407
456
  resource_owner_id: token.resource_owner_id,
408
- scopes: token.scopes,
409
- expires_in_seconds: token.expires_in_seconds,
457
+ scope: token.scopes,
458
+ expires_in: token.expires_in_seconds,
410
459
  application: { uid: token.application.uid },
411
- created_at: token.created_at.to_i,
460
+ created_at: token.created_at.to_i
412
461
  }
413
462
  expect(token.as_json).to eq token_hash
414
463
  end
415
464
  end
416
-
417
465
  end
418
466
  end