doorkeeper 4.2.6 → 5.0.0.rc1

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 (205) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +25 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  4. data/.gitignore +2 -1
  5. data/.hound.yml +2 -13
  6. data/.rubocop.yml +17 -0
  7. data/.travis.yml +19 -5
  8. data/Appraisals +8 -4
  9. data/CODE_OF_CONDUCT.md +46 -0
  10. data/Gemfile +1 -1
  11. data/NEWS.md +77 -0
  12. data/README.md +169 -34
  13. data/Rakefile +6 -0
  14. data/SECURITY.md +15 -0
  15. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  16. data/app/controllers/doorkeeper/application_controller.rb +2 -5
  17. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  18. data/app/controllers/doorkeeper/applications_controller.rb +47 -13
  19. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  20. data/app/controllers/doorkeeper/authorized_applications_controller.rb +15 -1
  21. data/app/controllers/doorkeeper/tokens_controller.rb +15 -7
  22. data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
  23. data/app/validators/redirect_uri_validator.rb +13 -2
  24. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  25. data/app/views/doorkeeper/applications/_form.html.erb +31 -19
  26. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  27. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  28. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  29. data/app/views/doorkeeper/applications/show.html.erb +8 -5
  30. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  31. data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
  32. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  33. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  34. data/config/locales/en.yml +18 -6
  35. data/doorkeeper.gemspec +6 -5
  36. data/gemfiles/rails_4_2.gemfile +6 -4
  37. data/gemfiles/rails_5_0.gemfile +4 -4
  38. data/gemfiles/rails_5_1.gemfile +6 -7
  39. data/gemfiles/rails_5_2.gemfile +12 -0
  40. data/gemfiles/rails_master.gemfile +14 -0
  41. data/lib/doorkeeper/config.rb +107 -68
  42. data/lib/doorkeeper/engine.rb +7 -3
  43. data/lib/doorkeeper/errors.rb +2 -5
  44. data/lib/doorkeeper/grape/helpers.rb +14 -9
  45. data/lib/doorkeeper/helpers/controller.rb +15 -6
  46. data/lib/doorkeeper/models/access_grant_mixin.rb +52 -23
  47. data/lib/doorkeeper/models/access_token_mixin.rb +51 -52
  48. data/lib/doorkeeper/models/application_mixin.rb +16 -30
  49. data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
  50. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  51. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  52. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  53. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  54. data/lib/doorkeeper/oauth/authorization/token.rb +41 -20
  55. data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
  56. data/lib/doorkeeper/oauth/base_request.rb +22 -7
  57. data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
  58. data/lib/doorkeeper/oauth/client.rb +2 -2
  59. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -1
  60. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -2
  61. data/lib/doorkeeper/oauth/error.rb +2 -2
  62. data/lib/doorkeeper/oauth/error_response.rb +11 -4
  63. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  64. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  65. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
  66. data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
  67. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
  68. data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
  69. data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
  70. data/lib/doorkeeper/oauth/scopes.rb +19 -9
  71. data/lib/doorkeeper/oauth/token.rb +6 -3
  72. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  73. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  74. data/lib/doorkeeper/oauth.rb +13 -0
  75. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  76. data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
  77. data/lib/doorkeeper/orm/active_record/application.rb +34 -0
  78. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  79. data/lib/doorkeeper/orm/active_record.rb +21 -8
  80. data/lib/doorkeeper/rails/helpers.rb +7 -10
  81. data/lib/doorkeeper/rails/routes.rb +21 -7
  82. data/lib/doorkeeper/rake/db.rake +40 -0
  83. data/lib/doorkeeper/rake/setup.rake +6 -0
  84. data/lib/doorkeeper/rake.rb +14 -0
  85. data/lib/doorkeeper/request/password.rb +1 -11
  86. data/lib/doorkeeper/request.rb +29 -23
  87. data/lib/doorkeeper/validations.rb +3 -2
  88. data/lib/doorkeeper/version.rb +14 -1
  89. data/lib/doorkeeper.rb +6 -17
  90. data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
  91. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  92. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  93. data/lib/generators/doorkeeper/migration_generator.rb +26 -9
  94. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  95. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
  96. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  97. data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
  98. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
  99. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  100. data/lib/generators/doorkeeper/templates/initializer.rb +88 -10
  101. data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
  102. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  103. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  104. data/spec/controllers/applications_controller_spec.rb +141 -17
  105. data/spec/controllers/authorizations_controller_spec.rb +255 -20
  106. data/spec/controllers/protected_resources_controller_spec.rb +44 -35
  107. data/spec/controllers/token_info_controller_spec.rb +17 -21
  108. data/spec/controllers/tokens_controller_spec.rb +142 -10
  109. data/spec/dummy/app/assets/config/manifest.js +2 -0
  110. data/spec/dummy/config/environments/test.rb +4 -5
  111. data/spec/dummy/config/initializers/doorkeeper.rb +18 -1
  112. data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
  113. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  114. data/spec/dummy/config/routes.rb +3 -42
  115. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  116. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  117. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
  118. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
  119. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
  120. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  121. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
  122. data/spec/dummy/db/schema.rb +38 -37
  123. data/spec/factories.rb +1 -1
  124. data/spec/generators/application_owner_generator_spec.rb +25 -6
  125. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  126. data/spec/generators/install_generator_spec.rb +1 -1
  127. data/spec/generators/migration_generator_spec.rb +25 -4
  128. data/spec/generators/pkce_generator_spec.rb +43 -0
  129. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  130. data/spec/generators/views_generator_spec.rb +1 -1
  131. data/spec/grape/grape_integration_spec.rb +135 -0
  132. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
  133. data/spec/lib/config_spec.rb +170 -22
  134. data/spec/lib/doorkeeper_spec.rb +1 -126
  135. data/spec/lib/models/expirable_spec.rb +0 -3
  136. data/spec/lib/models/revocable_spec.rb +2 -4
  137. data/spec/lib/models/scopes_spec.rb +0 -4
  138. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  139. data/spec/lib/oauth/authorization_code_request_spec.rb +63 -13
  140. data/spec/lib/oauth/base_request_spec.rb +19 -10
  141. data/spec/lib/oauth/base_response_spec.rb +1 -1
  142. data/spec/lib/oauth/client/credentials_spec.rb +5 -5
  143. data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
  144. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  145. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  146. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  147. data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
  148. data/spec/lib/oauth/client_spec.rb +0 -3
  149. data/spec/lib/oauth/code_request_spec.rb +5 -5
  150. data/spec/lib/oauth/error_response_spec.rb +0 -3
  151. data/spec/lib/oauth/error_spec.rb +1 -3
  152. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  153. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  154. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  155. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
  156. data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
  157. data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
  158. data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
  159. data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
  160. data/spec/lib/oauth/scopes_spec.rb +28 -4
  161. data/spec/lib/oauth/token_request_spec.rb +10 -13
  162. data/spec/lib/oauth/token_response_spec.rb +0 -1
  163. data/spec/lib/oauth/token_spec.rb +37 -14
  164. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  165. data/spec/lib/request/strategy_spec.rb +0 -1
  166. data/spec/lib/server_spec.rb +10 -0
  167. data/spec/models/doorkeeper/access_grant_spec.rb +2 -2
  168. data/spec/models/doorkeeper/access_token_spec.rb +118 -60
  169. data/spec/models/doorkeeper/application_spec.rb +101 -23
  170. data/spec/requests/applications/applications_request_spec.rb +94 -6
  171. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  172. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  173. data/spec/requests/endpoints/token_spec.rb +15 -6
  174. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
  175. data/spec/requests/flows/authorization_code_spec.rb +198 -1
  176. data/spec/requests/flows/client_credentials_spec.rb +73 -5
  177. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  178. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  179. data/spec/requests/flows/password_spec.rb +160 -24
  180. data/spec/requests/flows/refresh_token_spec.rb +6 -6
  181. data/spec/requests/flows/revoke_token_spec.rb +26 -26
  182. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  183. data/spec/requests/protected_resources/metal_spec.rb +2 -2
  184. data/spec/requests/protected_resources/private_api_spec.rb +2 -2
  185. data/spec/routing/custom_controller_routes_spec.rb +63 -7
  186. data/spec/routing/default_routes_spec.rb +6 -2
  187. data/spec/routing/scoped_routes_spec.rb +16 -2
  188. data/spec/spec_helper.rb +54 -3
  189. data/spec/spec_helper_integration.rb +2 -63
  190. data/spec/support/dependencies/factory_bot.rb +2 -0
  191. data/spec/support/doorkeeper_rspec.rb +19 -0
  192. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  193. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  194. data/spec/support/helpers/model_helper.rb +9 -4
  195. data/spec/support/helpers/request_spec_helper.rb +10 -6
  196. data/spec/support/helpers/url_helper.rb +15 -10
  197. data/spec/support/http_method_shim.rb +12 -16
  198. data/spec/support/shared/controllers_shared_context.rb +2 -6
  199. data/spec/support/shared/models_shared_examples.rb +4 -4
  200. data/spec/validators/redirect_uri_validator_spec.rb +58 -7
  201. data/spec/version/version_spec.rb +15 -0
  202. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  203. metadata +73 -19
  204. data/spec/controllers/application_metal_controller.rb +0 -10
  205. data/spec/support/dependencies/factory_girl.rb +0 -2
