doorkeeper 4.2.5 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (215) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE.md +25 -0
  3. data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
  4. data/.gitignore +2 -1
  5. data/.gitlab-ci.yml +16 -0
  6. data/.hound.yml +2 -13
  7. data/.rubocop.yml +17 -0
  8. data/.travis.yml +19 -4
  9. data/Appraisals +8 -4
  10. data/CODE_OF_CONDUCT.md +46 -0
  11. data/Gemfile +1 -1
  12. data/NEWS.md +115 -0
  13. data/README.md +175 -39
  14. data/RELEASING.md +5 -12
  15. data/Rakefile +6 -0
  16. data/SECURITY.md +15 -0
  17. data/UPGRADE.md +2 -0
  18. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  19. data/app/controllers/doorkeeper/application_controller.rb +2 -5
  20. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  21. data/app/controllers/doorkeeper/applications_controller.rb +47 -13
  22. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  23. data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
  24. data/app/controllers/doorkeeper/tokens_controller.rb +24 -17
  25. data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
  26. data/app/validators/redirect_uri_validator.rb +13 -2
  27. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  28. data/app/views/doorkeeper/applications/_form.html.erb +31 -19
  29. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  30. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  31. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  32. data/app/views/doorkeeper/applications/show.html.erb +8 -5
  33. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  34. data/app/views/doorkeeper/authorizations/new.html.erb +5 -1
  35. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  36. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  37. data/config/locales/en.yml +19 -6
  38. data/doorkeeper.gemspec +20 -20
  39. data/gemfiles/rails_4_2.gemfile +6 -4
  40. data/gemfiles/rails_5_0.gemfile +4 -4
  41. data/gemfiles/rails_5_1.gemfile +6 -7
  42. data/gemfiles/rails_5_2.gemfile +12 -0
  43. data/gemfiles/rails_master.gemfile +17 -0
  44. data/lib/doorkeeper/config.rb +123 -71
  45. data/lib/doorkeeper/engine.rb +7 -3
  46. data/lib/doorkeeper/errors.rb +20 -5
  47. data/lib/doorkeeper/grape/helpers.rb +14 -9
  48. data/lib/doorkeeper/helpers/controller.rb +16 -22
  49. data/lib/doorkeeper/models/access_grant_mixin.rb +67 -23
  50. data/lib/doorkeeper/models/access_token_mixin.rb +54 -55
  51. data/lib/doorkeeper/models/application_mixin.rb +16 -30
  52. data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
  53. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  54. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  55. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  56. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  57. data/lib/doorkeeper/oauth/authorization/token.rb +46 -20
  58. data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
  59. data/lib/doorkeeper/oauth/base_request.rb +23 -7
  60. data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
  61. data/lib/doorkeeper/oauth/client.rb +2 -4
  62. data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
  63. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
  64. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
  65. data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
  66. data/lib/doorkeeper/oauth/error.rb +2 -2
  67. data/lib/doorkeeper/oauth/error_response.rb +11 -4
  68. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  69. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  70. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
  71. data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
  72. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
  73. data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
  74. data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
  75. data/lib/doorkeeper/oauth/scopes.rb +19 -9
  76. data/lib/doorkeeper/oauth/token.rb +6 -3
  77. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  78. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  79. data/lib/doorkeeper/oauth.rb +13 -0
  80. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  81. data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
  82. data/lib/doorkeeper/orm/active_record/application.rb +45 -0
  83. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  84. data/lib/doorkeeper/orm/active_record.rb +21 -8
  85. data/lib/doorkeeper/rails/helpers.rb +7 -10
  86. data/lib/doorkeeper/rails/routes.rb +21 -7
  87. data/lib/doorkeeper/rake/db.rake +40 -0
  88. data/lib/doorkeeper/rake/setup.rake +6 -0
  89. data/lib/doorkeeper/rake.rb +14 -0
  90. data/lib/doorkeeper/request/authorization_code.rb +0 -2
  91. data/lib/doorkeeper/request/client_credentials.rb +0 -2
  92. data/lib/doorkeeper/request/code.rb +0 -2
  93. data/lib/doorkeeper/request/password.rb +1 -13
  94. data/lib/doorkeeper/request/refresh_token.rb +0 -2
  95. data/lib/doorkeeper/request/token.rb +0 -2
  96. data/lib/doorkeeper/request.rb +29 -30
  97. data/lib/doorkeeper/validations.rb +3 -2
  98. data/lib/doorkeeper/version.rb +14 -1
  99. data/lib/doorkeeper.rb +21 -17
  100. data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
  101. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  102. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  103. data/lib/generators/doorkeeper/migration_generator.rb +26 -9
  104. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  105. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
  106. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  107. data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
  108. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
  109. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  110. data/lib/generators/doorkeeper/templates/initializer.rb +104 -12
  111. data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
  112. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  113. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  114. data/spec/controllers/applications_controller_spec.rb +141 -17
  115. data/spec/controllers/authorizations_controller_spec.rb +304 -27
  116. data/spec/controllers/protected_resources_controller_spec.rb +44 -35
  117. data/spec/controllers/token_info_controller_spec.rb +17 -21
  118. data/spec/controllers/tokens_controller_spec.rb +201 -17
  119. data/spec/dummy/app/assets/config/manifest.js +2 -0
  120. data/spec/dummy/config/environments/test.rb +4 -5
  121. data/spec/dummy/config/initializers/doorkeeper.rb +23 -2
  122. data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
  123. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  124. data/spec/dummy/config/routes.rb +3 -42
  125. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  126. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  127. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
  128. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
  129. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
  130. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  131. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
  132. data/spec/dummy/db/schema.rb +38 -37
  133. data/spec/factories.rb +1 -1
  134. data/spec/generators/application_owner_generator_spec.rb +25 -6
  135. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  136. data/spec/generators/install_generator_spec.rb +1 -1
  137. data/spec/generators/migration_generator_spec.rb +25 -4
  138. data/spec/generators/pkce_generator_spec.rb +43 -0
  139. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  140. data/spec/generators/views_generator_spec.rb +1 -1
  141. data/spec/grape/grape_integration_spec.rb +135 -0
  142. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
  143. data/spec/lib/config_spec.rb +199 -22
  144. data/spec/lib/doorkeeper_spec.rb +1 -126
  145. data/spec/lib/models/expirable_spec.rb +0 -4
  146. data/spec/lib/models/revocable_spec.rb +2 -4
  147. data/spec/lib/models/scopes_spec.rb +0 -4
  148. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  149. data/spec/lib/oauth/authorization_code_request_spec.rb +63 -13
  150. data/spec/lib/oauth/base_request_spec.rb +43 -10
  151. data/spec/lib/oauth/base_response_spec.rb +1 -1
  152. data/spec/lib/oauth/client/credentials_spec.rb +5 -5
  153. data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
  154. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  155. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  156. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  157. data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
  158. data/spec/lib/oauth/client_spec.rb +0 -3
  159. data/spec/lib/oauth/code_request_spec.rb +5 -5
  160. data/spec/lib/oauth/error_response_spec.rb +0 -3
  161. data/spec/lib/oauth/error_spec.rb +1 -3
  162. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  163. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  164. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  165. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
  166. data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
  167. data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
  168. data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
  169. data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
  170. data/spec/lib/oauth/scopes_spec.rb +28 -4
  171. data/spec/lib/oauth/token_request_spec.rb +10 -13
  172. data/spec/lib/oauth/token_response_spec.rb +0 -1
  173. data/spec/lib/oauth/token_spec.rb +37 -14
  174. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  175. data/spec/lib/request/strategy_spec.rb +0 -1
  176. data/spec/lib/server_spec.rb +10 -0
  177. data/spec/models/doorkeeper/access_grant_spec.rb +45 -2
  178. data/spec/models/doorkeeper/access_token_spec.rb +132 -64
  179. data/spec/models/doorkeeper/application_spec.rb +114 -23
  180. data/spec/requests/applications/applications_request_spec.rb +139 -6
  181. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  182. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  183. data/spec/requests/endpoints/token_spec.rb +15 -6
  184. data/spec/requests/flows/authorization_code_errors_spec.rb +12 -2
  185. data/spec/requests/flows/authorization_code_spec.rb +199 -2
  186. data/spec/requests/flows/client_credentials_spec.rb +73 -5
  187. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  188. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  189. data/spec/requests/flows/password_spec.rb +160 -24
  190. data/spec/requests/flows/refresh_token_spec.rb +6 -6
  191. data/spec/requests/flows/revoke_token_spec.rb +26 -26
  192. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  193. data/spec/requests/protected_resources/metal_spec.rb +2 -2
  194. data/spec/requests/protected_resources/private_api_spec.rb +2 -2
  195. data/spec/routing/custom_controller_routes_spec.rb +63 -7
  196. data/spec/routing/default_routes_spec.rb +6 -2
  197. data/spec/routing/scoped_routes_spec.rb +16 -2
  198. data/spec/spec_helper.rb +54 -3
  199. data/spec/spec_helper_integration.rb +2 -64
  200. data/spec/support/dependencies/factory_bot.rb +2 -0
  201. data/spec/support/doorkeeper_rspec.rb +19 -0
  202. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  203. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  204. data/spec/support/helpers/model_helper.rb +9 -4
  205. data/spec/support/helpers/request_spec_helper.rb +18 -6
  206. data/spec/support/helpers/url_helper.rb +15 -10
  207. data/spec/support/http_method_shim.rb +12 -16
  208. data/spec/support/shared/controllers_shared_context.rb +2 -6
  209. data/spec/support/shared/models_shared_examples.rb +4 -4
  210. data/spec/validators/redirect_uri_validator_spec.rb +58 -7
  211. data/spec/version/version_spec.rb +15 -0
  212. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  213. metadata +75 -33
  214. data/spec/controllers/application_metal_controller.rb +0 -10
  215. data/spec/support/dependencies/factory_girl.rb +0 -2
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  feature 'Implicit Grant Flow (feature spec)' do
4
4
  background do
