doorkeeper 4.2.5 → 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 (206) 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 -4
  8. data/Appraisals +8 -4
  9. data/CODE_OF_CONDUCT.md +46 -0
  10. data/Gemfile +1 -1
  11. data/NEWS.md +81 -0
  12. data/README.md +169 -34
  13. data/RELEASING.md +5 -12
  14. data/Rakefile +6 -0
  15. data/SECURITY.md +15 -0
  16. data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
  17. data/app/controllers/doorkeeper/application_controller.rb +2 -5
  18. data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
  19. data/app/controllers/doorkeeper/applications_controller.rb +47 -13
  20. data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
  21. data/app/controllers/doorkeeper/authorized_applications_controller.rb +15 -1
  22. data/app/controllers/doorkeeper/tokens_controller.rb +15 -7
  23. data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
  24. data/app/validators/redirect_uri_validator.rb +13 -2
  25. data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
  26. data/app/views/doorkeeper/applications/_form.html.erb +31 -19
  27. data/app/views/doorkeeper/applications/edit.html.erb +1 -1
  28. data/app/views/doorkeeper/applications/index.html.erb +18 -6
  29. data/app/views/doorkeeper/applications/new.html.erb +1 -1
  30. data/app/views/doorkeeper/applications/show.html.erb +8 -5
  31. data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
  32. data/app/views/doorkeeper/authorizations/new.html.erb +5 -1
  33. data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
  34. data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
  35. data/config/locales/en.yml +18 -6
  36. data/doorkeeper.gemspec +6 -6
  37. data/gemfiles/rails_4_2.gemfile +6 -4
  38. data/gemfiles/rails_5_0.gemfile +4 -4
  39. data/gemfiles/rails_5_1.gemfile +6 -7
  40. data/gemfiles/rails_5_2.gemfile +12 -0
  41. data/gemfiles/rails_master.gemfile +14 -0
  42. data/lib/doorkeeper/config.rb +107 -68
  43. data/lib/doorkeeper/engine.rb +7 -3
  44. data/lib/doorkeeper/errors.rb +20 -5
  45. data/lib/doorkeeper/grape/helpers.rb +14 -9
  46. data/lib/doorkeeper/helpers/controller.rb +16 -22
  47. data/lib/doorkeeper/models/access_grant_mixin.rb +52 -23
  48. data/lib/doorkeeper/models/access_token_mixin.rb +51 -52
  49. data/lib/doorkeeper/models/application_mixin.rb +16 -30
  50. data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
  51. data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
  52. data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
  53. data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
  54. data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
  55. data/lib/doorkeeper/oauth/authorization/token.rb +41 -20
  56. data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
  57. data/lib/doorkeeper/oauth/base_request.rb +22 -7
  58. data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
  59. data/lib/doorkeeper/oauth/client.rb +2 -2
  60. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -1
  61. data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -2
  62. data/lib/doorkeeper/oauth/error.rb +2 -2
  63. data/lib/doorkeeper/oauth/error_response.rb +11 -4
  64. data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
  65. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
  66. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
  67. data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
  68. data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
  69. data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
  70. data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
  71. data/lib/doorkeeper/oauth/scopes.rb +19 -9
  72. data/lib/doorkeeper/oauth/token.rb +6 -3
  73. data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
  74. data/lib/doorkeeper/oauth/token_response.rb +4 -2
  75. data/lib/doorkeeper/oauth.rb +13 -0
  76. data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
  77. data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
  78. data/lib/doorkeeper/orm/active_record/application.rb +34 -0
  79. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
  80. data/lib/doorkeeper/orm/active_record.rb +21 -8
  81. data/lib/doorkeeper/rails/helpers.rb +7 -10
  82. data/lib/doorkeeper/rails/routes.rb +21 -7
  83. data/lib/doorkeeper/rake/db.rake +40 -0
  84. data/lib/doorkeeper/rake/setup.rake +6 -0
  85. data/lib/doorkeeper/rake.rb +14 -0
  86. data/lib/doorkeeper/request/password.rb +1 -11
  87. data/lib/doorkeeper/request.rb +29 -23
  88. data/lib/doorkeeper/validations.rb +3 -2
  89. data/lib/doorkeeper/version.rb +14 -1
  90. data/lib/doorkeeper.rb +6 -17
  91. data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
  92. data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
  93. data/lib/generators/doorkeeper/install_generator.rb +17 -9
  94. data/lib/generators/doorkeeper/migration_generator.rb +26 -9
  95. data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
  96. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
  97. data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
  98. data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
  99. data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
  100. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
  101. data/lib/generators/doorkeeper/templates/initializer.rb +88 -10
  102. data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
  103. data/lib/generators/doorkeeper/views_generator.rb +3 -1
  104. data/spec/controllers/application_metal_controller_spec.rb +50 -0
  105. data/spec/controllers/applications_controller_spec.rb +141 -17
  106. data/spec/controllers/authorizations_controller_spec.rb +277 -27
  107. data/spec/controllers/protected_resources_controller_spec.rb +44 -35
  108. data/spec/controllers/token_info_controller_spec.rb +17 -21
  109. data/spec/controllers/tokens_controller_spec.rb +142 -10
  110. data/spec/dummy/app/assets/config/manifest.js +2 -0
  111. data/spec/dummy/config/environments/test.rb +4 -5
  112. data/spec/dummy/config/initializers/doorkeeper.rb +18 -1
  113. data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
  114. data/spec/dummy/config/initializers/secret_token.rb +0 -1
  115. data/spec/dummy/config/routes.rb +3 -42
  116. data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
  117. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
  118. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
  119. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
  120. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
  121. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
  122. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
  123. data/spec/dummy/db/schema.rb +38 -37
  124. data/spec/factories.rb +1 -1
  125. data/spec/generators/application_owner_generator_spec.rb +25 -6
  126. data/spec/generators/confidential_applications_generator_spec.rb +45 -0
  127. data/spec/generators/install_generator_spec.rb +1 -1
  128. data/spec/generators/migration_generator_spec.rb +25 -4
  129. data/spec/generators/pkce_generator_spec.rb +43 -0
  130. data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
  131. data/spec/generators/views_generator_spec.rb +1 -1
  132. data/spec/grape/grape_integration_spec.rb +135 -0
  133. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
  134. data/spec/lib/config_spec.rb +170 -22
  135. data/spec/lib/doorkeeper_spec.rb +1 -126
  136. data/spec/lib/models/expirable_spec.rb +0 -4
  137. data/spec/lib/models/revocable_spec.rb +2 -4
  138. data/spec/lib/models/scopes_spec.rb +0 -4
  139. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
  140. data/spec/lib/oauth/authorization_code_request_spec.rb +63 -13
  141. data/spec/lib/oauth/base_request_spec.rb +19 -10
  142. data/spec/lib/oauth/base_response_spec.rb +1 -1
  143. data/spec/lib/oauth/client/credentials_spec.rb +5 -5
  144. data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
  145. data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
  146. data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
  147. data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
  148. data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
  149. data/spec/lib/oauth/client_spec.rb +0 -3
  150. data/spec/lib/oauth/code_request_spec.rb +5 -5
  151. data/spec/lib/oauth/error_response_spec.rb +0 -3
  152. data/spec/lib/oauth/error_spec.rb +1 -3
  153. data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
  154. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
  155. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
  156. data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
  157. data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
  158. data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
  159. data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
  160. data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
  161. data/spec/lib/oauth/scopes_spec.rb +28 -4
  162. data/spec/lib/oauth/token_request_spec.rb +10 -13
  163. data/spec/lib/oauth/token_response_spec.rb +0 -1
  164. data/spec/lib/oauth/token_spec.rb +37 -14
  165. data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
  166. data/spec/lib/request/strategy_spec.rb +0 -1
  167. data/spec/lib/server_spec.rb +10 -0
  168. data/spec/models/doorkeeper/access_grant_spec.rb +2 -2
  169. data/spec/models/doorkeeper/access_token_spec.rb +118 -60
  170. data/spec/models/doorkeeper/application_spec.rb +101 -23
  171. data/spec/requests/applications/applications_request_spec.rb +94 -6
  172. data/spec/requests/applications/authorized_applications_spec.rb +1 -1
  173. data/spec/requests/endpoints/authorization_spec.rb +1 -1
  174. data/spec/requests/endpoints/token_spec.rb +15 -6
  175. data/spec/requests/flows/authorization_code_errors_spec.rb +12 -2
  176. data/spec/requests/flows/authorization_code_spec.rb +198 -1
  177. data/spec/requests/flows/client_credentials_spec.rb +73 -5
  178. data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
  179. data/spec/requests/flows/implicit_grant_spec.rb +38 -11
  180. data/spec/requests/flows/password_spec.rb +160 -24
  181. data/spec/requests/flows/refresh_token_spec.rb +6 -6
  182. data/spec/requests/flows/revoke_token_spec.rb +26 -26
  183. data/spec/requests/flows/skip_authorization_spec.rb +16 -11
  184. data/spec/requests/protected_resources/metal_spec.rb +2 -2
  185. data/spec/requests/protected_resources/private_api_spec.rb +2 -2
  186. data/spec/routing/custom_controller_routes_spec.rb +63 -7
  187. data/spec/routing/default_routes_spec.rb +6 -2
  188. data/spec/routing/scoped_routes_spec.rb +16 -2
  189. data/spec/spec_helper.rb +54 -3
  190. data/spec/spec_helper_integration.rb +2 -64
  191. data/spec/support/dependencies/factory_bot.rb +2 -0
  192. data/spec/support/doorkeeper_rspec.rb +19 -0
  193. data/spec/support/helpers/access_token_request_helper.rb +1 -1
  194. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  195. data/spec/support/helpers/model_helper.rb +9 -4
  196. data/spec/support/helpers/request_spec_helper.rb +10 -6
  197. data/spec/support/helpers/url_helper.rb +15 -10
  198. data/spec/support/http_method_shim.rb +12 -16
  199. data/spec/support/shared/controllers_shared_context.rb +2 -6
  200. data/spec/support/shared/models_shared_examples.rb +4 -4
  201. data/spec/validators/redirect_uri_validator_spec.rb +58 -7
  202. data/spec/version/version_spec.rb +15 -0
  203. data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
  204. metadata +74 -34
  205. data/spec/controllers/application_metal_controller.rb +0 -10
  206. data/spec/support/dependencies/factory_girl.rb +0 -2