@@ -1,12 +1,12 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
4
4
  include AuthorizationRequestHelper
5
5
 
6
- if Rails::VERSION::MAJOR == 5
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
@@ -24,21 +24,24 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
24
24
  end
25
25
 
26
26
  def translated_error_message(key)
27
- I18n.translate key, scope: [:doorkeeper, :errors, :messages]
27
+ I18n.translate key, scope: %i[doorkeeper errors messages]
28
28
  end
29
29
 
30
- let(:client) { FactoryGirl.create :application }
30
+ let(:client) { FactoryBot.create :application }
31
31
  let(:user) { User.create!(name: 'Joe', password: 'sekret') }
32
- let(:access_token) { FactoryGirl.build :access_token, resource_owner_id: user.id, application_id: client.id }
32
+ let(:access_token) { FactoryBot.build :access_token, resource_owner_id: user.id, application_id: client.id }
33
33
 
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
@@ -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,48 @@ 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
+ post :create, params: { client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri }
77
118
  end
78
119
 
79
120
  it 'redirects after authorization' do
@@ -81,7 +122,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
81
122
  end
82
123
 
83
124
  it 'redirects to client redirect uri' do
84
- expect(response.location).to match(%r{^#{client.redirect_uri}})
125
+ expect(response.location).to match(/^#{client.redirect_uri}/)
85
126
  end
86
127
 
87
128
  it 'does not include access token in fragment' do
@@ -101,12 +142,47 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
101
142
  end
102
143
  end
103
144
 
145
+ describe 'POST #create in API mode with errors' do
146
+ before do
147
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
148
+ default_scopes_exist :public
149
+ post :create, params: { client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri }
150
+ end
151
+
152
+ let(:response_json_body) { JSON.parse(response.body) }
153
+ let(:redirect_uri) { response_json_body['redirect_uri'] }
154
+
155
+ it 'renders 400 error' do
156
+ expect(response.status).to eq 401
157
+ end
158
+
159
+ it 'includes correct redirect URI' do
160
+ expect(redirect_uri).to match(/^#{client.redirect_uri}/)
161
+ end
162
+
163
+ it 'does not include access token in fragment' do
164
+ expect(redirect_uri.match(/access_token=([a-f0-9]+)&?/)).to be_nil
165
+ end
166
+
167
+ it 'includes error in redirect uri' do
168
+ expect(redirect_uri.match(/error=([a-z_]+)&?/)[1]).to eq 'invalid_scope'
169
+ end
170
+
171
+ it 'includes error description in redirect uri' do
172
+ expect(redirect_uri.match(/error_description=(.+)&?/)[1]).to_not be_nil
173
+ end
174
+
175
+ it 'does not issue any access token' do
176
+ expect(Doorkeeper::AccessToken.all).to be_empty
177
+ end
178
+ end
179
+
104
180
  describe 'POST #create with application already authorized' do
105
181
  before do
106
182
  allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
107
183
 
108
184
  access_token.save!
109
- post :create, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
185
+ post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
110
186
  end
111
187
 
112
188
  it 'returns the existing access token in a fragment' do
@@ -118,13 +194,47 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
118
194
  end
119
195
  end
120
196
 
197
+ describe 'POST #create with callbacks' do
198
+ after do
199
+ client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
200
+ end
201
+
202
+ describe 'when successful' do
203
+ after do
204
+ post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
205
+ end
206
+
207
+ it 'should call :before_successful_authorization callback' do
208
+ expect(Doorkeeper.configuration).to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
209
+ end
210
+
211
+ it 'should call :after_successful_authorization callback' do
212
+ expect(Doorkeeper.configuration).to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
213
+ end
214
+ end
215
+
216
+ describe 'with errors' do
217
+ after do
218
+ post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: 'bad_uri' }
219
+ end
220
+
221
+ it 'should not call :before_successful_authorization callback' do
222
+ expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
223
+ end
224
+
225
+ it 'should not call :after_successful_authorization callback' do
226
+ expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
227
+ end
228
+ end
229
+ end
230
+
121
231
  describe 'GET #new token request with native url and skip_authorization true' do
122
232
  before do
123
233
  allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
124
234
  true
125
235
  end)
126
236
  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
237
+ get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
128
238
  end
129
239
 
130
240
  it 'should redirect immediately' do
@@ -143,18 +253,17 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
143
253
 
144
254
  describe 'GET #new code request with native url and skip_authorization true' do
145
255
  before do
146
- allow(Doorkeeper.configuration).to receive(:grant_flows).
147
- and_return(%w(authorization_code))
256
+ allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(%w[authorization_code])
148
257
  allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
149
258
  true
150
259
  end)
151
260
  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
261
+ get :new, params: { client_id: client.uid, response_type: 'code', redirect_uri: client.redirect_uri }
153
262
  end
154
263
 
155
264
  it 'should redirect immediately' do
156
265
  expect(response).to be_redirect
157
- expect(response.location).to match(/oauth\/authorize\//)
266
+ expect(response.location).to match(/oauth\/authorize\/native\?code=#{Doorkeeper::AccessGrant.first.token}/)
158
267
  end
159
268
 
160
269
  it 'should issue a grant' do
@@ -171,7 +280,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
171
280
  allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
172
281
  true
173
282
  end)
174
- get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
283
+ get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
175
284
  end
176
285
 
177
286
  it 'should redirect immediately' do
@@ -188,7 +297,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
188
297
  end
189
298
 
190
299
  it 'includes token expiration in fragment' do
191
- expect(response.query_params['expires_in'].to_i).to eq(2.hours.to_i)
300
+ expect(response.query_params['expires_in'].to_i).to eq(1234)
192
301
  end
193
302
 
194
303
  it 'issues the token for the current client' do
@@ -200,10 +309,72 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
200
309
  end
201
310
  end
202
311
 
312
+ describe 'GET #new in API mode' do
313
+ before do
314
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
315
+ get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
316
+ end
317
+
318
+ it 'should render success' do
319
+ expect(response).to be_successful
320
+ end
321
+
322
+ it "sets status to pre-authorization" do
323
+ expect(json_response["status"]).to eq(I18n.t('doorkeeper.pre_authorization.status'))
324
+ end
325
+
326
+ it "sets correct values" do
327
+ expect(json_response['client_id']).to eq(client.uid)
328
+ expect(json_response['redirect_uri']).to eq(client.redirect_uri)
329
+ expect(json_response['state']).to be_nil
330
+ expect(json_response['response_type']).to eq('token')
331
+ expect(json_response['scope']).to eq('')
332
+ end
333
+ end
334
+
335
+ describe 'GET #new in API mode with skip_authorization true' do
336
+ before do
337
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { true })
338
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
339
+
340
+ get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
341
+ end
342
+
343
+ it 'should render success' do
344
+ expect(response).to be_successful
345
+ end
346
+
347
+ it 'should issue a token' do
348
+ expect(Doorkeeper::AccessToken.count).to be 1
349
+ end
350
+
351
+ it "sets status to redirect" do
352
+ expect(JSON.parse(response.body)["status"]).to eq("redirect")
353
+ end
354
+
355
+ it "sets redirect_uri to correct value" do
356
+ redirect_uri = JSON.parse(response.body)["redirect_uri"]
357
+ expect(redirect_uri).to_not be_nil
358
+ expect(redirect_uri.match(/token_type=(\w+)&?/)[1]).to eq "bearer"
359
+ expect(redirect_uri.match(/expires_in=(\d+)&?/)[1].to_i).to eq 1234
360
+ expect(
361
+ redirect_uri.match(/access_token=([a-f0-9]+)&?/)[1]
362
+ ).to eq Doorkeeper::AccessToken.first.token
363
+ end
364
+
365
+ it "issues the token for the current client" do
366
+ expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
367
+ end
368
+
369
+ it "issues the token for the current resource owner" do
370
+ expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
371
+ end
372
+ end
373
+
203
374
  describe 'GET #new with errors' do
204
375
  before do
205
376
  default_scopes_exist :public
206
- get :new, an_invalid: 'request'
377
+ get :new, params: { an_invalid: 'request' }
207
378
  end
208
379
 
209
380
  it 'does not redirect' do
@@ -215,4 +386,68 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
215
386
  expect(Doorkeeper::AccessToken.count).to eq 0
216
387
  end
217
388
  end
389
+
390
+ describe 'GET #new with callbacks' do
391
+ after do
392
+ client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
393
+ get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
394
+ end
395
+
396
+ describe 'when authorizing' do
397
+ before do
398
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { true })
399
+ end
400
+
401
+ it 'should call :before_successful_authorization callback' do
402
+ expect(Doorkeeper.configuration).to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
403
+ end
404
+
405
+ it 'should call :after_successful_authorization callback' do
406
+ expect(Doorkeeper.configuration).to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
407
+ end
408
+ end
409
+
410
+ describe 'when not authorizing' do
411
+ before do
412
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { false })
413
+ end
414
+
415
+ it 'should not call :before_successful_authorization callback' do
416
+ expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
417
+ end
418
+
419
+ it 'should not call :after_successful_authorization callback' do
420
+ expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
421
+ end
422
+ end
423
+
424
+ describe 'when not authorizing in api mode' do
425
+ before do
426
+ allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { false })
427
+ allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
428
+ end
429
+
430
+ it 'should not call :before_successful_authorization callback' do
431
+ expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
432
+ end
433
+
434
+ it 'should not call :after_successful_authorization callback' do
435
+ expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
436
+ end
437
+ end
438
+ end
439
+
440
+ describe 'authorize response memoization' do
441
+ it 'memoizes the result of the authorization' do
442
+ strategy = double(:strategy, authorize: true)
443
+ expect(strategy).to receive(:authorize).once
444
+ allow(controller).to receive(:strategy) { strategy }
445
+ allow(controller).to receive(:create) do
446
+ 2.times { controller.send :authorize_response }
447
+ controller.render json: {}, status: :ok
448
+ end
449
+
450
+ post :create
451
+ end
452
+ end
218
453
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  module ControllerActions
4
4
  def index