@@ -17,6 +17,29 @@ feature 'Implicit Grant Flow (feature spec)' do
17
17
 
18
18
  i_should_be_on_client_callback @client
19
19
  end
20
+
21
+ context 'when application scopes are present and no scope is passed' do
22
+ background do
23
+ @client.update_attributes(scopes: 'public write read')
24
+ end
25
+
26
+ scenario 'access token has no scopes' do
27
+ default_scopes_exist :admin
28
+ visit authorization_endpoint_url(client: @client, response_type: 'token')
29
+ click_on 'Authorize'
30
+ access_token_should_exist_for @client, @resource_owner
31
+ token = Doorkeeper::AccessToken.first
32
+ expect(token.scopes).to be_empty
33
+ end
34
+
35
+ scenario 'access token has scopes which are common in application scopees and default scopes' do
36
+ default_scopes_exist :public, :write
37
+ visit authorization_endpoint_url(client: @client, response_type: 'token')
38
+ click_on 'Authorize'
39
+ access_token_should_exist_for @client, @resource_owner
40
+ access_token_should_have_scopes :public, :write
41
+ end
42
+ end
20
43
  end
21
44
 
22
45
  describe 'Implicit Grant Flow (request spec)' do
@@ -34,11 +57,13 @@ describe 'Implicit Grant Flow (request spec)' do
34
57
  token = client_is_authorized(@client, @resource_owner)