@@ -1,36 +1,27 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Doorkeeper::TokenInfoController do
4
- describe 'when requesting tokeninfo with valid token' do
5
- let(:doorkeeper_token) { FactoryGirl.create(:access_token) }
6
-
7
- before(:each) do
8
- allow(controller).to receive(:doorkeeper_token) { doorkeeper_token }
9
- end
10
-
11
- def do_get
12
- get :show
13
- end
4
+ describe 'when requesting token info with valid token' do
5
+ let(:doorkeeper_token) { FactoryBot.create(:access_token) }
14
6
 
15
7
  describe 'successful request' do
8
+ it 'responds with token info' do
9
+ get :show, params: { access_token: doorkeeper_token.token }
16
10
 
17
- it 'responds with tokeninfo' do
18
- do_get
19
11
  expect(response.body).to eq(doorkeeper_token.to_json)
20
12
  end
21
13
 
22
14
  it 'responds with a 200 status' do
23
- do_get
15
+ get :show, params: { access_token: doorkeeper_token.token }
16
+
24
17
  expect(response.status).to eq 200
25
18
  end
26
19
  end
27
20
 
28
21
  describe 'invalid token response' do
29
- before(:each) do
30
- allow(controller).to receive(:doorkeeper_token).and_return(nil)
31
- end
32
22
  it 'responds with 401 when doorkeeper_token is not valid' do