@@ -9,11 +9,9 @@ module ControllerActions
9
9
  render plain: 'show'
10
10
  end
11
11
 
12
- def doorkeeper_unauthorized_render_options(*)
13
- end
12
+ def doorkeeper_unauthorized_render_options(*); end
14
13
 
15
- def doorkeeper_forbidden_render_options(*)
16
- end
14
+ def doorkeeper_forbidden_render_options(*); end
17
15
  end
18
16
 
19
17
  describe 'doorkeeper authorize filter' do
@@ -35,12 +33,12 @@ describe 'doorkeeper authorize filter' do
35
33
 
36
34
  it 'access_token param' do
37
35
  expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
38
- get :index, access_token: token_string
36
+ get :index, params: { access_token: token_string }
39
37
  end
40
38
 
41
39
  it 'bearer_token param' do
42
40
  expect(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
43
- get :index, bearer_token: token_string
41
+ get :index, params: { bearer_token: token_string }
44
42
  end
45
43
 
46
44
  it 'Authorization header' do
@@ -59,7 +57,7 @@ describe 'doorkeeper authorize filter' do
59
57
  expect(Doorkeeper::AccessToken).to receive(:by_token).exactly(2).times.and_return(token)
60
58
  request.env['HTTP_AUTHORIZATION'] = "Bearer #{token_string}"
61
59
  get :index
62
- controller.send(:remove_instance_variable, :@_doorkeeper_token)
60
+ controller.send(:remove_instance_variable, :@doorkeeper_token)
63
61
  get :index
64
62
  end
65
63
  end
@@ -73,25 +71,25 @@ describe 'doorkeeper authorize filter' do
73
71
 
74
72
  context 'with valid token', token: :valid do
75
73
  it 'allows into index action' do
76
- get :index, access_token: token_string
77
- expect(response).to be_success
74
+ get :index, params: { access_token: token_string }
75
+ expect(response).to be_successful
78
76
  end
79
77
 
80
78
  it 'allows into show action' do
81
- get :show, id: '4', access_token: token_string
82
- expect(response).to be_success
79
+ get :show, params: { id: '4', access_token: token_string }
80
+ expect(response).to be_successful
83
81
  end
84
82
  end
85
83
 
86
84
  context 'with invalid token', token: :invalid do
87
85
  it 'does not allow into index action' do
88
- get :index, access_token: token_string
86
+ get :index, params: { access_token: token_string }
89
87
  expect(response.status).to eq 401
90
88
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
91
89
  end
92
90
 
93
91
  it 'does not allow into show action' do
94
- get :show, id: '4', access_token: token_string
92
+ get :show, params: { id: '4', access_token: token_string }
95
93
  expect(response.status).to eq 401
96
94
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
97
95
  end
@@ -109,15 +107,16 @@ describe 'doorkeeper authorize filter' do
109
107
 
110
108
  it 'allows if the token has particular scopes' do
111
109
  token = double(Doorkeeper::AccessToken,
112
- accessible?: true, scopes: %w(write public),
110
+ accessible?: true, scopes: %w[write public],
113
111
  previous_refresh_token: "",
114
112
  revoke_previous_refresh_token!: true)
115
113
  expect(token).to receive(:acceptable?).with([:write]).and_return(true)
116
114
  expect(
117
115
  Doorkeeper::AccessToken
118
116
  ).to receive(:by_token).with(token_string).and_return(token)
119
- get :index, access_token: token_string
120
- expect(response).to be_success
117
+
118
+ get :index, params: { access_token: token_string }
119
+ expect(response).to be_successful
121
120
  end
122
121
 
123
122
  it 'does not allow if the token does not include given scope' do
@@ -129,7 +128,8 @@ describe 'doorkeeper authorize filter' do
129
128
  Doorkeeper::AccessToken
130
129
  ).to receive(:by_token).with(token_string).and_return(token)