35
58
 
36
59
  post "/oauth/authorize",
37
- client_id: @client.uid,
38
- state: '',
39
- redirect_uri: @client.redirect_uri,
40
- response_type: 'token',
41
- commit: 'Authorize'
60
+ params: {
61
+ client_id: @client.uid,
62
+ state: '',
63
+ redirect_uri: @client.redirect_uri,
64
+ response_type: 'token',
65
+ commit: 'Authorize'
66
+ }
42
67
 
43
68
  expect(response.location).not_to include(token.token)
44
69
  end
@@ -49,11 +74,13 @@ describe 'Implicit Grant Flow (request spec)' do
49
74
  token = client_is_authorized(@client, @resource_owner)
50
75
 
51
76
  post "/oauth/authorize",
52
- client_id: @client.uid,
53
- state: '',
54
- redirect_uri: @client.redirect_uri,
55
- response_type: 'token',
56
- commit: 'Authorize'
77
+ params: {
78
+ client_id: @client.uid,
79
+ state: '',
80
+ redirect_uri: @client.redirect_uri,
81
+ response_type: 'token',
82
+ commit: 'Authorize'
83
+ }
57
84
 
58
85
  expect(response.location).to include(token.token)
59
86
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  describe 'Resource Owner Password Credentials Flow not set up' do
4
4
  before do
