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,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