131
130
  expect(token).to receive(:acceptable?).with([:write]).and_return(false)
132
- get :index, access_token: token_string
131
+
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
@@ -146,27 +146,30 @@ describe 'doorkeeper authorize filter' do
146
146
  before do
147
147
  module ControllerActions
148
148
  remove_method :doorkeeper_unauthorized_render_options
149
+
149
150
  def doorkeeper_unauthorized_render_options(error: nil)
150
151
  { json: ActiveSupport::JSON.encode(error_message: error.description) }
151
152
  end
152
153
  end
153
154
  end
155
+
154
156
  after do
155
157
  module ControllerActions
156
158
  remove_method :doorkeeper_unauthorized_render_options
159
+
157
160
  def doorkeeper_unauthorized_render_options(error: nil)
158
161
  end
159
162
  end
160
163
  end
161
164
 
162
165
  it 'it renders a custom JSON response', token: :invalid do
163
- get :index, access_token: token_string
166
+ get :index, params: { access_token: token_string }
164
167
  expect(response.status).to eq 401
165
168
  expect(response.content_type).to eq('application/json')
166
169
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
167
- parsed_body = JSON.parse(response.body)
168
- expect(parsed_body).not_to be_nil
169
- expect(parsed_body['error_message']).to match('token is invalid')
170
+
171
+ expect(json_response).not_to be_nil
172
+ expect(json_response['error_message']).to match('token is invalid')
170
173
  end