@@ -7,49 +7,92 @@ describe 'Resource Owner Password Credentials Flow not set up' do
7
7
  end
8
8
 
9
9
  context 'with valid user credentials' do
10
- it 'doesn\'t issue new token' do
10
+ it 'does not issue new token' do
11
11
  expect do
12
12
  post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
13
- end.to_not change { Doorkeeper::AccessToken.count }
13
+ end.to_not(change { Doorkeeper::AccessToken.count })
14
14
  end
15
15
  end
16
16
  end
17
17
 
18
18
  describe 'Resource Owner Password Credentials Flow' do
19
+ let(:client_attributes) { {} }
20
+
19
21
  before do
20
22
  config_is_set(:grant_flows, ["password"])
21
23
  config_is_set(:resource_owner_from_credentials) { User.authenticate! params[:username], params[:password] }
22
- client_exists
24
+ client_exists(client_attributes)
23
25
  create_resource_owner
24
26
  end
25
27
 
26
28
  context 'with valid user credentials' do
27
- it 'should issue new token with confidential client' do
28
- expect do
29
- post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
30
- end.to change { Doorkeeper::AccessToken.count }.by(1)
29
+ context "with non-confidential/public client" do
30
+ let(:client_attributes) { { confidential: false } }
31
+
32
+ context "when client_secret absent" do
33
+ it "should issue new token" do
34
+ expect do
35
+ post password_token_endpoint_url(client_id: @client.uid, resource_owner: @resource_owner)
36
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
37
+
38
+ token = Doorkeeper::AccessToken.first
39
+
40
+ expect(token.application_id).to eq @client.id
41
+ should_have_json 'access_token', token.token
42
+ end
43
+ end
44
+
45
+ context "when client_secret present" do
46
+ it "should issue new token" do
47
+ expect do
48
+ post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
49
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
50
+
51
+ token = Doorkeeper::AccessToken.first
52
+
53
+ expect(token.application_id).to eq @client.id
54
+ should_have_json 'access_token', token.token
55
+ end
56
+
57
+ context "when client_secret incorrect" do
58
+ it "should not issue new token" do
59
+ expect do
60
+ post password_token_endpoint_url(client_id: @client.uid, client_secret: 'foobar', resource_owner: @resource_owner)
61
+ end.not_to(change { Doorkeeper::AccessToken.count })
62
+
63
+ expect(response).not_to be_ok
64
+ end
65
+ end
66
+ end
67
+ end
31
68
 
32
- token = Doorkeeper::AccessToken.first
69
+ context "with confidential/private client" do
70
+ it "should issue new token" do
71
+ expect do
72
+ post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
73
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
33
74
 
34
- expect(token.application_id).to eq @client.id
35
- should_have_json 'access_token', token.token
36
- end
75
+ token = Doorkeeper::AccessToken.first
37
76
 
38
- it 'should issue new token with public client (only client_id present)' do
39
- expect do
40
- post password_token_endpoint_url(client_id: @client.uid, resource_owner: @resource_owner)
41
- end.to change { Doorkeeper::AccessToken.count }.by(1)
77
+ expect(token.application_id).to eq @client.id
78
+ should_have_json 'access_token', token.token
79
+ end
42
80
 
43
- token = Doorkeeper::AccessToken.first
81
+ context "when client_secret absent" do
82
+ it "should not issue new token" do
83
+ expect do
84
+ post password_token_endpoint_url(client_id: @client.uid, resource_owner: @resource_owner)
85
+ end.not_to(change { Doorkeeper::AccessToken.count })
44
86
 
45
- expect(token.application_id).to eq @client.id
46
- should_have_json 'access_token', token.token
87
+ expect(response).not_to be_ok
88
+ end
89
+ end
47
90
  end
48
91
 
49
92
  it 'should issue new token without client credentials' do
50
93
  expect do
51
94
  post password_token_endpoint_url(resource_owner: @resource_owner)
52
- end.to change { Doorkeeper::AccessToken.count }.by(1)
95
+ end.to(change { Doorkeeper::AccessToken.count }.by(1))
53
96
 
