doorkeeper 5.3.3 → 5.6.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (247) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +216 -9
  3. data/README.md +30 -21
  4. data/app/controllers/doorkeeper/application_controller.rb +1 -0
  5. data/app/controllers/doorkeeper/applications_controller.rb +4 -4
  6. data/app/controllers/doorkeeper/authorizations_controller.rb +66 -22
  7. data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
  8. data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
  9. data/app/controllers/doorkeeper/tokens_controller.rb +73 -25
  10. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  11. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  12. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  13. data/app/views/doorkeeper/authorizations/error.html.erb +3 -1
  14. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  15. data/app/views/doorkeeper/authorizations/new.html.erb +16 -14
  16. data/config/locales/en.yml +9 -2
  17. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  18. data/lib/doorkeeper/config/option.rb +26 -14
  19. data/lib/doorkeeper/config/validations.rb +53 -0
  20. data/lib/doorkeeper/config.rb +182 -134
  21. data/lib/doorkeeper/engine.rb +10 -3
  22. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  23. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  24. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  25. data/lib/doorkeeper/grant_flow.rb +45 -0
  26. data/lib/doorkeeper/grape/helpers.rb +1 -1
  27. data/lib/doorkeeper/helpers/controller.rb +9 -5
  28. data/lib/doorkeeper/models/access_grant_mixin.rb +22 -19
  29. data/lib/doorkeeper/models/access_token_mixin.rb +115 -52
  30. data/lib/doorkeeper/models/application_mixin.rb +5 -4
  31. data/lib/doorkeeper/models/concerns/expirable.rb +1 -1
  32. data/lib/doorkeeper/models/concerns/expiration_time_sql_math.rb +88 -0
  33. data/lib/doorkeeper/models/concerns/polymorphic_resource_owner.rb +30 -0
  34. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  35. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  36. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  37. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  38. data/lib/doorkeeper/oauth/authorization/code.rb +25 -6
  39. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  40. data/lib/doorkeeper/oauth/authorization/token.rb +24 -16
  41. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  42. data/lib/doorkeeper/oauth/authorization_code_request.rb +34 -21
  43. data/lib/doorkeeper/oauth/base_request.rb +19 -26
  44. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  45. data/lib/doorkeeper/oauth/client.rb +1 -1
  46. data/lib/doorkeeper/oauth/client_credentials/creator.rb +31 -15
  47. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +4 -2
  48. data/lib/doorkeeper/oauth/client_credentials/validator.rb +5 -4
  49. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  50. data/lib/doorkeeper/oauth/code_request.rb +4 -4
  51. data/lib/doorkeeper/oauth/code_response.rb +22 -12
  52. data/lib/doorkeeper/oauth/error_response.rb +7 -9
  53. data/lib/doorkeeper/oauth/forbidden_token_response.rb +2 -1
  54. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +2 -8
  55. data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -2
  56. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +4 -22
  57. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  58. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  59. data/lib/doorkeeper/oauth/password_access_token_request.rb +26 -8
  60. data/lib/doorkeeper/oauth/pre_authorization.rb +65 -33
  61. data/lib/doorkeeper/oauth/refresh_token_request.rb +42 -25
  62. data/lib/doorkeeper/oauth/token.rb +5 -6
  63. data/lib/doorkeeper/oauth/token_introspection.rb +8 -12
  64. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  65. data/lib/doorkeeper/oauth/token_response.rb +2 -3
  66. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +14 -4
  67. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +34 -4
  68. data/lib/doorkeeper/orm/active_record/mixins/application.rb +28 -5
  69. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +6 -1
  70. data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +5 -2
  71. data/lib/doorkeeper/orm/active_record.rb +30 -38
  72. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  73. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  74. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  75. data/lib/doorkeeper/rails/routes.rb +25 -22
  76. data/lib/doorkeeper/rake/db.rake +3 -3
  77. data/lib/doorkeeper/request/password.rb +1 -0
  78. data/lib/doorkeeper/request/refresh_token.rb +2 -1
  79. data/lib/doorkeeper/request/strategy.rb +2 -2
  80. data/lib/doorkeeper/request.rb +49 -12
  81. data/lib/doorkeeper/server.rb +4 -4
  82. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  83. data/lib/doorkeeper/version.rb +2 -6
  84. data/lib/doorkeeper.rb +181 -81
  85. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  86. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  87. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  88. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  89. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  90. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  91. data/lib/generators/doorkeeper/templates/initializer.rb +73 -17
  92. data/lib/generators/doorkeeper/templates/migration.rb.erb +28 -9
  93. metadata +48 -316
  94. data/Appraisals +0 -40
  95. data/CODE_OF_CONDUCT.md +0 -46
  96. data/CONTRIBUTING.md +0 -49
  97. data/Dangerfile +0 -67
  98. data/Dockerfile +0 -29
  99. data/Gemfile +0 -25
  100. data/NEWS.md +0 -1
  101. data/RELEASING.md +0 -11
  102. data/Rakefile +0 -28
  103. data/SECURITY.md +0 -15
  104. data/UPGRADE.md +0 -2
  105. data/bin/console +0 -16
  106. data/doorkeeper.gemspec +0 -42
  107. data/gemfiles/rails_5_0.gemfile +0 -18
  108. data/gemfiles/rails_5_1.gemfile +0 -18
  109. data/gemfiles/rails_5_2.gemfile +0 -18
  110. data/gemfiles/rails_6_0.gemfile +0 -18
  111. data/gemfiles/rails_master.gemfile +0 -18
  112. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  113. data/spec/controllers/applications_controller_spec.rb +0 -274
  114. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  115. data/spec/controllers/protected_resources_controller_spec.rb +0 -361
  116. data/spec/controllers/token_info_controller_spec.rb +0 -50
  117. data/spec/controllers/tokens_controller_spec.rb +0 -498
  118. data/spec/dummy/Rakefile +0 -9
  119. data/spec/dummy/app/assets/config/manifest.js +0 -2
  120. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  121. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  122. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  123. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  124. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  125. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  126. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  127. data/spec/dummy/app/models/user.rb +0 -7
  128. data/spec/dummy/app/views/home/index.html.erb +0 -0
  129. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  130. data/spec/dummy/config/application.rb +0 -49
  131. data/spec/dummy/config/boot.rb +0 -7
  132. data/spec/dummy/config/database.yml +0 -15
  133. data/spec/dummy/config/environment.rb +0 -5
  134. data/spec/dummy/config/environments/development.rb +0 -31
  135. data/spec/dummy/config/environments/production.rb +0 -64
  136. data/spec/dummy/config/environments/test.rb +0 -45
  137. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  138. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  139. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  140. data/spec/dummy/config/initializers/session_store.rb +0 -10
  141. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  142. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  143. data/spec/dummy/config/routes.rb +0 -13
  144. data/spec/dummy/config.ru +0 -6
  145. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  146. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  147. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  148. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  149. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  150. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  151. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  152. data/spec/dummy/db/schema.rb +0 -68
  153. data/spec/dummy/public/404.html +0 -26
  154. data/spec/dummy/public/422.html +0 -26
  155. data/spec/dummy/public/500.html +0 -26
  156. data/spec/dummy/public/favicon.ico +0 -0
  157. data/spec/dummy/script/rails +0 -9
  158. data/spec/factories.rb +0 -30
  159. data/spec/generators/application_owner_generator_spec.rb +0 -28
  160. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  161. data/spec/generators/install_generator_spec.rb +0 -36
  162. data/spec/generators/migration_generator_spec.rb +0 -28
  163. data/spec/generators/pkce_generator_spec.rb +0 -28
  164. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  165. data/spec/generators/templates/routes.rb +0 -4
  166. data/spec/generators/views_generator_spec.rb +0 -29
  167. data/spec/grape/grape_integration_spec.rb +0 -137
  168. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  169. data/spec/lib/config_spec.rb +0 -809
  170. data/spec/lib/doorkeeper_spec.rb +0 -27
  171. data/spec/lib/models/expirable_spec.rb +0 -61
  172. data/spec/lib/models/reusable_spec.rb +0 -40
  173. data/spec/lib/models/revocable_spec.rb +0 -59
  174. data/spec/lib/models/scopes_spec.rb +0 -53
  175. data/spec/lib/models/secret_storable_spec.rb +0 -135
  176. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  177. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -170
  178. data/spec/lib/oauth/base_request_spec.rb +0 -224
  179. data/spec/lib/oauth/base_response_spec.rb +0 -45
  180. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  181. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -134
  182. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  183. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  184. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  185. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -107
  186. data/spec/lib/oauth/client_spec.rb +0 -38
  187. data/spec/lib/oauth/code_request_spec.rb +0 -46
  188. data/spec/lib/oauth/code_response_spec.rb +0 -32
  189. data/spec/lib/oauth/error_response_spec.rb +0 -64
  190. data/spec/lib/oauth/error_spec.rb +0 -21
  191. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
  192. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
  193. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  194. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  195. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
  196. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
  197. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -190
  198. data/spec/lib/oauth/pre_authorization_spec.rb +0 -223
  199. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  200. data/spec/lib/oauth/scopes_spec.rb +0 -146
  201. data/spec/lib/oauth/token_request_spec.rb +0 -157
  202. data/spec/lib/oauth/token_response_spec.rb +0 -84
  203. data/spec/lib/oauth/token_spec.rb +0 -156
  204. data/spec/lib/request/strategy_spec.rb +0 -54
  205. data/spec/lib/secret_storing/base_spec.rb +0 -60
  206. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  207. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  208. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  209. data/spec/lib/server_spec.rb +0 -49
  210. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  211. data/spec/models/doorkeeper/access_grant_spec.rb +0 -161
  212. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  213. data/spec/models/doorkeeper/application_spec.rb +0 -482
  214. data/spec/requests/applications/applications_request_spec.rb +0 -259
  215. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  216. data/spec/requests/endpoints/authorization_spec.rb +0 -91
  217. data/spec/requests/endpoints/token_spec.rb +0 -75
  218. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  219. data/spec/requests/flows/authorization_code_spec.rb +0 -525
  220. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  221. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  222. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  223. data/spec/requests/flows/password_spec.rb +0 -316
  224. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  225. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  226. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  227. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  228. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  229. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  230. data/spec/routing/default_routes_spec.rb +0 -41
  231. data/spec/routing/scoped_routes_spec.rb +0 -47
  232. data/spec/spec_helper.rb +0 -54
  233. data/spec/spec_helper_integration.rb +0 -4
  234. data/spec/support/dependencies/factory_bot.rb +0 -4
  235. data/spec/support/doorkeeper_rspec.rb +0 -22
  236. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  237. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  238. data/spec/support/helpers/config_helper.rb +0 -11
  239. data/spec/support/helpers/model_helper.rb +0 -78
  240. data/spec/support/helpers/request_spec_helper.rb +0 -110
  241. data/spec/support/helpers/url_helper.rb +0 -62
  242. data/spec/support/orm/active_record.rb +0 -5
  243. data/spec/support/shared/controllers_shared_context.rb +0 -133
  244. data/spec/support/shared/hashing_shared_context.rb +0 -36
  245. data/spec/support/shared/models_shared_examples.rb +0 -54
  246. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  247. data/spec/version/version_spec.rb +0 -17