171
174
  end
172
175
 
@@ -174,21 +177,23 @@ describe 'doorkeeper authorize filter' do
174
177
  before do
175
178
  module ControllerActions
176
179
  remove_method :doorkeeper_unauthorized_render_options
177
- def doorkeeper_unauthorized_render_options(error: nil)
180
+
181
+ def doorkeeper_unauthorized_render_options(**)
178
182
  { plain: 'Unauthorized' }
179
183
  end
180
184
  end
181
185
  end
186
+
182
187
  after do
183
188
  module ControllerActions
184
189
  remove_method :doorkeeper_unauthorized_render_options
185
- def doorkeeper_unauthorized_render_options(error: nil)
186
- end
190
+
191
+ def doorkeeper_unauthorized_render_options(error: nil); end
187
192
  end
188
193
  end
189
194
 
190
195
  it 'it renders a custom text response', token: :invalid do
191
- get :index, access_token: token_string
196
+ get :index, params: { access_token: token_string }
192
197
  expect(response.status).to eq 401
193
198
  expect(response.content_type).to eq('text/plain')
194
199
  expect(response.header['WWW-Authenticate']).to match(/^Bearer/)
@@ -206,8 +211,8 @@ describe 'doorkeeper authorize filter' do
206
211
  after do
207
212
  module ControllerActions