33
- do_get
23
+ get :show
24
+
34
25
  expect(response.status).to eq 401
35
26
  expect(response.headers['WWW-Authenticate']).to match(/^Bearer/)
36
27
  end
@@ -38,14 +29,19 @@ describe Doorkeeper::TokenInfoController do
38
29
  it 'responds with 401 when doorkeeper_token is invalid, expired or revoked' do
39
30
  allow(controller).to receive(:doorkeeper_token).and_return(doorkeeper_token)
40
31
  allow(doorkeeper_token).to receive(:accessible?).and_return(false)
41
- do_get
32
+
33
+ get :show
34
+
42
35
  expect(response.status).to eq 401
43
36
  expect(response.headers['WWW-Authenticate']).to match(/^Bearer/)
44
37
  end
45
38
 
46
39
  it 'responds body message for error' do
47
- do_get
48
- expect(response.body).to eq(Doorkeeper::OAuth::ErrorResponse.new(name: :invalid_request, status: :unauthorized).body.to_json)
40
+ get :show
41
+
42
+ expect(response.body).to eq(
43
+ Doorkeeper::OAuth::ErrorResponse.new(name: :invalid_request, status: :unauthorized).body.to_json
44
+ )
49
45
  end
50
46
  end
51
47
  end
@@ -1,14 +1,9 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
 
