doorkeeper 5.3.0 → 5.4.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 (225) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -1
  3. data/README.md +6 -4
  4. data/app/controllers/doorkeeper/applications_controller.rb +7 -7
  5. data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
  6. data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
  7. data/app/controllers/doorkeeper/tokens_controller.rb +57 -20
  8. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  9. data/app/views/doorkeeper/applications/show.html.erb +19 -2
  10. data/config/locales/en.yml +3 -1
  11. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  12. data/lib/doorkeeper/config/option.rb +28 -14
  13. data/lib/doorkeeper/config.rb +65 -35
  14. data/lib/doorkeeper/engine.rb +1 -1
  15. data/lib/doorkeeper/grape/helpers.rb +1 -1
  16. data/lib/doorkeeper/helpers/controller.rb +4 -4
  17. data/lib/doorkeeper/models/access_grant_mixin.rb +20 -16
  18. data/lib/doorkeeper/models/access_token_mixin.rb +110 -46
  19. data/lib/doorkeeper/models/application_mixin.rb +5 -4
  20. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  21. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  22. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  23. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  24. data/lib/doorkeeper/oauth/authorization/code.rb +15 -6
  25. data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
  26. data/lib/doorkeeper/oauth/authorization/token.rb +8 -12
  27. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  28. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
  29. data/lib/doorkeeper/oauth/base_request.rb +11 -19
  30. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  31. data/lib/doorkeeper/oauth/client.rb +1 -1
  32. data/lib/doorkeeper/oauth/client_credentials/creator.rb +26 -8
  33. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  34. data/lib/doorkeeper/oauth/client_credentials/validator.rb +4 -2
  35. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  36. data/lib/doorkeeper/oauth/code_request.rb +3 -3
  37. data/lib/doorkeeper/oauth/code_response.rb +6 -2
  38. data/lib/doorkeeper/oauth/error_response.rb +2 -4
  39. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
  40. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  41. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  42. data/lib/doorkeeper/oauth/password_access_token_request.rb +4 -6
  43. data/lib/doorkeeper/oauth/pre_authorization.rb +36 -30
  44. data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
  45. data/lib/doorkeeper/oauth/token.rb +5 -6
  46. data/lib/doorkeeper/oauth/token_introspection.rb +4 -8
  47. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  48. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  49. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +8 -3
  50. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +7 -3
  51. data/lib/doorkeeper/orm/active_record/mixins/application.rb +69 -10
  52. data/lib/doorkeeper/orm/active_record.rb +10 -2
  53. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  54. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  55. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  56. data/lib/doorkeeper/rails/routes.rb +13 -17
  57. data/lib/doorkeeper/request/refresh_token.rb +2 -1
  58. data/lib/doorkeeper/request/strategy.rb +2 -2
  59. data/lib/doorkeeper/server.rb +4 -4
  60. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  61. data/lib/doorkeeper/version.rb +1 -1
  62. data/lib/doorkeeper.rb +106 -79
  63. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  64. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  65. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +2 -0
  66. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  67. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  68. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  69. data/lib/generators/doorkeeper/templates/initializer.rb +47 -3
  70. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  71. metadata +12 -295
  72. data/Appraisals +0 -40
  73. data/CODE_OF_CONDUCT.md +0 -46
  74. data/CONTRIBUTING.md +0 -49
  75. data/Dangerfile +0 -67
  76. data/Dockerfile +0 -29
  77. data/Gemfile +0 -25
  78. data/NEWS.md +0 -1
  79. data/RELEASING.md +0 -11
  80. data/Rakefile +0 -28
  81. data/SECURITY.md +0 -15
  82. data/UPGRADE.md +0 -2
  83. data/bin/console +0 -16
  84. data/doorkeeper.gemspec +0 -42
  85. data/gemfiles/rails_5_0.gemfile +0 -18
  86. data/gemfiles/rails_5_1.gemfile +0 -18
  87. data/gemfiles/rails_5_2.gemfile +0 -18
  88. data/gemfiles/rails_6_0.gemfile +0 -18
  89. data/gemfiles/rails_master.gemfile +0 -18
  90. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  91. data/spec/controllers/applications_controller_spec.rb +0 -274
  92. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  93. data/spec/controllers/protected_resources_controller_spec.rb +0 -361
  94. data/spec/controllers/token_info_controller_spec.rb +0 -50
  95. data/spec/controllers/tokens_controller_spec.rb +0 -498
  96. data/spec/dummy/Rakefile +0 -9
  97. data/spec/dummy/app/assets/config/manifest.js +0 -2
  98. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  99. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  100. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  101. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  102. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  103. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  104. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  105. data/spec/dummy/app/models/user.rb +0 -7
  106. data/spec/dummy/app/views/home/index.html.erb +0 -0
  107. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  108. data/spec/dummy/config/application.rb +0 -49
  109. data/spec/dummy/config/boot.rb +0 -7
  110. data/spec/dummy/config/database.yml +0 -15
  111. data/spec/dummy/config/environment.rb +0 -5
  112. data/spec/dummy/config/environments/development.rb +0 -31
  113. data/spec/dummy/config/environments/production.rb +0 -64
  114. data/spec/dummy/config/environments/test.rb +0 -45
  115. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  116. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  117. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  118. data/spec/dummy/config/initializers/session_store.rb +0 -10
  119. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  120. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  121. data/spec/dummy/config/routes.rb +0 -13
  122. data/spec/dummy/config.ru +0 -6
  123. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  124. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  125. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  126. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  127. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  128. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  129. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  130. data/spec/dummy/db/schema.rb +0 -68
  131. data/spec/dummy/public/404.html +0 -26
  132. data/spec/dummy/public/422.html +0 -26
  133. data/spec/dummy/public/500.html +0 -26
  134. data/spec/dummy/public/favicon.ico +0 -0
  135. data/spec/dummy/script/rails +0 -9
  136. data/spec/factories.rb +0 -30
  137. data/spec/generators/application_owner_generator_spec.rb +0 -28
  138. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  139. data/spec/generators/install_generator_spec.rb +0 -36
  140. data/spec/generators/migration_generator_spec.rb +0 -28
  141. data/spec/generators/pkce_generator_spec.rb +0 -28
  142. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  143. data/spec/generators/templates/routes.rb +0 -4
  144. data/spec/generators/views_generator_spec.rb +0 -29
  145. data/spec/grape/grape_integration_spec.rb +0 -137
  146. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  147. data/spec/lib/config_spec.rb +0 -794
  148. data/spec/lib/doorkeeper_spec.rb +0 -27
  149. data/spec/lib/models/expirable_spec.rb +0 -61
  150. data/spec/lib/models/reusable_spec.rb +0 -40
  151. data/spec/lib/models/revocable_spec.rb +0 -59
  152. data/spec/lib/models/scopes_spec.rb +0 -53
  153. data/spec/lib/models/secret_storable_spec.rb +0 -135
  154. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  155. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -170
  156. data/spec/lib/oauth/base_request_spec.rb +0 -224
  157. data/spec/lib/oauth/base_response_spec.rb +0 -45
  158. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  159. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -134
  160. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  161. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  162. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -27
  163. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -107
  164. data/spec/lib/oauth/client_spec.rb +0 -38
  165. data/spec/lib/oauth/code_request_spec.rb +0 -46
  166. data/spec/lib/oauth/code_response_spec.rb +0 -32
  167. data/spec/lib/oauth/error_response_spec.rb +0 -64
  168. data/spec/lib/oauth/error_spec.rb +0 -21
  169. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -20
  170. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -110
  171. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  172. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  173. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -73
  174. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -53
  175. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -190
  176. data/spec/lib/oauth/pre_authorization_spec.rb +0 -223
  177. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  178. data/spec/lib/oauth/scopes_spec.rb +0 -146
  179. data/spec/lib/oauth/token_request_spec.rb +0 -157
  180. data/spec/lib/oauth/token_response_spec.rb +0 -84
  181. data/spec/lib/oauth/token_spec.rb +0 -156
  182. data/spec/lib/request/strategy_spec.rb +0 -54
  183. data/spec/lib/secret_storing/base_spec.rb +0 -60
  184. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  185. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  186. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  187. data/spec/lib/server_spec.rb +0 -49
  188. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  189. data/spec/models/doorkeeper/access_grant_spec.rb +0 -161
  190. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  191. data/spec/models/doorkeeper/application_spec.rb +0 -404
  192. data/spec/requests/applications/applications_request_spec.rb +0 -259
  193. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  194. data/spec/requests/endpoints/authorization_spec.rb +0 -91
  195. data/spec/requests/endpoints/token_spec.rb +0 -75
  196. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  197. data/spec/requests/flows/authorization_code_spec.rb +0 -525
  198. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  199. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  200. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  201. data/spec/requests/flows/password_spec.rb +0 -316
  202. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  203. data/spec/requests/flows/revoke_token_spec.rb +0 -157
  204. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  205. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  206. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  207. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  208. data/spec/routing/default_routes_spec.rb +0 -41
  209. data/spec/routing/scoped_routes_spec.rb +0 -47
  210. data/spec/spec_helper.rb +0 -54
  211. data/spec/spec_helper_integration.rb +0 -4
  212. data/spec/support/dependencies/factory_bot.rb +0 -4
  213. data/spec/support/doorkeeper_rspec.rb +0 -22
  214. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  215. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  216. data/spec/support/helpers/config_helper.rb +0 -11
  217. data/spec/support/helpers/model_helper.rb +0 -78
  218. data/spec/support/helpers/request_spec_helper.rb +0 -110
  219. data/spec/support/helpers/url_helper.rb +0 -62
  220. data/spec/support/orm/active_record.rb +0 -5
  221. data/spec/support/shared/controllers_shared_context.rb +0 -133
  222. data/spec/support/shared/hashing_shared_context.rb +0 -36
  223. data/spec/support/shared/models_shared_examples.rb +0 -54
  224. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  225. data/spec/version/version_spec.rb +0 -17