@@ -1,498 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- describe Doorkeeper::TokensController do
6
- let(:client) { FactoryBot.create :application }
7
- let!(:user) { User.create!(name: "Joe", password: "sekret") }
8
-
9
- before do
10
- Doorkeeper.configure do
11
- resource_owner_from_credentials do
12
- User.first
13
- end
14
- end
15
-
16
- allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["password"])
17
- end
18
-
19
- subject { JSON.parse(response.body) }
20
-
21
- describe "POST #create" do
22
- before do
23
- post :create, params: {
24
- client_id: client.uid,
25
- client_secret: client.secret,
26
- grant_type: "password",
27
- }
28
- end
29
-
30
- it "responds after authorization" do
31
- expect(response).to be_successful
32
- end
33
-
34
- it "includes access token in response" do
35
- expect(subject["access_token"]).to eq(Doorkeeper::AccessToken.first.token)
36
- end
37
-
38
- it "includes token type in response" do
39
- expect(subject["token_type"]).to eq("Bearer")
40
- end
41
-
42
- it "includes token expiration in response" do
43
- expect(subject["expires_in"].to_i).to eq(Doorkeeper.configuration.access_token_expires_in)
44
- end
45
-
46
- it "issues the token for the current client" do
47
- expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
48
- end
49
-
50
- it "issues the token for the current resource owner" do
51
- expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
52
- end
53
- end
54
-
55
- describe "POST #create with errors" do
56
- before do
57
- post :create, params: {
58
- client_id: client.uid,
59
- client_secret: "invalid",
60
- grant_type: "password",
61
- }
62
- end
63
-
64
- it "responds after authorization" do
65
- expect(response).to be_unauthorized
66
- end
67
-
68
- it "include error in response" do
69
- expect(subject["error"]).to eq("invalid_client")
70
- end
71
-
72
- it "include error_description in response" do
73
- expect(subject["error_description"]).to be
74
- end
75
-
76
- it "does not include access token in response" do
77
- expect(subject["access_token"]).to be_nil
78
- end
79
-
80
- it "does not include token type in response" do
81
- expect(subject["token_type"]).to be_nil
82
- end
83
-
84
- it "does not include token expiration in response" do
85
- expect(subject["expires_in"]).to be_nil
86
- end
87
-
88
- it "does not issue any access token" do
89
- expect(Doorkeeper::AccessToken.all).to be_empty
90
- end
91
- end
92
-
93
- describe "POST #create with callbacks" do
94
- after do
95
- client.update_attribute :redirect_uri, "urn:ietf:wg:oauth:2.0:oob"
96
- end
97
-
98
- describe "when successful" do
99
- after do
100
- post :create, params: {
101
- client_id: client.uid,
102
- client_secret: client.secret,
103
- grant_type: "password",
104
- }
105
- end
106
-
107
- it "should call :before_successful_authorization callback" do
108
- expect(Doorkeeper.configuration)
109
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
110
- end
111
-
112
- it "should call :after_successful_authorization callback" do
113
- expect(Doorkeeper.configuration)
114
- .to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
115
- end
116
- end
117
-
118
- describe "with errors" do
119
- after do
120
- post :create, params: {
121
- client_id: client.uid,
122
- client_secret: "invalid",
123
- grant_type: "password",
124
- }
125
- end
126
-
127
- it "should call :before_successful_authorization callback" do
128
- expect(Doorkeeper.configuration)
129
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
130
- end
131
-
132
- it "should not call :after_successful_authorization callback" do
133
- expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
134
- end
135
- end
136
- end
137
-
138
- describe "POST #create with custom error" do
139
- it "returns the error response with a custom message" do
140
- # I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
141
- custom_message = "my_message"
142
- allow(I18n).to receive(:translate)
143
- .with(
144
- custom_message,
145
- hash_including(scope: %i[doorkeeper errors messages]),
146
- )
147
- .and_return("Authorization custom message")
148
-
149
- doorkeeper_error = Doorkeeper::Errors::DoorkeeperError.new(custom_message)
150
-
151
- strategy = double(:strategy)
152
- request = double(token_request: strategy)
153
- allow(strategy).to receive(:authorize).and_raise(doorkeeper_error)
154
- allow(controller).to receive(:server).and_return(request)
155
-
156
- post :create
157
-
158
- expected_response_body = {
159
- "error" => custom_message,
160
- "error_description" => "Authorization custom message",
161
- }
162
- expect(response.status).to eq 400
163
- expect(response.headers["WWW-Authenticate"]).to match(/Bearer/)
164
- expect(JSON.parse(response.body)).to eq expected_response_body
165
- end
166
- end
167
-
168
- # http://tools.ietf.org/html/rfc7009#section-2.2
169
- describe "POST #revoke" do
170
- let(:client) { FactoryBot.create(:application) }
171
- let(:access_token) { FactoryBot.create(:access_token, application: client) }
172
-
173
- context "when associated app is public" do
174
- let(:client) { FactoryBot.create(:application, confidential: false) }
175
-
176
- it "returns 200" do
177
- post :revoke, params: { token: access_token.token }
178
-
179
- expect(response.status).to eq 200
180
- end
181
-
182
- it "revokes the access token" do
183
- post :revoke, params: { token: access_token.token }
184
-
185
- expect(access_token.reload).to have_attributes(revoked?: true)
186
- end
187
- end
188
-
189
- context "when associated app is confidential" do
190
- let(:client) { FactoryBot.create(:application, confidential: true) }
191
- let(:oauth_client) { Doorkeeper::OAuth::Client.new(client) }
192
-
193
- before(:each) do
194
- allow_any_instance_of(Doorkeeper::Server).to receive(:client) { oauth_client }
195
- end
196
-
197
- it "returns 200" do
198
- post :revoke, params: { token: access_token.token }
199
-
200
- expect(response.status).to eq 200
201
- end
202
-
203
- it "revokes the access token" do
204
- post :revoke, params: { token: access_token.token }
205
-
206
- expect(access_token.reload).to have_attributes(revoked?: true)
207
- end
208
-
209
- context "when authorization fails" do
210
- let(:some_other_client) { FactoryBot.create(:application, confidential: true) }
211
- let(:oauth_client) { Doorkeeper::OAuth::Client.new(some_other_client) }
212
-
213
- it "returns 403" do
214
- post :revoke, params: { token: access_token.token }
215
-
216
- expect(response.status).to eq 403
217
- end
218
-
219
- it "does not revoke the access token" do
220
- post :revoke, params: { token: access_token.token }
221
-
222
- expect(access_token.reload).to have_attributes(revoked?: false)
223
- end
224
- end
225
- end
226
- end
227
-
228
- describe "POST #introspect" do
229
- let(:client) { FactoryBot.create(:application) }
230
- let(:access_token) { FactoryBot.create(:access_token, application: client) }
231
- let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
232
-
233
- context "authorized using valid Bearer token" do
234
- it "responds with full token introspection" do
235
- request.headers["Authorization"] = "Bearer #{access_token.token}"
236
-
237
- post :introspect, params: { token: token_for_introspection.token }
238
-
239
- should_have_json "active", true
240
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
241
- end
242
- end
243
-
244
- context "authorized using Client Credentials of the client that token is issued to" do
245
- it "responds with full token introspection" do
246
- request.headers["Authorization"] = basic_auth_header_for_client(client)
247
-
248
- post :introspect, params: { token: token_for_introspection.token }
249
-
250
- should_have_json "active", true
251
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
252
- should_have_json "client_id", client.uid
253
- end
254
- end
255
-
256
- context "configured token introspection disabled" do
257
- before do
258
- Doorkeeper.configure do
259
- orm DOORKEEPER_ORM
260
- allow_token_introspection false
261
- end
262
- end
263
-
264
- it "responds with invalid_token error" do
265
- request.headers["Authorization"] = "Bearer #{access_token.token}"
266
-
267
- post :introspect, params: { token: token_for_introspection.token }
268
-
269
- response_status_should_be 401
270
-
271
- should_not_have_json "active"
272
- should_have_json "error", "invalid_token"
273
- end
274
- end
275
-
276
- context "using custom introspection response" do
277
- before do
278
- Doorkeeper.configure do
279
- orm DOORKEEPER_ORM
280
- custom_introspection_response do |_token, _context|
281
- {
282
- sub: "Z5O3upPC88QrAjx00dis",
283
- aud: "https://protected.example.net/resource",
284
- }
285
- end
286
- end
287
- end
288
-
289
- it "responds with full token introspection" do
290
- request.headers["Authorization"] = "Bearer #{access_token.token}"
291
-
292
- post :introspect, params: { token: token_for_introspection.token }
293
-
294
- expect(json_response).to include("client_id", "token_type", "exp", "iat", "sub", "aud")
295
- should_have_json "sub", "Z5O3upPC88QrAjx00dis"
296
- should_have_json "aud", "https://protected.example.net/resource"
297
- end
298
- end
299
-
300
- context "public access token" do
301
- let(:token_for_introspection) { FactoryBot.create(:access_token, application: nil) }
302
-
303
- it "responds with full token introspection" do
304
- request.headers["Authorization"] = basic_auth_header_for_client(client)
305
-
306
- post :introspect, params: { token: token_for_introspection.token }
307
-
308
- should_have_json "active", true
309
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
310
- should_have_json "client_id", nil
311
- end
312
- end
313
-
314
- context "token was issued to a different client than is making this request" do
315
- let(:different_client) { FactoryBot.create(:application) }
316
-
317
- it "responds with only active state" do
318
- request.headers["Authorization"] = basic_auth_header_for_client(different_client)
319
-
320
- post :introspect, params: { token: token_for_introspection.token }
321
-
322
- expect(response).to be_successful
323
-
324
- should_have_json "active", false
325
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
326
- end
327
- end
328
-
329
- context "introspection request authorized by a client and allow_token_introspection is true" do
330
- let(:different_client) { FactoryBot.create(:application) }
331
-
332
- before do
333
- allow(Doorkeeper.configuration).to receive(:allow_token_introspection).and_return(proc do
334
- true
335
- end)
336
- end
337
-
338
- it "responds with full token introspection" do
339
- request.headers["Authorization"] = basic_auth_header_for_client(different_client)
340
-
341
- post :introspect, params: { token: token_for_introspection.token }
342
-
343
- should_have_json "active", true
344
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
345
- should_have_json "client_id", client.uid
346
- end
347
- end
348
-
349
- context "allow_token_introspection requires authorized token with special scope" do
350
- let(:access_token) { FactoryBot.create(:access_token, scopes: "introspection") }
351
-
352
- before do
353
- allow(Doorkeeper.configuration).to receive(:allow_token_introspection).and_return(proc do |_token, _client, authorized_token|
354
- authorized_token.scopes.include?("introspection")
355
- end)
356
- end
357
-
358
- it "responds with full token introspection if authorized token has introspection scope" do
359
- request.headers["Authorization"] = "Bearer #{access_token.token}"
360
-
361
- post :introspect, params: { token: token_for_introspection.token }
362
-
363
- should_have_json "active", true
364
- expect(json_response).to include("client_id", "token_type", "exp", "iat")
365
- end
366
-
367
- it "responds with invalid_token error if authorized token doesn't have introspection scope" do
368
- access_token.update(scopes: "read write")
369
-
370
- request.headers["Authorization"] = "Bearer #{access_token.token}"
371
-
372
- post :introspect, params: { token: token_for_introspection.token }
373
-
374
- response_status_should_be 401
375
-
376
- should_not_have_json "active"
377
- should_have_json "error", "invalid_token"
378
- end
379
- end
380
-
381
- context "authorized using invalid Bearer token" do
382
- let(:access_token) do
383
- FactoryBot.create(:access_token, application: client, revoked_at: 1.day.ago)
384
- end
385
-
386
- it "responds with invalid_token error" do
387
- request.headers["Authorization"] = "Bearer #{access_token.token}"
388
-
389
- post :introspect, params: { token: token_for_introspection.token }
390
-
391
- response_status_should_be 401
392
-
393
- should_not_have_json "active"
394
- should_have_json "error", "invalid_token"
395
- end
396
- end
397
-
398
- context "authorized using the Bearer token that need to be introspected" do
399
- it "responds with invalid token error" do
400
- request.headers["Authorization"] = "Bearer #{access_token.token}"
401
-
402
- post :introspect, params: { token: access_token.token }
403
-
404
- response_status_should_be 401
405
-
406
- should_not_have_json "active"
407
- should_have_json "error", "invalid_token"
408
- end
409
- end
410
-
411
- context "using invalid credentials to authorize" do
412
- let(:client) { double(uid: "123123", secret: "666999") }
413
- let(:access_token) { FactoryBot.create(:access_token) }
414
-
415
- it "responds with invalid_client error" do
416
- request.headers["Authorization"] = basic_auth_header_for_client(client)
417
-
418
- post :introspect, params: { token: access_token.token }
419
-
420
- expect(response).not_to be_successful
421
- response_status_should_be 401
422
-
423
- should_not_have_json "active"
424
- should_have_json "error", "invalid_client"
425
- end
426
- end
427
-
428
- context "using wrong token value" do
429
- context "authorized using client credentials" do
430
- it "responds with only active state" do
431
- request.headers["Authorization"] = basic_auth_header_for_client(client)
432
-
433
- post :introspect, params: { token: SecureRandom.hex(16) }
434
-
435
- should_have_json "active", false
436
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
437
- end
438
- end
439
-
440
- context "authorized using valid Bearer token" do
441
- it "responds with invalid_token error" do
442
- request.headers["Authorization"] = "Bearer #{access_token.token}"
443
-
444
- post :introspect, params: { token: SecureRandom.hex(16) }
445
-
446
- response_status_should_be 401
447
-
448
- should_not_have_json "active"
449
- should_have_json "error", "invalid_token"
450
- end
451
- end
452
- end
453
-
454
- context "when requested access token expired" do
455
- let(:token_for_introspection) do
456
- FactoryBot.create(:access_token, application: client, created_at: 1.year.ago)
457
- end
458
-
459
- it "responds with only active state" do
460
- request.headers["Authorization"] = basic_auth_header_for_client(client)
461
-
462
- post :introspect, params: { token: token_for_introspection.token }
463
-
464
- should_have_json "active", false
465
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
466
- end
467
- end
468
-
469
- context "when requested Access Token revoked" do
470
- let(:token_for_introspection) do
471
- FactoryBot.create(:access_token, application: client, revoked_at: 1.year.ago)
472
- end
473
-
474
- it "responds with only active state" do
475
- request.headers["Authorization"] = basic_auth_header_for_client(client)
476
-
477
- post :introspect, params: { token: token_for_introspection.token }
478
-
479
- should_have_json "active", false
480
- expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
481
- end
482
- end
483
-
484
- context "unauthorized (no bearer token or client credentials)" do
485
- let(:token_for_introspection) { FactoryBot.create(:access_token) }
486
-
487
- it "responds with invalid_request error" do
488
- post :introspect, params: { token: token_for_introspection.token }
489
-
490
- expect(response).not_to be_successful
491
- response_status_should_be 400
492
-
493
- should_not_have_json "active"
494
- should_have_json "error", "invalid_request"
495
- end
496
- end
497
- end
498
- end
data/spec/dummy/Rakefile DELETED
@@ -1,9 +0,0 @@
1
- #!/usr/bin/env rake
2
- # frozen_string_literal: true
3
-
4
- # Add your own tasks in files placed in lib/tasks ending in .rake,
5
- # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
6
-
7
- require File.expand_path("config/application", __dir__)
8
-
9
- Dummy::Application.load_tasks
@@ -1,2 +0,0 @@
1
- // JS and CSS bundles
2
- //
@@ -1,5 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class ApplicationController < ActionController::Base
4
- protect_from_forgery with: :exception
5
- end
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class CustomAuthorizationsController < ::ApplicationController
4
- %w[index show new create edit update destroy].each do |action|
5
- define_method action do
6
- render nothing: true
7
- end
8
- end
9
- end
@@ -1,14 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class FullProtectedResourcesController < ApplicationController
4
- before_action -> { doorkeeper_authorize! :write, :admin }, only: :show
5
- before_action :doorkeeper_authorize!, only: :index
6
-
7
- def index
8
- render plain: "index"
9
- end
10
-
11
- def show
12
- render plain: "show"
13
- end
14
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class HomeController < ApplicationController
4
- def index; end
5
-
6
- def sign_in
7
- session[:user_id] = if Rails.env.development?
8
- User.first || User.create!(name: "Joe", password: "sekret")
9
- else
10
- User.first
11
- end
12
- redirect_to "/"
13
- end
14
-
15
- def callback
16
- render plain: "ok"
17
- end
18
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class MetalController < ActionController::Metal
4
- include AbstractController::Callbacks
5
- include ActionController::Head
6
- include Doorkeeper::Rails::Helpers
7
-
8
- before_action :doorkeeper_authorize!
9
-
10
- def index
11
- self.response_body = { ok: true }.to_json
12
- end
13
- end
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class SemiProtectedResourcesController < ApplicationController
4
- before_action :doorkeeper_authorize!, only: :index
5
-
6
- def index
7
- render plain: "protected index"
8
- end
9
-
10
- def show
11
- render plain: "non protected show"
12
- end
13
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module ApplicationHelper
4
- def current_user
5
- @current_user ||= User.find_by_id(session[:user_id])
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class User < ActiveRecord::Base
4
- def self.authenticate!(name, password)
5
- User.where(name: name, password: password).first
6
- end
7
- end
File without changes
@@ -1,14 +0,0 @@
1
- <!DOCTYPE html>
2
- <html>
3
- <head>
4
- <title>Dummy</title>
5
- <%= csrf_meta_tags %>
6
- </head>
7
- <body>
8
-
9
- <%= link_to "Sign in", '/sign_in' %>
10
-
11
- <%= yield %>
12
-
13
- </body>
14
- </html>
@@ -1,49 +0,0 @@
1
- require File.expand_path('boot', __dir__)
2
-
3
- require "rails"
4
-
5
- %w[
6
- action_controller/railtie
7
- action_view/railtie
8
- action_cable/engine
9
- sprockets/railtie
10
- ].each do |railtie|
11
- begin
12
- require railtie
13
- rescue LoadError => e
14
- puts "Error loading '#{railtie}' (#{e.message})"
15
- end
16
- end
17
-
18
- Bundler.require(*Rails.groups)
19
-
20
- require 'yaml'
21
-
22
- orm = if DOORKEEPER_ORM =~ /mongoid/
23
- Mongoid.load!(File.join(File.dirname(File.expand_path(__FILE__)), "#{DOORKEEPER_ORM}.yml"))
24
- :mongoid
25
- else
26
- DOORKEEPER_ORM
27
- end
28
- require "#{orm}/railtie"
29
-
30
- module Dummy
31
- class Application < Rails::Application
32
- if Rails.gem_version < Gem::Version.new('5.1')
33
- config.action_controller.per_form_csrf_tokens = true
34
- config.action_controller.forgery_protection_origin_check = true
35
-
36
- ActiveSupport.to_time_preserves_timezone = true
37
-
38
- config.active_record.belongs_to_required_by_default = true
39
-
40
- config.ssl_options = { hsts: { subdomains: true } }
41
- else
42
- config.load_defaults "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
43
- end
44
-
45
- # Settings in config/environments/* take precedence over those specified here.
46
- # Application configuration should go into files in config/initializers
47
- # -- all .rb files in that directory are automatically loaded.
48
- end
49
- end
@@ -1,7 +0,0 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
3
-
4
- orm = ENV['BUNDLE_GEMFILE'].match(/Gemfile\.(.+)\.rb/)
5
- DOORKEEPER_ORM = (orm && orm[1]) || :active_record unless defined?(DOORKEEPER_ORM)
6
-
7
- $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)