3
3
  describe Doorkeeper::TokensController do
4
4
  describe 'when authorization has succeeded' do
5
- let :token do
6
- double(:token, authorize: true)
7
- end
5
+ let(:token) { double(:token, authorize: true) }
8
6
 
9
- before do
10
- allow(controller).to receive(:token) { token }
11
- end
12
7
 
13
8
  it 'returns the authorization' do
14
9
  skip 'verify need of these specs'
@@ -38,7 +33,7 @@ describe Doorkeeper::TokensController do
38
33
  allow(I18n).to receive(:translate).
39
34
  with(
40
35
  custom_message,
41
- hash_including(scope: [:doorkeeper, :errors, :messages]),
36
+ hash_including(scope: %i[doorkeeper errors messages]),
42
37
  ).
43
38
  and_return('Authorization custom message')
44
39
 
@@ -57,7 +52,7 @@ describe Doorkeeper::TokensController do
57
52
  }
58
53
  expect(response.status).to eq 401
59
54
  expect(response.headers['WWW-Authenticate']).to match(/Bearer/)
60
- expect(JSON.load(response.body)).to eq expected_response_body
55
+ expect(JSON.parse(response.body)).to eq expected_response_body
61
56
  end
62
57
  end
63
58
 
@@ -79,10 +74,147 @@ describe Doorkeeper::TokensController do
79
74
  expect(strategy).to receive(:authorize).once
80
75
  allow(controller).to receive(:strategy) { strategy }
81
76
  allow(controller).to receive(:create) do
82
- controller.send :authorize_response
77
+ 2.times { controller.send :authorize_response }
78
+ controller.render json: {}, status: :ok
83
79
  end
84
80
 
85
81
  post :create
86
82
  end
87
83
  end
84
+
85
+ describe 'when requested token introspection' do
86
+ context 'authorized using Bearer token' do
87
+ let(:client) { FactoryBot.create(:application) }
88
+ let(:access_token) { FactoryBot.create(:access_token, application: client) }
89
+
90
+ it 'responds with full token introspection' do
91
+ request.headers['Authorization'] = "Bearer #{access_token.token}"
92
+
93
+ post :introspect, params: { token: access_token.token }
94
+
95
+ should_have_json 'active', true
96
+ expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
97
+ end
98
+ end
99
+
100
+ context 'authorized using Client Authentication' do
101
+ let(:client) { FactoryBot.create(:application) }
102
+ let(:access_token) { FactoryBot.create(:access_token, application: client) }
103
+
104
+ it 'responds with full token introspection' do
105
+ request.headers['Authorization'] = basic_auth_header_for_client(client)
106
+
107
+ post :introspect, params: { token: access_token.token }
108
+
109
+ should_have_json 'active', true
110
+ expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
111
+ should_have_json 'client_id', client.uid
112
+ end
113
+ end
114
+
115
+ context 'public access token' do
116
+ let(:client) { FactoryBot.create(:application) }
117
+ let(:access_token) { FactoryBot.create(:access_token, application: nil) }
118
+
119
+ it 'responds with full token introspection' do
120
+ request.headers['Authorization'] = basic_auth_header_for_client(client)
121
+
122
+ post :introspect, params: { token: access_token.token }
123
+
124
+ should_have_json 'active', true
125
+ expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
126
+ should_have_json 'client_id', nil
127
+ end
128
+ end
129
+
130
+ context 'token was issued to a different client than is making this request' do
131
+ let(:client) { FactoryBot.create(:application) }
132
+ let(:different_client) { FactoryBot.create(:application) }
133
+ let(:access_token) { FactoryBot.create(:access_token, application: client) }
134
+
135
+ it 'responds with only active state' do
136
+ request.headers['Authorization'] = basic_auth_header_for_client(different_client)
137
+
138
+ post :introspect, params: { token: access_token.token }
139
+
140
+ expect(response).to be_successful
141
+
142
+ should_have_json 'active', false
143
+ expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
144
+ end
145
+ end
146
+
147
+ context 'using invalid credentials to authorize' do
148
+ let(:client) { double(uid: '123123', secret: '666999') }
149
+ let(:access_token) { FactoryBot.create(:access_token) }
150
+
151
+ it 'responds with invalid_client error' do
152
+ request.headers['Authorization'] = basic_auth_header_for_client(client)
153
+
154
+ post :introspect, params: { token: access_token.token }
155
+
156
+ expect(response).not_to be_successful
157
+ response_status_should_be 401
158
+
159
+ should_not_have_json 'active'
160
+ should_have_json 'error', 'invalid_client'
161
+ end
162
+ end
163
+
164
+ context 'using wrong token value' do
165
+ let(:client) { FactoryBot.create(:application) }
166
+ let(:access_token) { FactoryBot.create(:access_token, application: client) }
167
+
168
+ it 'responds with only active state' do
169
+ request.headers['Authorization'] = basic_auth_header_for_client(client)
170
+
171
+ post :introspect, params: { token: SecureRandom.hex(16) }
172
+
173
+ should_have_json 'active', false
174
+ expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
175
+ end
176
+ end
177
+
178
+ context 'when requested Access Token expired' do
179
+ let(:client) { FactoryBot.create(:application) }
180
+ let(:access_token) { FactoryBot.create(:access_token, application: client, created_at: 1.year.ago) }
181
+
182
+ it 'responds with only active state' do
183
+ request.headers['Authorization'] = basic_auth_header_for_client(client)
184
+
185
+ post :introspect, params: { token: access_token.token }
186
+
187
+ should_have_json 'active', false
188
+ expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
189
+ end
190
+ end
191
+
192
+ context 'when requested Access Token revoked' do
193
+ let(:client) { FactoryBot.create(:application) }
194
+ let(:access_token) { FactoryBot.create(:access_token, application: client, revoked_at: 1.year.ago) }
195
+
196
+ it 'responds with only active state' do
197
+ request.headers['Authorization'] = basic_auth_header_for_client(client)
198
+
199
+ post :introspect, params: { token: access_token.token }
200
+
201
+ should_have_json 'active', false
202
+ expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
203
+ end
204
+ end
205
+
206
+ context 'unauthorized (no bearer token or client credentials)' do
207
+ let(:access_token) { FactoryBot.create(:access_token) }
208
+
209
+ it 'responds with invalid_request error' do
210
+ post :introspect, params: { token: access_token.token }
211
+
212
+ expect(response).not_to be_successful
213
+ response_status_should_be 401
214
+
215
+ should_not_have_json 'active'
216
+ should_have_json 'error', 'invalid_request'
217
+ end
218
+ end
219
+ end
88
220
  end