54
97
  token = Doorkeeper::AccessToken.first
55
98
 
@@ -77,6 +120,99 @@ describe 'Resource Owner Password Credentials Flow' do
77
120
  expect(Doorkeeper::AccessToken.count).to be(1)
78
121
  should_have_json 'access_token', Doorkeeper::AccessToken.first.token
79
122
  end
123
+
124
+ context 'with valid, default scope' do
125
+ before do
126
+ default_scopes_exist :public
127
+ end
128
+
129
+ it 'should issue new token' do
130
+ expect do
131
+ post password_token_endpoint_url(client: @client, resource_owner: @resource_owner, scope: 'public')
132
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
133
+
134
+ token = Doorkeeper::AccessToken.first
135
+
136
+ expect(token.application_id).to eq @client.id
137
+ should_have_json 'access_token', token.token
138
+ should_have_json 'scope', 'public'
139
+ end
140
+ end
141
+ end
142
+
143
+ context 'when application scopes are present and differs from configured default scopes and no scope is passed' do
144
+ before do
145
+ default_scopes_exist :public
146
+ @client.update_attributes(scopes: 'abc')
147
+ end
148
+
149
+ it 'issues new token without any scope' do
150
+ expect do
151
+ post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
152
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
153
+
154
+ token = Doorkeeper::AccessToken.first
155
+
156
+ expect(token.application_id).to eq @client.id
157
+ expect(token.scopes).to be_empty
158
+ should_have_json 'access_token', token.token
159
+ should_not_have_json 'scope'
160
+ end
161
+ end
162
+
163
+ context 'when application scopes contain some of the default scopes and no scope is passed' do
164
+ before do
165
+ @client.update_attributes(scopes: 'read write public')
166
+ end
167
+
168
+ it 'issues new token with one default scope that are present in application scopes' do
169
+ default_scopes_exist :public, :admin
170
+
171
+ expect do
172
+ post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
173
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
174
+
175
+ token = Doorkeeper::AccessToken.first
176
+
177
+ expect(token.application_id).to eq @client.id
178
+ should_have_json 'access_token', token.token
179
+ should_have_json 'scope', 'public'
180
+ end
181
+
182
+ it 'issues new token with multiple default scopes that are present in application scopes' do
183
+ default_scopes_exist :public, :read, :update
184
+
185
+ expect do
186
+ post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
187
+ end.to change { Doorkeeper::AccessToken.count }.by(1)
188
+
189
+ token = Doorkeeper::AccessToken.first
190
+
191
+ expect(token.application_id).to eq @client.id
192
+ should_have_json 'access_token', token.token
193
+ should_have_json 'scope', 'public read'
194
+ end
195
+ end
196
+
197
+ context 'with invalid scopes' do
198
+ subject do
199
+ post password_token_endpoint_url(client: @client,
200
+ resource_owner: @resource_owner,
201
+ scope: 'random')
202
+ end
203
+
204
+ it 'should not issue new token' do
205
+ expect { subject }.to_not(change { Doorkeeper::AccessToken.count })
206
+ end
207
+
208
+ it 'should return invalid_scope error' do
209
+ subject
210
+ should_have_json 'error', 'invalid_scope'
211
+ should_have_json 'error_description', translated_error_message(:invalid_scope)
212
+ should_not_have_json 'access_token'
213
+
214
+ expect(response.status).to eq(401)
215
+ end
80
216
  end
81
217
 
82
218
  context 'with invalid user credentials' do
@@ -85,13 +221,13 @@ describe 'Resource Owner Password Credentials Flow' do
85
221
  post password_token_endpoint_url(client: @client,
86
222
  resource_owner_username: @resource_owner.name,
87
223
  resource_owner_password: 'wrongpassword')
88
- end.to_not change { Doorkeeper::AccessToken.count }
224
+ end.to_not(change { Doorkeeper::AccessToken.count })
89
225
  end
90
226
 
91
227
  it 'should not issue new token without credentials' do
92
228
  expect do
93
229
  post password_token_endpoint_url(client: @client)
94
- end.to_not change { Doorkeeper::AccessToken.count }
230
+ end.to_not(change { Doorkeeper::AccessToken.count })
95
231
  end
96
232
  end