@@ -1,223 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- describe Doorkeeper::OAuth::PreAuthorization do
6
- let(:server) do
7
- server = Doorkeeper.configuration
8
- allow(server).to receive(:default_scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("default"))
9
- allow(server).to receive(:optional_scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("public profile"))
10
- server
11
- end
12
-
13
- let(:application) { FactoryBot.create(:application, redirect_uri: "https://app.com/callback") }
14
- let(:client) { Doorkeeper::OAuth::Client.find(application.uid) }
15
-
16
- let :attributes do
17
- {
18
- client_id: client.uid,
19
- response_type: "code",
20
- redirect_uri: "https://app.com/callback",
21
- state: "save-this",
22
- }
23
- end
24
-
25
- subject do
26
- described_class.new(server, attributes)
27
- end
28
-
29
- it "is authorizable when request is valid" do
30
- expect(subject).to be_authorizable
31
- end
32
-
33
- it "accepts code as response type" do
34
- attributes[:response_type] = "code"
35
- expect(subject).to be_authorizable
36
- end
37
-
38
- it "accepts token as response type" do
39
- allow(server).to receive(:grant_flows).and_return(["implicit"])
40
- attributes[:response_type] = "token"
41
- expect(subject).to be_authorizable
42
- end
43
-
44
- context "when using default grant flows" do
45
- it 'accepts "code" as response type' do
46
- attributes[:response_type] = "code"
47
- expect(subject).to be_authorizable
48
- end
49
-
50
- it 'accepts "token" as response type' do
51
- allow(server).to receive(:grant_flows).and_return(["implicit"])
52
- attributes[:response_type] = "token"
53
- expect(subject).to be_authorizable
54
- end
55
- end
56
-
57
- context "when authorization code grant flow is disabled" do
58
- before do
59
- allow(server).to receive(:grant_flows).and_return(["implicit"])
60
- end
61
-
62
- it 'does not accept "code" as response type' do
63
- attributes[:response_type] = "code"
64
- expect(subject).not_to be_authorizable
65
- end
66
- end
67
-
68
- context "when implicit grant flow is disabled" do
69
- before do
70
- allow(server).to receive(:grant_flows).and_return(["authorization_code"])
71
- end
72
-
73
- it 'does not accept "token" as response type' do
74
- attributes[:response_type] = "token"
75
- expect(subject).not_to be_authorizable
76
- end
77
- end
78
-
79
- context "client application does not restrict valid scopes" do
80
- it "accepts valid scopes" do
81
- attributes[:scope] = "public"
82
- expect(subject).to be_authorizable
83
- end
84
-
85
- it "rejects (globally) non-valid scopes" do
86
- attributes[:scope] = "invalid"
87
- expect(subject).not_to be_authorizable
88
- end
89
-
90
- it "accepts scopes which are permitted for grant_type" do
91
- allow(server).to receive(:scopes_by_grant_type).and_return(authorization_code: [:public])
92
- attributes[:scope] = "public"
93
- expect(subject).to be_authorizable
94
- end
95
-
96
- it "rejects scopes which are not permitted for grant_type" do
97
- allow(server).to receive(:scopes_by_grant_type).and_return(authorization_code: [:profile])
98
- attributes[:scope] = "public"
99
- expect(subject).not_to be_authorizable
100
- end
101
- end
102
-
103
- context "client application restricts valid scopes" do
104
- let(:application) do
105
- FactoryBot.create(:application, scopes: Doorkeeper::OAuth::Scopes.from_string("public nonsense"))
106
- end
107
-
108
- it "accepts valid scopes" do
109
- attributes[:scope] = "public"
110
- expect(subject).to be_authorizable
111
- end
112
-
113
- it "rejects (globally) non-valid scopes" do
114
- attributes[:scope] = "invalid"
115
- expect(subject).not_to be_authorizable
116
- end
117
-
118
- it "rejects (application level) non-valid scopes" do
119
- attributes[:scope] = "profile"
120
- expect(subject).to_not be_authorizable
121
- end
122
-
123
- it "accepts scopes which are permitted for grant_type" do
124
- allow(server).to receive(:scopes_by_grant_type).and_return(authorization_code: [:public])
125
- attributes[:scope] = "public"
126
- expect(subject).to be_authorizable
127
- end
128
-
129
- it "rejects scopes which are not permitted for grant_type" do
130
- allow(server).to receive(:scopes_by_grant_type).and_return(authorization_code: [:profile])
131
- attributes[:scope] = "public"
132
- expect(subject).not_to be_authorizable
133
- end
134
- end
135
-
136
- context "when scope is not provided to pre_authorization" do
137
- before { attributes[:scope] = nil }
138
-
139
- context "when default scopes is provided" do
140
- it "uses default scopes" do
141
- allow(server).to receive(:default_scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("default_scope"))
142
- expect(subject).to be_authorizable
143
- expect(subject.scope).to eq("default_scope")
144
- expect(subject.scopes).to eq(Doorkeeper::OAuth::Scopes.from_string("default_scope"))
145
- end
146
- end
147
-
148
- context "when default scopes is none" do
149
- it "not be authorizable when none default scope" do
150
- allow(server).to receive(:default_scopes).and_return(Doorkeeper::OAuth::Scopes.new)
151
- expect(subject).not_to be_authorizable
152
- end
153
- end
154
- end
155
-
156
- it "matches the redirect uri against client's one" do
157
- attributes[:redirect_uri] = "http://nothesame.com"
158
- expect(subject).not_to be_authorizable
159
- end
160
-
161
- it "stores the state" do
162
- expect(subject.state).to eq("save-this")
163
- end
164
-
165
- it "rejects if response type is not allowed" do
166
- attributes[:response_type] = "whops"
167
- expect(subject).not_to be_authorizable
168
- end
169
-
170
- it "requires an existing client" do
171
- attributes[:client_id] = nil
172
- expect(subject).not_to be_authorizable
173
- end
174
-
175
- it "requires a redirect uri" do
176
- attributes[:redirect_uri] = nil
177
- expect(subject).not_to be_authorizable
178
- end
179
-
180
- describe "as_json" do
181
- before { subject.authorizable? }
182
-
183
- it { is_expected.to respond_to :as_json }
184
-
185
- shared_examples "returns the pre authorization" do
186
- it "returns the pre authorization" do
187
- expect(json[:client_id]).to eq client.uid
188
- expect(json[:redirect_uri]).to eq subject.redirect_uri
189
- expect(json[:state]).to eq subject.state
190
- expect(json[:response_type]).to eq subject.response_type
191
- expect(json[:scope]).to eq subject.scope
192
- expect(json[:client_name]).to eq client.name
193
- expect(json[:status]).to eq I18n.t("doorkeeper.pre_authorization.status")
194
- end
195
- end
196
-
197
- context "when attributes param is not passed" do
198
- let(:json) { subject.as_json }
199
-
200
- include_examples "returns the pre authorization"
201
- end
202
-
203
- context "when attributes param is passed" do
204
- context "when attributes is a hash" do
205
- let(:custom_attributes) { { custom_id: "1234", custom_name: "a pretty good name" } }
206
- let(:json) { subject.as_json(custom_attributes) }
207
-
208
- include_examples "returns the pre authorization"
209
-
210
- it "merges the attributes in params" do
211
- expect(json[:custom_id]).to eq custom_attributes[:custom_id]
212
- expect(json[:custom_name]).to eq custom_attributes[:custom_name]
213
- end
214
- end
215
-
216
- context "when attributes is not a hash" do
217
- let(:json) { subject.as_json(nil) }
218
-
219
- include_examples "returns the pre authorization"
220
- end
221
- end
222
- end
223
- end
@@ -1,177 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- describe Doorkeeper::OAuth::RefreshTokenRequest do
6
- let(:server) do
7
- double :server,
8
- access_token_expires_in: 2.minutes
9
- end
10
-
11
- let(:refresh_token) do
12
- FactoryBot.create(:access_token, use_refresh_token: true)
13
- end
14
-
15
- let(:client) { refresh_token.application }
16
- let(:credentials) { Doorkeeper::OAuth::Client::Credentials.new(client.uid, client.secret) }
17
-
18
- before do
19
- allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
20
- allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(false)
21
- end
22
-
23
- subject { described_class.new server, refresh_token, credentials }
24
-
25
- it "issues a new token for the client" do
26
- expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
27
- # #sort_by used for MongoDB ORM extensions for valid ordering
28
- expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(120)
29
- end
30
-
31
- it "issues a new token for the client with custom expires_in" do
32
- server = double :server,
33
- access_token_expires_in: 2.minutes,
34
- custom_access_token_expires_in: lambda { |context|
35
- context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
36
- }
37
-
38
- allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
39
- allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
40
-
41
- described_class.new(server, refresh_token, credentials).authorize
42
-
43
- # #sort_by used for MongoDB ORM extensions for valid ordering
44
- expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
45
- end
46
-
47
- it "revokes the previous token" do
48
- expect { subject.authorize }.to change { refresh_token.revoked? }.from(false).to(true)
49
- end
50
-
51
- it "calls configured request callback methods" do
52
- expect(Doorkeeper.configuration.before_successful_strategy_response)
53
- .to receive(:call).with(subject).once
54
-
55
- expect(Doorkeeper.configuration.after_successful_strategy_response)
56
- .to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
57
-
58
- subject.authorize
59
- end
60
-
61
- it "requires the refresh token" do
62
- subject.refresh_token = nil
63
- subject.validate
64
- expect(subject.error).to eq(:invalid_request)
65
- expect(subject.missing_param).to eq(:refresh_token)
66
- end
67
-
68
- it "requires credentials to be valid if provided" do
69
- subject.client = nil
70
- subject.validate
71
- expect(subject.error).to eq(:invalid_client)
72
- end
73
-
74
- it "requires the token's client and current client to match" do
75
- subject.client = FactoryBot.create(:application)
76
- subject.validate
77
- expect(subject.error).to eq(:invalid_grant)
78
- end
79
-
80
- it "rejects revoked tokens" do
81
- refresh_token.revoke
82
- subject.validate
83
- expect(subject.error).to eq(:invalid_grant)
84
- end
85
-
86
- it "accepts expired tokens" do
87
- refresh_token.expires_in = -1
88
- refresh_token.save
89
- subject.validate
90
- expect(subject).to be_valid
91
- end
92
-
93
- context "refresh tokens expire on access token use" do
94
- let(:server) do
95
- double :server,
96
- access_token_expires_in: 2.minutes,
97
- custom_access_token_expires_in: lambda { |context|
98
- context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
99
- }
100
- end
101
-
102
- before do
103
- allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(true)
104
- end
105
-
106
- it "issues a new token for the client" do
107
- expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
108
- end
109
-
110
- it "does not revoke the previous token" do
111
- subject.authorize
112
- expect(refresh_token).not_to be_revoked
113
- end
114
-
115
- it "sets the previous refresh token in the new access token" do
116
- subject.authorize
117
- expect(
118
- # #sort_by used for MongoDB ORM extensions for valid ordering
119
- client.access_tokens.max_by(&:created_at).previous_refresh_token,
120
- ).to eq(refresh_token.refresh_token)
121
- end
122
- end
123
-
124
- context "clientless access tokens" do
125
- let!(:refresh_token) { FactoryBot.create(:clientless_access_token, use_refresh_token: true) }
126
-
127
- subject { described_class.new server, refresh_token, nil }
128
-
129
- it "issues a new token without a client" do
130
- expect { subject.authorize }.to change { Doorkeeper::AccessToken.count }.by(1)
131
- end
132
- end
133
-
134
- context "with scopes" do
135
- let(:refresh_token) do
136
- FactoryBot.create :access_token,
137
- use_refresh_token: true,
138
- scopes: "public write"
139
- end
140
- let(:parameters) { {} }
141
-
142
- subject { described_class.new server, refresh_token, credentials, parameters }
143
-
144
- it "transfers scopes from the old token to the new token" do
145
- subject.authorize
146
- expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public write])
147
- end
148
-
149
- it "reduces scopes to the provided scopes" do
150
- parameters[:scopes] = "public"
151
- subject.authorize
152
- expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
153
- end
154
-
155
- it "validates that scopes are included in the original access token" do
156
- parameters[:scopes] = "public update"
157
-
158
- subject.validate
159
- expect(subject.error).to eq(:invalid_scope)
160
- end
161
-
162
- it "uses params[:scope] in favor of scopes if present (valid)" do
163
- parameters[:scopes] = "public update"
164
- parameters[:scope] = "public"
165
- subject.authorize
166
- expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
167
- end
168
-
169
- it "uses params[:scope] in favor of scopes if present (invalid)" do
170
- parameters[:scopes] = "public"
171
- parameters[:scope] = "public update"
172
-
173
- subject.validate
174
- expect(subject.error).to eq(:invalid_scope)
175
- end
176
- end
177
- end
@@ -1,146 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- describe Doorkeeper::OAuth::Scopes do
6
- describe "#add" do
7
- it "allows you to add scopes with symbols" do
8
- subject.add :public
9
- expect(subject.all).to eq(["public"])
10
- end
11
-
12
- it "allows you to add scopes with strings" do
13
- subject.add "public"
14
- expect(subject.all).to eq(["public"])
15
- end
16
-
17
- it "do not add already included scopes" do
18
- subject.add :public
19
- subject.add :public
20
- expect(subject.all).to eq(["public"])
21
- end
22
- end
23
-
24
- describe "#exists" do
25
- before do
26
- subject.add :public
27
- end
28
-
29
- it "returns true if scope with given name is present" do
30
- expect(subject.exists?("public")).to be_truthy
31
- end
32
-
33
- it "returns false if scope with given name does not exist" do
34
- expect(subject.exists?("other")).to be_falsey
35
- end
36
-
37
- it "handles symbols" do
38
- expect(subject.exists?(:public)).to be_truthy
39
- expect(subject.exists?(:other)).to be_falsey
40
- end
41
- end
42
-
43
- describe ".from_string" do
44
- let(:string) { "public write" }
45
-
46
- subject { described_class.from_string(string) }
47
-
48
- it { expect(subject).to be_a(described_class) }
49
-
50
- describe "#all" do
51
- it "should be an array of the expected scopes" do
52
- scopes_array = subject.all
53
- expect(scopes_array.size).to eq(2)
54
- expect(scopes_array).to include("public")
55
- expect(scopes_array).to include("write")
56
- end
57
- end
58
- end
59
-
60
- describe "#+" do
61
- it "can add to another scope object" do
62
- scopes = described_class.from_string("public") + described_class.from_string("admin")
63
- expect(scopes.all).to eq(%w[public admin])
64
- end
65
-
66
- it "does not change the existing object" do
67
- origin = described_class.from_string("public")
68
- expect(origin.to_s).to eq("public")
69
- end
70
-
71
- it "can add an array to a scope object" do
72
- scopes = described_class.from_string("public") + ["admin"]
73
- expect(scopes.all).to eq(%w[public admin])
74
- end
75
-
76
- it "raises an error if cannot handle addition" do
77
- expect do
78
- described_class.from_string("public") + "admin"
79
- end.to raise_error(NoMethodError)
80
- end
81
- end
82
-
83
- describe "#&" do
84
- it "can get intersection with another scope object" do
85
- scopes = described_class.from_string("public admin") & described_class.from_string("write admin")
86
- expect(scopes.all).to eq(%w[admin])
87
- end
88
-
89
- it "does not change the existing object" do
90
- origin = described_class.from_string("public admin")
91
- origin & described_class.from_string("write admin")
92
- expect(origin.to_s).to eq("public admin")
93
- end
94
-
95
- it "can get intersection with an array" do
96
- scopes = described_class.from_string("public admin") & %w[write admin]
97
- expect(scopes.all).to eq(%w[admin])
98
- end
99
- end
100
-
101
- describe "#==" do
102
- it "is equal to another set of scopes" do
103
- expect(described_class.from_string("public")).to eq(described_class.from_string("public"))
104
- end
105
-
106
- it "is equal to another set of scopes with no particular order" do
107
- expect(described_class.from_string("public write")).to eq(described_class.from_string("write public"))
108
- end
109
-
110
- it "differs from another set of scopes when scopes are not the same" do
111
- expect(described_class.from_string("public write")).not_to eq(described_class.from_string("write"))
112
- end
113
-
114
- it "does not raise an error when compared to a non-enumerable object" do
115
- expect { described_class.from_string("public") == false }.not_to raise_error
116
- end
117
- end
118
-
119
- describe "#has_scopes?" do
120
- subject { described_class.from_string("public admin") }
121
-
122
- it "returns true when at least one scope is included" do
123
- expect(subject.has_scopes?(described_class.from_string("public"))).to be_truthy
124
- end
125
-
126
- it "returns true when all scopes are included" do
127
- expect(subject.has_scopes?(described_class.from_string("public admin"))).to be_truthy
128
- end
129
-
130
- it "is true if all scopes are included in any order" do
131
- expect(subject.has_scopes?(described_class.from_string("admin public"))).to be_truthy
132
- end
133
-
134
- it "is false if no scopes are included" do
135
- expect(subject.has_scopes?(described_class.from_string("notexistent"))).to be_falsey
136
- end
137
-
138
- it "returns false when any scope is not included" do
139
- expect(subject.has_scopes?(described_class.from_string("public nope"))).to be_falsey
140
- end
141
-
142
- it "is false if no scopes are included even for existing ones" do
143
- expect(subject.has_scopes?(described_class.from_string("public admin notexistent"))).to be_falsey
144
- end
145
- end
146
- end
@@ -1,157 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- describe Doorkeeper::OAuth::TokenRequest do
6
- let :application do
7
- FactoryBot.create(:application, scopes: "public")
8
- end
9
-
10
- let :pre_auth do
11
- server = Doorkeeper.configuration
12
- allow(server).to receive(:default_scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("public"))
13
- allow(server).to receive(:grant_flows).and_return(Doorkeeper::OAuth::Scopes.from_string("implicit"))
14
-
15
- client = Doorkeeper::OAuth::Client.new(application)
16
-
17
- attributes = {
18
- client_id: client.uid,
19
- response_type: "token",
20
- redirect_uri: "https://app.com/callback",
21
- }
22
-
23
- pre_auth = Doorkeeper::OAuth::PreAuthorization.new(server, attributes)
24
- pre_auth.authorizable?
25
- pre_auth
26
- end
27
-
28
- let :owner do
29
- double :owner, id: 7866
30
- end
31
-
32
- subject do
33
- described_class.new(pre_auth, owner)
34
- end
35
-
36
- it "creates an access token" do
37
- expect do
38
- subject.authorize
39
- end.to change { Doorkeeper::AccessToken.count }.by(1)
40
- end
41
-
42
- it "returns a code response" do
43
- expect(subject.authorize).to be_a(Doorkeeper::OAuth::CodeResponse)
44
- end
45
-
46
- context "when pre_auth is denied" do
47
- it "does not create token and returns a error response" do
48
- expect { subject.deny }.not_to(change { Doorkeeper::AccessToken.count })
49
- expect(subject.deny).to be_a(Doorkeeper::OAuth::ErrorResponse)
50
- end
51
- end
52
-
53
- describe "with custom expiration" do
54
- context "when proper TTL returned" do
55
- before do
56
- Doorkeeper.configure do
57
- orm DOORKEEPER_ORM
58
- custom_access_token_expires_in do |context|
59
- context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
60
- end
61
- end
62
- end
63
-
64
- it "should use the custom ttl" do
65
- subject.authorize
66
- token = Doorkeeper::AccessToken.first
67
- expect(token.expires_in).to eq(1234)
68
- end
69
- end
70
-
71
- context "when nil TTL returned" do
72
- before do
73
- Doorkeeper.configure do
74
- orm DOORKEEPER_ORM
75
- access_token_expires_in 654
76
- custom_access_token_expires_in do |_context|
77
- nil
78
- end
79
- end
80
- end
81
-
82
- it "should fallback to access_token_expires_in" do
83
- subject.authorize
84
- token = Doorkeeper::AccessToken.first
85
- expect(token.expires_in).to eq(654)
86
- end
87
- end
88
-
89
- context "when infinite TTL returned" do
90
- before do
91
- Doorkeeper.configure do
92
- orm DOORKEEPER_ORM
93
- access_token_expires_in 654
94
- custom_access_token_expires_in do |_context|
95
- Float::INFINITY
96
- end
97
- end
98
- end
99
-
100
- it "should fallback to access_token_expires_in" do
101
- subject.authorize
102
- token = Doorkeeper::AccessToken.first
103
- expect(token.expires_in).to be_nil
104
- end
105
- end
106
- end
107
-
108
- context "token reuse" do
109
- it "creates a new token if there are no matching tokens" do
110
- allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
111
- expect do
112
- subject.authorize
113
- end.to change { Doorkeeper::AccessToken.count }.by(1)
114
- end
115
-
116
- it "creates a new token if scopes do not match" do
117
- allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
118
- FactoryBot.create(
119
- :access_token, application_id: pre_auth.client.id,
120
- resource_owner_id: owner.id, scopes: "",
121
- )
122
- expect do
123
- subject.authorize
124
- end.to change { Doorkeeper::AccessToken.count }.by(1)
125
- end
126
-
127
- it "skips token creation if there is a matching one reusable" do
128
- allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
129
- allow(application.scopes).to receive(:has_scopes?).and_return(true)
130
- allow(application.scopes).to receive(:all?).and_return(true)
131
-
132
- FactoryBot.create(
133
- :access_token, application_id: pre_auth.client.id,
134
- resource_owner_id: owner.id, scopes: "public",
135
- )
136
-
137
- expect { subject.authorize }.not_to(change { Doorkeeper::AccessToken.count })
138
- end
139
-
140
- it "creates new token if there is a matching one but non reusable" do
141
- allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
142
- allow(application.scopes).to receive(:has_scopes?).and_return(true)
143
- allow(application.scopes).to receive(:all?).and_return(true)
144
-
145
- FactoryBot.create(
146
- :access_token, application_id: pre_auth.client.id,
147
- resource_owner_id: owner.id, scopes: "public",
148
- )
149
-
150
- allow_any_instance_of(Doorkeeper::AccessToken).to receive(:reusable?).and_return(false)
151
-
152
- expect do
153
- subject.authorize
154
- end.to change { Doorkeeper::AccessToken.count }.by(1)
155
- end
156
- end
157
- end