@@ -0,0 +1,2 @@
1
+ // JS and CSS bundles
2
+ //
@@ -7,6 +7,10 @@ Dummy::Application.configure do
7
7
  # and recreated between test runs. Don't rely on the data there!
8
8
  config.cache_classes = true
9
9
 
10
+ config.assets.enabled = true
11
+ config.assets.version = '1.0'
12
+ config.assets.digest = false
13
+
10
14
  # Do not eager load code on boot. This avoids loading your whole application
11
15
  # just for the purpose of running a single test. If you are using a tool that
12
16
  # preloads Rails for running tests, you may have to set it to true.
@@ -36,9 +40,4 @@ Dummy::Application.configure do
36
40
  config.active_support.deprecation = :stderr
37
41
 
38
42
  config.eager_load = true
39
-
40
- if DOORKEEPER_ORM == :active_record
41
- config.active_record.table_name_prefix = TABLE_NAME_PREFIX.to_s
42
- config.active_record.table_name_suffix = TABLE_NAME_SUFFIX.to_s
43
- end
44
43
  end
@@ -29,6 +29,12 @@ Doorkeeper.configure do
29
29
  # Issue access tokens with refresh token (disabled by default)
30
30
  use_refresh_token
31
31
 
32
+ # Forbids creating/updating applications with arbitrary scopes that are
33
+ # not in configuration, i.e. `default_scopes` or `optional_scopes`.
34
+ # (disabled by default)
35
+ #
36
+ # enforce_configured_scopes
37
+
32
38
  # Provide support for an owner to be assigned to each registered application (disabled by default)
33
39
  # Optional parameter confirmation: true (default false) if you want to enforce ownership of
34
40
  # a registered application
@@ -82,7 +88,18 @@ Doorkeeper.configure do
82
88
  # http://tools.ietf.org/html/rfc6819#section-4.4.2
83
89
  # http://tools.ietf.org/html/rfc6819#section-4.4.3
84
90
  #