97
233
 
@@ -101,7 +237,7 @@ describe 'Resource Owner Password Credentials Flow' do
101
237
  post password_token_endpoint_url(client_id: @client.uid,
102
238
  client_secret: 'bad_secret',
103
239
  resource_owner: @resource_owner)
104
- end.to_not change { Doorkeeper::AccessToken.count }
240
+ end.to_not(change { Doorkeeper::AccessToken.count })
105
241
  end
106
242
  end
107
243
 
@@ -109,7 +245,7 @@ describe 'Resource Owner Password Credentials Flow' do
109
245
  it 'should not issue new token with bad client id' do
110
246
  expect do
111
247
  post password_token_endpoint_url(client_id: 'bad_id', resource_owner: @resource_owner)
112
- end.to_not change { Doorkeeper::AccessToken.count }
248
+ end.to_not(change { Doorkeeper::AccessToken.count })
113
249
  end
114
250
  end
115
251
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  describe 'Refresh Token Flow' do
4
4
  before do
@@ -14,7 +14,7 @@ describe 'Refresh Token Flow' do
14
14
  authorization_code_exists application: @client
15
15
  end
16
16
 
17
- it 'client gets the refresh token and refreshses it' do
17
+ it 'client gets the refresh token and refreshes it' do
18
18
  post token_endpoint_url(code: @authorization.token, client: @client)
19
19
 
20
20
  token = Doorkeeper::AccessToken.first
@@ -37,7 +37,7 @@ describe 'Refresh Token Flow' do
37
37
 
38
38
  context 'refreshing the token' do
39
39
  before do
