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
  describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
4
4
  include AuthorizationRequestHelper
@@ -6,7 +6,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
6
6
  if Rails::VERSION::MAJOR >= 5
7
7
  class ActionDispatch::TestResponse
8
8
  def query_params
9
- @_query_params ||= begin
9
+ @query_params ||= begin
10
10
  fragment = URI.parse(location).fragment
11
11
  Rack::Utils.parse_query(fragment)
12
12
  end
@@ -15,7 +15,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
15
15
  else
16
16
  class ActionController::TestResponse
17
17
  def query_params
18
- @_query_params ||= begin
18
+ @query_params ||= begin
19
19
  fragment = URI.parse(location).fragment
20
20
  Rack::Utils.parse_query(fragment)
21
21
  end
@@ -34,11 +34,14 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
34
34
  before do
35
35
  allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["implicit"])
36
36
  allow(controller).to receive(:current_resource_owner).and_return(user)
37
+ allow(Doorkeeper.configuration).to receive(:custom_access_token_expires_in).and_return(proc { |context|
38
+ context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
39
+ })
37
40
  end
38
41
 
39
42
  describe 'POST #create' do
40
43
  before do
41
- post :create, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
44
+ post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
42
45
  end
43
46
 
44
47
  it 'redirects after authorization' do
@@ -46,7 +49,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
46
49
  end
47
50
 
48
51
  it 'redirects to client redirect uri' do