85
- # grant_flows %w(authorization_code client_credentials)
91
+ # grant_flows %w[authorization_code client_credentials]
92
+
93
+ # Hook into the strategies' request & response life-cycle in case your
94
+ # application needs advanced customization or logging:
95
+ #
96
+ # before_successful_strategy_response do |request|
97
+ # puts "BEFORE HOOK FIRED! #{request}"
98
+ # end
99
+ #
100
+ # after_successful_strategy_response do |request, response|
101
+ # puts "AFTER HOOK FIRED! #{request}, #{response}"
102
+ # end
86
103
 
87
104
  # Under some circumstances you might want to have applications auto-approved,
88
105
  # so that the user skips the authorization step.
@@ -1,6 +1,10 @@
1
1
  # Require `belongs_to` associations by default. This is a new Rails 5.0
2
2
  # default, so it is introduced as a configuration option to ensure that apps
3
3
  # made on earlier versions of Rails are not affected when upgrading.
4
- if Rails.version.to_i >= 5
4
+ if Rails::VERSION::MAJOR >= 5
5
5
  Rails.application.config.active_record.belongs_to_required_by_default = true
6
+
7
+ if Rails::VERSION::MINOR >= 2
8
+ Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
9
+ end
6
10
  end
@@ -5,5 +5,4 @@
5
5
  # Make sure the secret is at least 30 characters and all random,
6
6
  # no regular words or you'll be exposed to dictionary attacks.
7
7
  Dummy::Application.config.secret_key_base =
8
- Dummy::Application.config.secret_token =
9
8
  'c00157b5a1bb6181792f0f4a8a080485de7bab9987e6cf159dc74c4f0573345c1bfa713b5d756e1491fc0b098567e8a619e2f8d268eda86a20a720d05d633780'
@@ -1,52 +1,13 @@
1
1
  Rails.application.routes.draw do
2
2
  use_doorkeeper
3
- use_doorkeeper scope: 'scope'
4
3
 
5
- scope 'inner_space' do
6
- use_doorkeeper scope: 'scope' do
7
- controllers authorizations: 'custom_authorizations',
8
- tokens: 'custom_authorizations',
9
- applications: 'custom_authorizations',
10
- token_info: 'custom_authorizations'
11
-
12
- as authorizations: 'custom_auth',
13
- tokens: 'custom_token',
14
- token_info: 'custom_token_info'
15
- end
16
- end
17
-
18
- scope 'space' do
19
- use_doorkeeper do
20
- controllers authorizations: 'custom_authorizations',
21
- tokens: 'custom_authorizations',
22
- applications: 'custom_authorizations',
23
- token_info: 'custom_authorizations'
24
-
25
- as authorizations: 'custom_auth',
26
- tokens: 'custom_token',
27
- token_info: 'custom_token_info'
28
- end
29
- end
30
-
31
- scope 'outer_space' do
32
- use_doorkeeper do
33
- controllers authorizations: 'custom_authorizations',
34
- tokens: 'custom_authorizations',
35
- token_info: 'custom_authorizations'
36
-
37
- as authorizations: 'custom_auth',
38
- tokens: 'custom_token',
39
- token_info: 'custom_token_info'
40
-
41
- skip_controllers :tokens, :applications, :token_info
42
- end
43
- end
4
+ resources :semi_protected_resources
5
+ resources :full_protected_resources
44
6
 
45
7
  get 'metal.json' => 'metal#index'
46
8
 
47
9
  get '/callback', to: 'home#callback'
48
10
  get '/sign_in', to: 'home#sign_in'
49
- resources :semi_protected_resources
50
- resources :full_protected_resources
11
+
51
12
  root to: 'home#index'
52
13
  end
@@ -1,4 +1,6 @@
1
- class CreateUsers < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class CreateUsers < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  create_table :users do |t|
4
6
  t.string :name
@@ -1,4 +1,6 @@
1
- class AddPasswordToUsers < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddPasswordToUsers < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  add_column :users, :password, :string
4
6
  end
@@ -1,4 +1,6 @@
1
- class CreateDoorkeeperTables < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  create_table :oauth_applications do |t|
4
6
  t.string :name, null: false
@@ -1,4 +1,6 @@
1
- class AddOwnerToApplication < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddOwnerToApplication < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  add_column :oauth_applications, :owner_id, :integer, null: true
4
6
  add_column :oauth_applications, :owner_type, :string, null: true