40
- @token = FactoryGirl.create(
40
+ @token = FactoryBot.create(
41
41
  :access_token,
42
42
  application: @client,
43
43
  resource_owner_id: 1,
@@ -101,14 +101,14 @@ describe 'Refresh Token Flow' do
101
101
  should_have_json 'error', 'invalid_grant'
102
102
  end
103
103
 
104
- it 'client gets an error for revoked acccess token' do
104
+ it 'client gets an error for revoked access token' do
105
105
  @token.revoke
106
106
  post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
107
107
  should_not_have_json 'refresh_token'
108
108
  should_have_json 'error', 'invalid_grant'
109
109
  end
110
110
 
111
- it 'second of simultaneous client requests get an error for revoked acccess token' do
111
+ it 'second of simultaneous client requests get an error for revoked access token' do
112
112
  allow_any_instance_of(Doorkeeper::AccessToken).to receive(:revoked?).and_return(false, true)
113
113
  post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
114
114
 
@@ -130,7 +130,7 @@ describe 'Refresh Token Flow' do
130
130
  )
131
131
  last_token.update_attribute :created_at, 5.seconds.ago
132
132
 
133
- @token = FactoryGirl.create(
133
+ @token = FactoryBot.create(
134
134
  :access_token,
135
135
  application: @client,
136
136
  resource_owner_id: @resource_owner.id,
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  describe 'Revoke Token Flow' do
4
4
  before do
@@ -6,10 +6,10 @@ describe 'Revoke Token Flow' do
6
6
  end
7
7
 
8
8
  context 'with default parameters' do
9
- let(:client_application) { FactoryGirl.create :application }
9
+ let(:client_application) { FactoryBot.create :application }
10
10
  let(:resource_owner) { User.create!(name: 'John', password: 'sekret') }
11
11
  let(:access_token) do
12
- FactoryGirl.create(:access_token,
12
+ FactoryBot.create(:access_token,
13
13
  application: client_application,
14
14
  resource_owner_id: resource_owner.id,
15
15
  use_refresh_token: true)
@@ -24,31 +24,31 @@ describe 'Revoke Token Flow' do
24
24
  end
25
25
 
26
26
  it 'should revoke the access token provided' do
27
- post revocation_token_endpoint_url, { token: access_token.token }, headers
27
+ post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
28
28
 
29
29
  access_token.reload
30
30
 
31
- expect(response).to be_success
31
+ expect(response).to be_successful
32
32
  expect(access_token.revoked?).to be_truthy
33
33
  end
34
34
 
35
35
  it 'should revoke the refresh token provided' do
36
- post revocation_token_endpoint_url, { token: access_token.refresh_token }, headers
36
+ post revocation_token_endpoint_url, params: { token: access_token.refresh_token }, headers: headers
37
37
 
38
38
  access_token.reload
39
39
 
40
- expect(response).to be_success
40
+ expect(response).to be_successful
41
41
  expect(access_token.revoked?).to be_truthy
42
42
  end
43
43
 
44
44
  context 'with invalid token to revoke' do
45
45
  it 'should not revoke any tokens and respond successfully' do
46
46
  num_prev_revoked_tokens = Doorkeeper::AccessToken.where(revoked_at: nil).count
47
- post revocation_token_endpoint_url, { token: 'I_AM_AN_INVALID_TOKEN' }, headers
47
+ post revocation_token_endpoint_url, params: { token: 'I_AM_AN_INVALID_TOKEN' }, headers: headers
48
48
 
49
49
  # The authorization server responds with HTTP status code 200 even if
50
50
  # token is invalid
51
- expect(response).to be_success
51
+ expect(response).to be_successful
52
52
  expect(Doorkeeper::AccessToken.where(revoked_at: nil).count).to eq(num_prev_revoked_tokens)
53
53
  end
54
54
  end
@@ -60,28 +60,28 @@ describe 'Revoke Token Flow' do
60
60
  { 'HTTP_AUTHORIZATION' => "Basic #{credentials}" }
61
61
  end
62
62
  it 'should not revoke any tokens and respond successfully' do
63
- post revocation_token_endpoint_url, { token: access_token.token }, headers
63
+ post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
64
64
 
65
65
  access_token.reload
66
66
 
67
- expect(response).to be_success
67
+ expect(response).to be_successful
68
68
  expect(access_token.revoked?).to be_falsey
69
69
  end
70
70
  end
71
71
 
72
72
  context 'with no credentials and a valid token' do
73
73
  it 'should not revoke any tokens and respond successfully' do
74
- post revocation_token_endpoint_url, { token: access_token.token }
74
+ post revocation_token_endpoint_url, params: { token: access_token.token }
75
75
 
76
76
  access_token.reload
77
77
 
78
- expect(response).to be_success
78
+ expect(response).to be_successful
79
79
  expect(access_token.revoked?).to be_falsey
80
80
  end
81
81
  end
82
82
 
83
83
  context 'with valid token for another client application' do
84
- let(:other_client_application) { FactoryGirl.create :application }
84
+ let(:other_client_application) { FactoryBot.create :application }
85
85
  let(:headers) do
86
86
  client_id = other_client_application.uid
87
87
  client_secret = other_client_application.secret
@@ -90,11 +90,11 @@ describe 'Revoke Token Flow' do
90
90
  end
91
91
 
92
92
  it 'should not revoke the token as its unauthorized' do
93
- post revocation_token_endpoint_url, { token: access_token.token }, headers
93
+ post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
94
94
 
95
95
  access_token.reload
96
96
 
97
- expect(response).to be_success
97
+ expect(response).to be_successful
98
98
  expect(access_token.revoked?).to be_falsey
99
99
  end
100
100
  end
@@ -102,53 +102,53 @@ describe 'Revoke Token Flow' do
102
102
 
103
103
  context 'with public OAuth 2.0 client/application' do
104
104
  let(:access_token) do
105
- FactoryGirl.create(:access_token,
105
+ FactoryBot.create(:access_token,
106
106
  application: nil,
107
107
  resource_owner_id: resource_owner.id,
108
108
  use_refresh_token: true)
109
109
  end
110
110
 
111
111
  it 'should revoke the access token provided' do
112
- post revocation_token_endpoint_url, { token: access_token.token }
112
+ post revocation_token_endpoint_url, params: { token: access_token.token }
113
113
 
114
114
  access_token.reload
115
115
 
116
- expect(response).to be_success
116
+ expect(response).to be_successful
117
117
  expect(access_token.revoked?).to be_truthy
118
118
  end
119
119
 
120
120
  it 'should revoke the refresh token provided' do
121
- post revocation_token_endpoint_url, { token: access_token.refresh_token }
121
+ post revocation_token_endpoint_url, params: { token: access_token.refresh_token }
122
122
 
123
123
  access_token.reload
124
124
 
125
- expect(response).to be_success
125
+ expect(response).to be_successful
126
126
  expect(access_token.revoked?).to be_truthy
127
127
  end
128
128
 
129
129
  context 'with a valid token issued for a confidential client' do
130
130
  let(:access_token) do
131
- FactoryGirl.create(:access_token,
131
+ FactoryBot.create(:access_token,
132
132
  application: client_application,
133
133
  resource_owner_id: resource_owner.id,
134
134
  use_refresh_token: true)
135
135
  end
136
136
 
137
137
  it 'should not revoke the access token provided' do
138
- post revocation_token_endpoint_url, { token: access_token.token }
138
+ post revocation_token_endpoint_url, params: { token: access_token.token }
139
139
 
140
140
  access_token.reload
141
141
 
142
- expect(response).to be_success
142
+ expect(response).to be_successful
143
143
  expect(access_token.revoked?).to be_falsey
144
144
  end
145
145
 
146
146
  it 'should not revoke the refresh token provided' do
147
- post revocation_token_endpoint_url, { token: access_token.token }
147
+ post revocation_token_endpoint_url, params: { token: access_token.token }
148
148
 
149
149
  access_token.reload
150
150
 
151
- expect(response).to be_success
151
+ expect(response).to be_successful
152
152
  expect(access_token.revoked?).to be_falsey
153
153
  end
154
154
  end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  feature 'Skip authorization form' do
4
4
  background do
@@ -15,13 +15,24 @@ feature 'Skip authorization form' do
15
15
  end
16
16
 
17
17
  scenario 'skips the authorization and return a new grant code' do
18
- client_is_authorized(@client, @resource_owner, scopes: 'public')
19
- visit authorization_endpoint_url(client: @client)
18
+ client_is_authorized(@client, @resource_owner, scopes: "public")
19
+ visit authorization_endpoint_url(client: @client, scope: "public")
20
+
21
+ i_should_not_see "Authorize"
22
+ client_should_be_authorized @client
23
+ i_should_be_on_client_callback @client
24
+ url_should_have_param "code", Doorkeeper::AccessGrant.first.token
25
+ end
26
+
27
+ scenario "skips the authorization if other scopes are not requested" do
28
+ client_exists scopes: "public read write"
29
+ client_is_authorized(@client, @resource_owner, scopes: "public")
30
+ visit authorization_endpoint_url(client: @client, scope: "public")
20
31
 
21
- i_should_not_see 'Authorize'
32
+ i_should_not_see "Authorize"
22
33
  client_should_be_authorized @client
23
34
  i_should_be_on_client_callback @client
24
- url_should_have_param 'code', Doorkeeper::AccessGrant.first.token
35
+ url_should_have_param "code", Doorkeeper::AccessGrant.first.token
25
36
  end
26
37
 
27
38
  scenario 'does not skip authorization when scopes differ (new request has fewer scopes)' do
@@ -43,12 +54,6 @@ feature 'Skip authorization form' do
43
54
  access_grant_should_have_scopes :public
44
55
  end
45
56
 
46
- scenario 'doesn not skip authorization when scopes are greater' do
47
- client_is_authorized(@client, @resource_owner, scopes: 'public')
48
- visit authorization_endpoint_url(client: @client, scope: 'public write')
49
- i_should_see 'Authorize'
50
- end
51
-
52
57
  scenario 'creates grant with new scope when scopes are greater' do
53
58
  client_is_authorized(@client, @resource_owner, scopes: 'public')
54
59
  visit authorization_endpoint_url(client: @client, scope: 'public write')
@@ -1,8 +1,8 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  describe 'ActionController::Metal API' do
4
4
  before do
5
- @client = FactoryGirl.create(:application)
5
+ @client = FactoryBot.create(:application)
6
6
  @resource = User.create!(name: 'Joe', password: 'sekret')
7
7
  @token = client_is_authorized(@client, @resource)
8
8
  end
@@ -1,8 +1,8 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  feature 'Private API' do
4
4
  background do
5
- @client = FactoryGirl.create(:application)
5
+ @client = FactoryBot.create(:application)
6
6
  @resource = User.create!(name: 'Joe', password: 'sekret')
7
7
  @token = client_is_authorized(@client, @resource)
8
8
  end