49
- expect(response.location).to match(%r{^#{client.redirect_uri}})
52
+ expect(response.location).to match(/^#{client.redirect_uri}/)
50
53
  end
51
54
 
52
55
  it 'includes access token in fragment' do
@@ -58,7 +61,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
58
61
  end
59
62
 
60
63
  it 'includes token expiration in fragment' do
61
- expect(response.query_params['expires_in'].to_i).to eq(2.hours.to_i)
64
+ expect(response.query_params['expires_in'].to_i).to eq(1234)
62
65
  end
63
66
 
64
67
  it 'issues the token for the current client' do
@@ -70,10 +73,54 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
70
73
  end
71
74
  end
72
75
 
76
+ describe "POST #create in API mode" do
77
+ before do
78
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
79
+ post :create, params: { client_id: client.uid, response_type: "token", redirect_uri: client.redirect_uri }
80
+ end
81
+
82
+ let(:response_json_body) { JSON.parse(response.body) }
83
+ let(:redirect_uri) { response_json_body["redirect_uri"] }
84
+
85
+ it "renders success after authorization" do
86
+ expect(response).to be_successful
87
+ end
88
+
89
+ it "renders correct redirect uri" do
90
+ expect(redirect_uri).to match(/^#{client.redirect_uri}/)
91
+ end
92
+
93
+ it "includes access token in fragment" do
94
+ expect(redirect_uri.match(/access_token=([a-f0-9]+)&?/)[1]).to eq(Doorkeeper::AccessToken.first.token)
95
+ end
96
+
97
+ it "includes token type in fragment" do
98
+ expect(redirect_uri.match(/token_type=(\w+)&?/)[1]).to eq "Bearer"
99
+ end
100
+
101
+ it "includes token expiration in fragment" do
102
+ expect(redirect_uri.match(/expires_in=(\d+)&?/)[1].to_i).to eq 1234
103
+ end
104
+
105
+ it "issues the token for the current client" do
106
+ expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
107
+ end
108
+
109
+ it "issues the token for the current resource owner" do
110
+ expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
111
+ end
112
+ end
113
+
73
114
  describe 'POST #create with errors' do
74
115
  before do
75
116
  default_scopes_exist :public
76
- post :create, client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri
117
+
118
+ post :create, params: {
119
+ client_id: client.uid,
120
+ response_type: 'token',
121
+ scope: 'invalid',
122
+ redirect_uri: client.redirect_uri
123
+ }
77
124
  end
78
125
 
79
126
  it 'redirects after authorization' do
@@ -81,7 +128,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
81
128
  end
82
129
 
83
130
  it 'redirects to client redirect uri' do
84
- expect(response.location).to match(%r{^#{client.redirect_uri}})
131
+ expect(response.location).to match(/^#{client.redirect_uri}/)
85
132
  end
86
133
 
87
134
  it 'does not include access token in fragment' do
@@ -101,12 +148,58 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
101
148
  end
102
149
  end
103
150
 
151
+ describe 'POST #create in API mode with errors' do
152
+ before do
153
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
154
+ default_scopes_exist :public
155
+
156
+ post :create, params: {
157
+ client_id: client.uid,
158
+ response_type: 'token',
159
+ scope: 'invalid',
160
+ redirect_uri: client.redirect_uri
161
+ }
162
+ end
163
+
164
+ let(:response_json_body) { JSON.parse(response.body) }
165
+ let(:redirect_uri) { response_json_body['redirect_uri'] }
166
+
167
+ it 'renders 400 error' do
168
+ expect(response.status).to eq 401
169
+ end
170
+
171
+ it 'includes correct redirect URI' do
172
+ expect(redirect_uri).to match(/^#{client.redirect_uri}/)
173
+ end
174
+
175
+ it 'does not include access token in fragment' do
176
+ expect(redirect_uri.match(/access_token=([a-f0-9]+)&?/)).to be_nil
177
+ end
178
+
179
+ it 'includes error in redirect uri' do
180
+ expect(redirect_uri.match(/error=([a-z_]+)&?/)[1]).to eq 'invalid_scope'
181
+ end
182
+
183
+ it 'includes error description in redirect uri' do
184
+ expect(redirect_uri.match(/error_description=(.+)&?/)[1]).to_not be_nil
185
+ end
186
+
187
+ it 'does not issue any access token' do
188
+ expect(Doorkeeper::AccessToken.all).to be_empty
189
+ end
190
+ end
191
+
104
192
  describe 'POST #create with application already authorized' do
105
193
  before do
106
194
  allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
107
195
 
108
196
  access_token.save!
109
- post :create, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
197
+
198
+ post :create, params: {
199
+ client_id: client.uid,
200
+ response_type: 'token',
201
+ redirect_uri: client.redirect_uri
202
+ }
110
203
  end
111
204
 
112
205
  it 'returns the existing access token in a fragment' do
@@ -118,18 +211,64 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
118
211
  end
119
212
  end
120
213
 
214
+ describe 'POST #create with callbacks' do
215
+ after do
216
+ client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
217
+ end
218
+
219
+ describe 'when successful' do
220
+ after do
221
+ post :create, params: {
222
+ client_id: client.uid,
223
+ response_type: 'token',
224
+ redirect_uri: client.redirect_uri
225
+ }
226
+ end
227
+
228
+ it 'should call :before_successful_authorization callback' do
229
+ expect(Doorkeeper.configuration)
230
+ .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
231
+ end
232
+
233
+ it 'should call :after_successful_authorization callback' do
234
+ expect(Doorkeeper.configuration)
235
+ .to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
236
+ end
237
+ end
238
+
239
+ describe 'with errors' do
240
+ after do
241
+ post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: 'bad_uri' }
242
+ end
243
+
244
+ it 'should not call :before_successful_authorization callback' do
245
+ expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
246
+ end
247
+
248
+ it 'should not call :after_successful_authorization callback' do
249
+ expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
250
+ end
251
+ end
252
+ end
253
+
121
254
  describe 'GET #new token request with native url and skip_authorization true' do
122
255
  before do
123
256
  allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
124
257
  true
125
258
  end)
259
+
126
260
  client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
127
- get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
261
+
262
+ get :new, params: {
263
+ client_id: client.uid,
264
+ response_type: 'token',
265
+ redirect_uri: client.redirect_uri
266
+ }
128
267
  end
129
268
 
130
269
  it 'should redirect immediately' do
131
270
  expect(response).to be_redirect
132
- expect(response.location).to match(/oauth\/token\/info\?access_token=/)
271
+ expect(response.location).to match(%r{/oauth/token/info\?access_token=})
133
272
  end
134
273
 
135
274
  it 'should not issue a grant' do
@@ -143,18 +282,24 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
143
282
 
144
283
  describe 'GET #new code request with native url and skip_authorization true' do
145
284
  before do
146
- allow(Doorkeeper.configuration).to receive(:grant_flows).
147
- and_return(%w[authorization_code])
285
+ allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(%w[authorization_code])
148
286
  allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
149
287
  true
150
288
  end)
289
+
151
290
  client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
152
- get :new, client_id: client.uid, response_type: 'code', redirect_uri: client.redirect_uri
291
+
292
+ get :new, params: {
293
+ client_id: client.uid,
294
+ response_type: 'code',
295
+ redirect_uri: client.redirect_uri
296
+ }
153
297
  end
154
298
 
155
299
  it 'should redirect immediately' do
156
300
  expect(response).to be_redirect
157
- expect(response.location).to match(/oauth\/authorize\/native\?code=#{Doorkeeper::AccessGrant.first.token}/)
301
+ expect(response.location)
302
+ .to match(%r{/oauth/authorize/native\?code=#{Doorkeeper::AccessGrant.first.token}})
158
303
  end
159
304
 
160
305
  it 'should issue a grant' do
@@ -164,38 +309,6 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
164
309
  it 'should not issue a token' do
165
310
  expect(Doorkeeper::AccessToken.count).to be 0
166
311
  end
167
-
168
- context 'with opt_out_native_route_change' do
169
- around(:each) do |example|
170
- Doorkeeper.configure do
171
- orm DOORKEEPER_ORM
172
- opt_out_native_route_change
173
- end
174
-
175
- Rails.application.reload_routes!
176
-
177
- example.run
178
-
179
- Doorkeeper.configure do
180
- orm DOORKEEPER_ORM
181
- end
182
-
183
- Rails.application.reload_routes!
184
- end
185
-
186
- it 'should redirect immediately' do
187
- expect(response).to be_redirect
188
- expect(response.location).to match(/oauth\/authorize\/#{Doorkeeper::AccessGrant.first.token}/)
189
- end
190
-
191
- it 'should issue a grant' do
192
- expect(Doorkeeper::AccessGrant.count).to be 1
193
- end
194
-
195
- it 'should not issue a token' do
196
- expect(Doorkeeper::AccessToken.count).to be 0
197
- end
198
- end
199
312
  end
200
313
 
201
314
  describe 'GET #new with skip_authorization true' do
@@ -203,12 +316,17 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
203
316
  allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
204
317
  true
205
318
  end)
206
- get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
319
+
320
+ get :new, params: {
321
+ client_id: client.uid,
322
+ response_type: 'token',
323
+ redirect_uri: client.redirect_uri
324
+ }
207
325
  end
208
326
 
209
327
  it 'should redirect immediately' do
210
328
  expect(response).to be_redirect
211
- expect(response.location).to match(%r{^#{client.redirect_uri}})
329
+ expect(response.location).to match(/^#{client.redirect_uri}/)
212
330
  end
213
331
 
214
332
  it 'should issue a token' do
@@ -220,7 +338,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
220
338
  end
221
339
 
222
340
  it 'includes token expiration in fragment' do
223
- expect(response.query_params['expires_in'].to_i).to eq(2.hours.to_i)
341
+ expect(response.query_params['expires_in'].to_i).to eq(1234)
224
342
  end
225
343
 
226
344
  it 'issues the token for the current client' do
@@ -232,10 +350,81 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
232
350
  end
233
351
  end
234
352
 
353
+ describe 'GET #new in API mode' do
354
+ before do
355
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
356
+
357
+ get :new, params: {
358
+ client_id: client.uid,
359
+ response_type: 'token',
360
+ redirect_uri: client.redirect_uri
361
+ }
362
+ end
363
+
364
+ it 'should render success' do
365
+ expect(response).to be_successful
366
+ end
367
+
368
+ it "sets status to pre-authorization" do
369
+ expect(json_response["status"]).to eq(I18n.t('doorkeeper.pre_authorization.status'))
370
+ end
371
+
372
+ it "sets correct values" do
373
+ expect(json_response['client_id']).to eq(client.uid)
374
+ expect(json_response['redirect_uri']).to eq(client.redirect_uri)
375
+ expect(json_response['state']).to be_nil
376
+ expect(json_response['response_type']).to eq('token')
377
+ expect(json_response['scope']).to eq('')
378
+ end
379
+ end
380
+
381
+ describe 'GET #new in API mode with skip_authorization true' do
382
+ before do
383
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { true })
384
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
385
+
386
+ get :new, params: {
387
+ client_id: client.uid,
388
+ response_type: 'token',
389
+ redirect_uri: client.redirect_uri
390
+ }
391
+ end
392
+
393
+ it 'should render success' do
394
+ expect(response).to be_successful
395
+ end
396
+
397
+ it 'should issue a token' do
398
+ expect(Doorkeeper::AccessToken.count).to be 1
399
+ end
400
+
401
+ it "sets status to redirect" do
402
+ expect(JSON.parse(response.body)["status"]).to eq("redirect")
403
+ end
404
+
405
+ it "sets redirect_uri to correct value" do
406
+ redirect_uri = JSON.parse(response.body)["redirect_uri"]
407
+ expect(redirect_uri).to_not be_nil
408
+ expect(redirect_uri.match(/token_type=(\w+)&?/)[1]).to eq "Bearer"
409
+ expect(redirect_uri.match(/expires_in=(\d+)&?/)[1].to_i).to eq 1234
410
+ expect(
411
+ redirect_uri.match(/access_token=([a-f0-9]+)&?/)[1]
412
+ ).to eq Doorkeeper::AccessToken.first.token
413
+ end
414
+
415
+ it "issues the token for the current client" do
416
+ expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
417
+ end
418
+
419
+ it "issues the token for the current resource owner" do
420
+ expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
421
+ end
422
+ end
423
+
235
424
  describe 'GET #new with errors' do
236
425
  before do
237
426
  default_scopes_exist :public
238
- get :new, an_invalid: 'request'
427
+ get :new, params: { an_invalid: 'request' }
239
428
  end
240
429
 
241
430
  it 'does not redirect' do
@@ -247,4 +436,98 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
247
436
  expect(Doorkeeper::AccessToken.count).to eq 0
248
437
  end
249
438
  end
439
+
440
+ describe 'GET #new in API mode with errors' do
441
+ let(:response_json_body) { JSON.parse(response.body) }
442
+
443
+ before do
444
+ default_scopes_exist :public
445
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
446
+ get :new, params: { an_invalid: 'request' }
447
+ end
448
+
449
+ it 'should render bad request' do
450
+ expect(response).to have_http_status(:bad_request)
451
+ end
452
+
453
+ it 'includes error in body' do
454
+ expect(response_json_body['error']).to eq('unsupported_response_type')
455
+ end
456
+
457
+ it 'includes error description in body' do
458
+ expect(response_json_body['error_description'])
459
+ .to eq(translated_error_message(:unsupported_response_type))
460
+ end
461
+
462
+ it 'does not issue any token' do
463
+ expect(Doorkeeper::AccessGrant.count).to eq 0
464
+ expect(Doorkeeper::AccessToken.count).to eq 0
465
+ end
466
+ end
467
+
468
+ describe 'GET #new with callbacks' do
469
+ after do
470
+ client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
471
+ get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
472
+ end
473
+
474
+ describe 'when authorizing' do
475
+ before do
476
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { true })
477
+ end
478
+
479
+ it 'should call :before_successful_authorization callback' do
480
+ expect(Doorkeeper.configuration)
481
+ .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
482
+ end
483
+
484
+ it 'should call :after_successful_authorization callback' do
485
+ expect(Doorkeeper.configuration)
486
+ .to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
487
+ end
488
+ end
489
+
490
+ describe 'when not authorizing' do
491
+ before do
492
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { false })
493
+ end
494
+
495
+ it 'should not call :before_successful_authorization callback' do
496
+ expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
497
+ end
498
+
499
+ it 'should not call :after_successful_authorization callback' do
500
+ expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
501
+ end
502
+ end
503
+
504
+ describe 'when not authorizing in api mode' do
505
+ before do
506
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { false })
507
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
508
+ end
509
+
510
+ it 'should not call :before_successful_authorization callback' do
511
+ expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
512
+ end
513
+
514
+ it 'should not call :after_successful_authorization callback' do
515
+ expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
516
+ end
517
+ end
518
+ end
519
+
520
+ describe 'authorize response memoization' do
521
+ it 'memoizes the result of the authorization' do
522
+ strategy = double(:strategy, authorize: true)
523
+ expect(strategy).to receive(:authorize).once
524
+ allow(controller).to receive(:strategy) { strategy }
525
+ allow(controller).to receive(:create) do
526
+ 2.times { controller.send :authorize_response }
527
+ controller.render json: {}, status: :ok
528
+ end
529
+
530
+ post :create
531
+ end
532
+ end
250
533
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module ControllerActions
4
4
  def index
@@ -33,12 +33,12 @@ describe 'doorkeeper authorize filter' do
33
33
 
34
34
  it 'access_token param' do
35
35
  expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
36
- get :index, access_token: token_string
36
+ get :index, params: { access_token: token_string }
37
37
  end
38
38
 
39
39
  it 'bearer_token param' do
40
40
  expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
41
- get :index, bearer_token: token_string
41
+ get :index, params: { bearer_token: token_string }
42
42
  end
43
43
 
44
44
  it 'Authorization header' do
@@ -57,7 +57,7 @@ describe 'doorkeeper authorize filter' do
57
57
  expect(Doorkeeper::AccessToken).to receive(:by_token).exactly(2).times.and_return(token)
58
58
  request.env['HTTP_AUTHORIZATION'] = "Bearer #{token_string}"
59
59
  get :index
60
- controller.send(:remove_instance_variable, :@_doorkeeper_token)
60
+ controller.send(:remove_instance_variable, :@doorkeeper_token)
61
61
  get :index
62
62
  end
63
63
  end
@@ -71,25 +71,25 @@ describe 'doorkeeper authorize filter' do
71
71
 
72
72
  context 'with valid token', token: :valid do
73
73
  it 'allows into index action' do
74
- get :index, access_token: token_string
74
+ get :index, params: { access_token: token_string }
75
75
  expect(response).to be_successful
76
76
  end
77
77
 
78
78
  it 'allows into show action' do
79
- get :show, id: '4', access_token: token_string
79
+ get :show, params: { id: '4', access_token: token_string }
80
80
  expect(response).to be_successful
81
81
  end
82
82
  end
83
83
 
84
84
  context 'with invalid token', token: :invalid do
85
85
  it 'does not allow into index action' do
86
- get :index, access_token: token_string
86
+ get :index, params: { access_token: token_string }
87
87
  expect(response.status).to eq 401
88
88
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
89
89
  end
90
90
 
91
91
  it 'does not allow into show action' do
92
- get :show, id: '4', access_token: token_string
92
+ get :show, params: { id: '4', access_token: token_string }
93
93
  expect(response.status).to eq 401
94
94
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
95
95
  end
@@ -115,7 +115,7 @@ describe 'doorkeeper authorize filter' do
115
115
  Doorkeeper::AccessToken
116
116
  ).to receive(:by_token).with(token_string).and_return(token)
117
117
 
118
- get :index, access_token: token_string
118
+ get :index, params: { access_token: token_string }
119
119
  expect(response).to be_successful
120
120
  end
121
121
 
@@ -129,7 +129,7 @@ describe 'doorkeeper authorize filter' do
129
129
  ).to receive(:by_token).with(token_string).and_return(token)
130
130
  expect(token).to receive(:acceptable?).with([:write]).and_return(false)
131
131
 
132
- get :index, access_token: token_string
132
+ get :index, params: { access_token: token_string }
133
133
  expect(response.status).to eq 403
134
134
  expect(response.header).to_not include('WWW-Authenticate')
135
135
  end
@@ -157,13 +157,12 @@ describe 'doorkeeper authorize filter' do
157
157
  module ControllerActions
158
158
  remove_method :doorkeeper_unauthorized_render_options
159
159
 
160
- def doorkeeper_unauthorized_render_options(error: nil)
161
- end
160
+ def doorkeeper_unauthorized_render_options(error: nil); end
162
161
  end
163
162
  end
164
163
 
165
164
  it 'it renders a custom JSON response', token: :invalid do
166
- get :index, access_token: token_string
165
+ get :index, params: { access_token: token_string }
167
166
  expect(response.status).to eq 401
168
167
  expect(response.content_type).to eq('application/json')
169
168
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
@@ -193,7 +192,7 @@ describe 'doorkeeper authorize filter' do
193
192
  end
194
193
 
195
194
  it 'it renders a custom text response', token: :invalid do
196
- get :index, access_token: token_string
195
+ get :index, params: { access_token: token_string }
197
196
  expect(response.status).to eq 401
198
197
  expect(response.content_type).to eq('text/plain')
199
198
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
@@ -243,7 +242,7 @@ describe 'doorkeeper authorize filter' do
243
242
  end
244
243
 
245
244
  it 'renders a custom JSON response' do
246
- get :index, access_token: token_string
245
+ get :index, params: { access_token: token_string }
247
246
  expect(response.header).to_not include('WWW-Authenticate')
248
247
  expect(response.content_type).to eq('application/json')
249
248
  expect(response.status).to eq 403
@@ -265,7 +264,7 @@ describe 'doorkeeper authorize filter' do
265
264
  end
266
265
 
267
266
  it 'overrides the default status code' do
268
- get :index, access_token: token_string
267
+ get :index, params: { access_token: token_string }
269
268
  expect(response.status).to eq 404
270
269
  end
271
270
  end
@@ -282,7 +281,7 @@ describe 'doorkeeper authorize filter' do
282
281
  end
283
282
 
284
283
  it 'renders a custom status code and text response' do
285
- get :index, access_token: token_string
284
+ get :index, params: { access_token: token_string }
286
285
  expect(response.header).to_not include('WWW-Authenticate')
287
286
  expect(response.status).to eq 403
288
287
  expect(response.body).to eq('Forbidden')
@@ -301,9 +300,52 @@ describe 'doorkeeper authorize filter' do
301
300
  end
302
301
 
303
302
  it 'overrides the default status code' do
304
- get :index, access_token: token_string
303
+ get :index, params: { access_token: token_string }
305
304
  expect(response.status).to eq 404
306
305
  end
307
306
  end
308
307
  end
308
+
309
+ context 'when handle_auth_errors option is set to :raise' do
310
+ subject { get :index, params: { access_token: token_string } }
311
+
312
+ before do
313
+ config_is_set(:handle_auth_errors, :raise)
314
+ end
315
+
316
+ controller do
317
+ before_action :doorkeeper_authorize!
318
+ include ControllerActions
319
+ end
320
+
321
+ context 'when token is unknown' do
322
+ it 'raises Doorkeeper::Errors::TokenUnknown exception', token: :invalid do
323
+ expect { subject }.to raise_error(Doorkeeper::Errors::TokenUnknown)
324
+ end
325
+ end
326
+
327
+ context 'when token is expired' do
328
+ it 'raises Doorkeeper::Errors::TokenExpired exception', token: :expired do
329
+ expect { subject }.to raise_error(Doorkeeper::Errors::TokenExpired)
330
+ end
331
+ end
332
+
333
+ context 'when token is revoked' do
334
+ it 'raises Doorkeeper::Errors::TokenRevoked exception', token: :revoked do
335
+ expect { subject }.to raise_error(Doorkeeper::Errors::TokenRevoked)
336
+ end
337
+ end
338
+
339
+ context 'when token is forbidden' do
340
+ it 'raises Doorkeeper::Errors::TokenForbidden exception', token: :forbidden do
341
+ expect { subject }.to raise_error(Doorkeeper::Errors::TokenForbidden)
342
+ end
343
+ end
344
+
345
+ context 'when token is valid' do
346
+ it 'allows into index action', token: :valid do
347
+ expect(response).to be_successful
348
+ end
349
+ end
350
+ end
309
351
  end