208
213
  remove_method :doorkeeper_forbidden_render_options
209
- def doorkeeper_forbidden_render_options(*)
210
- end
214
+
215
+ def doorkeeper_forbidden_render_options(*); end
211
216
  end
212
217
  end
213
218
 
@@ -223,12 +228,14 @@ describe 'doorkeeper authorize filter' do
223
228
  expired?: false, previous_refresh_token: "",
224
229
  revoke_previous_refresh_token!: true)
225
230
  end
231
+
226
232
  let(:token_string) { '1A2DUWE' }
227
233
 
228
234
  context 'with a JSON custom render' do
229
235
  before do
230
236
  module ControllerActions
231
237
  remove_method :doorkeeper_forbidden_render_options
238
+
232
239
  def doorkeeper_forbidden_render_options(*)
233
240
  { json: { error_message: 'Forbidden' } }
234
241
  end
@@ -236,13 +243,13 @@ describe 'doorkeeper authorize filter' do
236
243
  end
237
244
 
238
245
  it 'renders a custom JSON response' do
239
- get :index, access_token: token_string
246
+ get :index, params: { access_token: token_string }
240
247
  expect(response.header).to_not include('WWW-Authenticate')
241
248
  expect(response.content_type).to eq('application/json')
242
249
  expect(response.status).to eq 403