@@ -1,4 +1,6 @@
1
- class AddPreviousRefreshTokenToAccessTokens < ActiveRecord::Migration
1
+ # frozen_string_literal: true
2
+
3
+ class AddPreviousRefreshTokenToAccessTokens < ActiveRecord::Migration[4.2]
2
4
  def change
3
5
  add_column(
4
6
  :oauth_access_tokens,
@@ -0,0 +1,6 @@
1
+ class EnablePkce < ActiveRecord::Migration[4.2]
2
+ def change
3
+ add_column :oauth_access_grants, :code_challenge, :string, null: true
4
+ add_column :oauth_access_grants, :code_challenge_method, :string, null: true
5
+ end
6
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class AddConfidentialToApplications < ActiveRecord::Migration[5.1]
4
+ def change
5
+ add_column(
6
+ :oauth_applications,
7
+ :confidential,
8
+ :boolean,
9
+ null: false,
10
+ default: true # maintaining backwards compatibility: require secrets
11
+ )
12
+ end
13
+ end
@@ -1,4 +1,3 @@
1
- # encoding: UTF-8
2
1
  # This file is auto-generated from the current state of the database. Instead
3
2
  # of editing this file, please use the migrations feature of Active Record to
4
3
  # incrementally modify your database, and then regenerate this schema definition.
@@ -11,57 +10,59 @@
11
10
  #
12
11
  # It's strongly recommended that you check this file into your version control system.
13
12
 
14
- ActiveRecord::Schema.define(version: 20160320211015) do
13
+ ActiveRecord::Schema.define(version: 20180210183654) do
15
14
 
16
15
  create_table "oauth_access_grants", force: :cascade do |t|
17
- t.integer "resource_owner_id", null: false
18
- t.integer "application_id", null: false
19
- t.string "token", null: false
20
- t.integer "expires_in", null: false
21
- t.text "redirect_uri", null: false
22
- t.datetime "created_at", null: false
16
+ t.integer "resource_owner_id", null: false
17
+ t.integer "application_id", null: false
18
+ t.string "token", null: false
19
+ t.integer "expires_in", null: false
20
+ t.text "redirect_uri", null: false
21
+ t.datetime "created_at", null: false
23
22
  t.datetime "revoked_at"
24
- t.string "scopes"
23
+ t.string "scopes"
24
+ unless ENV['WITHOUT_PKCE']
25
+ t.string "code_challenge"
26
+ t.string "code_challenge_method"
27
+ end
28
+ t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true
25
29
  end
26
30
 
27
- add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true
28
-
29
31
  create_table "oauth_access_tokens", force: :cascade do |t|
30
- t.integer "resource_owner_id"
31
- t.integer "application_id"
32
- t.string "token", null: false
33
- t.string "refresh_token"
34
- t.integer "expires_in"
32
+ t.integer "resource_owner_id"
33
+ t.integer "application_id"
34
+ t.string "token", null: false
35
+ t.string "refresh_token"
36
+ t.integer "expires_in"
35
37
  t.datetime "revoked_at"
36
- t.datetime "created_at", null: false
37
- t.string "scopes"
38
- t.string "previous_refresh_token", default: "", null: false
38
+ t.datetime "created_at", null: false
39
+ t.string "scopes"
40
+ t.string "previous_refresh_token", default: "", null: false
41
+ t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
42
+ t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
43
+ t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true
39
44
  end
40
45
 
41
- add_index "oauth_access_tokens", ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
42
- add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
43
- add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true
44
-
45
46
  create_table "oauth_applications", force: :cascade do |t|
46
- t.string "name", null: false
47
- t.string "uid", null: false
48
- t.string "secret", null: false
49
- t.text "redirect_uri", null: false
50
- t.string "scopes", default: "", null: false
51
- t.datetime "created_at"
52
- t.datetime "updated_at"
53
- t.integer "owner_id"
54
- t.string "owner_type"
47
+ t.string "name", null: false
48
+ t.string "uid", null: false
49
+ t.string "secret", null: false
50
+ t.text "redirect_uri", null: false
51
+ t.string "scopes", default: "", null: false
52
+ t.datetime "created_at", null: false
53
+ t.datetime "updated_at", null: false
54
+ t.integer "owner_id"
55
+ t.string "owner_type"
56
+ t.boolean "confidential", default: true, null: false
57
+ t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type"
58
+ t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
55
59
  end
56
60
 
57
- add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type"
58
- add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true
59
-
60
61
  create_table "users", force: :cascade do |t|
61
- t.string "name"
62
+ t.string "name"
62
63
  t.datetime "created_at"
63
64
  t.datetime "updated_at"
64
- t.string "password"
65
+ t.string "password"
65
66
  end
66
67
 
67
68
  end
data/spec/factories.rb CHANGED
@@ -1,4 +1,4 @@
1
- FactoryGirl.define do
1
+ FactoryBot.define do
2
2
  factory :access_grant, class: Doorkeeper::AccessGrant do
3
3
  sequence(:resource_owner_id) { |n| n }
4
4
  application
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
  require 'generators/doorkeeper/application_owner_generator'
3
3
 
4
4
  describe 'Doorkeeper::ApplicationOwnerGenerator' do
@@ -10,13 +10,32 @@ describe 'Doorkeeper::ApplicationOwnerGenerator' do
10
10
  describe 'after running the generator' do
11
11
  before :each do
12
12
  prepare_destination
13
- FileUtils.mkdir(::File.expand_path('config', Pathname(destination_root)))
14
- FileUtils.copy_file(::File.expand_path('../templates/routes.rb', __FILE__), ::File.expand_path('config/routes.rb', Pathname.new(destination_root)))
15
- run_generator
16
13
  end
17
14
 
18
- it 'creates a migration' do
19
- assert_migration 'db/migrate/add_owner_to_application.rb'
15
+ context 'pre Rails 5.0.0' do
16
+ it 'creates a migration with no version specifier' do
17
+ stub_const("ActiveRecord::VERSION::MAJOR", 4)
18
+ stub_const("ActiveRecord::VERSION::MINOR", 2)
19
+
20
+ run_generator
21
+
22
+ assert_migration 'db/migrate/add_owner_to_application.rb' do |migration|
23
+ assert migration.include?("ActiveRecord::Migration\n")
24
+ end
25
+ end
26
+ end
27
+
28
+ context 'post Rails 5.0.0' do
29
+ it 'creates a migration with a version specifier' do
30
+ stub_const("ActiveRecord::VERSION::MAJOR", 5)
31
+ stub_const("ActiveRecord::VERSION::MINOR", 0)
32
+
33
+ run_generator
34
+
35
+ assert_migration 'db/migrate/add_owner_to_application.rb' do |migration|
36
+ assert migration.include?("ActiveRecord::Migration[5.0]\n")
37
+ end
38
+ end
20
39
  end
21
40
  end
22
41
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+ require 'generators/doorkeeper/confidential_applications_generator'
5
+
6
+ describe 'Doorkeeper::ConfidentialApplicationsGenerator' do
7
+ include GeneratorSpec::TestCase
8
+
9
+ tests Doorkeeper::ConfidentialApplicationsGenerator
10
+ destination ::File.expand_path('../tmp/dummy', __FILE__)
11
+
12
+ describe 'after running the generator' do
13
+ before :each do
14
+ prepare_destination
15
+ end
16
+
17
+ context 'pre Rails 5.0.0' do
18
+ it 'creates a migration with no version specifier' do
19
+ stub_const("ActiveRecord::VERSION::MAJOR", 4)
20
+ stub_const("ActiveRecord::VERSION::MINOR", 2)
21
+
22
+ run_generator
23
+
24
+ assert_migration 'db/migrate/add_confidential_to_applications.rb' do |migration|
25
+ assert migration.include?("ActiveRecord::Migration\n")
26
+ assert migration.include?(':confidential')
27
+ end
28
+ end
29
+ end
30
+
31
+ context 'post Rails 5.0.0' do
32
+ it 'creates a migration with a version specifier' do
33
+ stub_const("ActiveRecord::VERSION::MAJOR", 5)
34
+ stub_const("ActiveRecord::VERSION::MINOR", 0)
35
+
36
+ run_generator
37
+
38
+ assert_migration 'db/migrate/add_confidential_to_applications.rb' do |migration|
39
+ assert migration.include?("ActiveRecord::Migration[5.0]\n")
40
+ assert migration.include?(':confidential')
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,4 +1,4 @@
1
- require 'spec_helper_integration'
1
+ require 'spec_helper'
2
2
  require 'generators/doorkeeper/install_generator'
3
3
 
4
4
  describe 'Doorkeeper::InstallGenerator' do