243
- parsed_body = JSON.parse(response.body)
244
- expect(parsed_body).not_to be_nil
245
- expect(parsed_body['error_message']).to match('Forbidden')
250
+
251
+ expect(json_response).not_to be_nil
252
+ expect(json_response['error_message']).to match('Forbidden')
246
253
  end
247
254
  end
248
255
 
@@ -258,7 +265,7 @@ describe 'doorkeeper authorize filter' do
258
265
  end
259
266
 
260
267
  it 'overrides the default status code' do
261
- get :index, access_token: token_string
268
+ get :index, params: { access_token: token_string }
262
269
  expect(response.status).to eq 404
263
270
  end
264
271
  end
@@ -267,6 +274,7 @@ describe 'doorkeeper authorize filter' do
267
274
  before do
268
275
  module ControllerActions
269
276
  remove_method :doorkeeper_forbidden_render_options
277
+
270
278
  def doorkeeper_forbidden_render_options(*)
271
279
  { plain: 'Forbidden' }
272
280
  end
@@ -274,7 +282,7 @@ describe 'doorkeeper authorize filter' do
274
282
  end
275
283
 
276
284
  it 'renders a custom status code and text response' do
277
- get :index, access_token: token_string
285
+ get :index, params: { access_token: token_string }
278
286
  expect(response.header).to_not include('WWW-Authenticate')
279
287
  expect(response.status).to eq 403
280
288
  expect(response.body).to eq('Forbidden')
@@ -285,6 +293,7 @@ describe 'doorkeeper authorize filter' do
285
293
  before do
286
294
  module ControllerActions
287
295
  remove_method :doorkeeper_forbidden_render_options
296
+
288
297
  def doorkeeper_forbidden_render_options(*)
289
298
  { respond_not_found_when_forbidden: true, plain: 'Not Found' }
290
299
  end
@@ -292,7 +301,7 @@ describe 'doorkeeper authorize filter' do
292
301
  end
293
302
 
294
303
  it 'overrides the default status code' do
295
- get :index, access_token: token_string
304
+ get :index, params: { access_token: token_string }
296
305
  expect(response.status).to eq 404
297
306
  end
298
307
  end