doorkeeper 5.2.2 → 5.5.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of doorkeeper might be problematic. Click here for more details.

Files changed (260) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +198 -3
  3. data/README.md +28 -20
  4. data/app/controllers/doorkeeper/application_controller.rb +3 -2
  5. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
  6. data/app/controllers/doorkeeper/applications_controller.rb +7 -8
  7. data/app/controllers/doorkeeper/authorizations_controller.rb +48 -18
  8. data/app/controllers/doorkeeper/authorized_applications_controller.rb +6 -6
  9. data/app/controllers/doorkeeper/token_info_controller.rb +12 -2
  10. data/app/controllers/doorkeeper/tokens_controller.rb +70 -25
  11. data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
  12. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  13. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  14. data/app/views/doorkeeper/authorizations/form_post.html.erb +15 -0
  15. data/app/views/doorkeeper/authorizations/new.html.erb +2 -0
  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 +214 -122
  21. data/lib/doorkeeper/engine.rb +1 -1
  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 +2 -2
  27. data/lib/doorkeeper/helpers/controller.rb +18 -12
  28. data/lib/doorkeeper/models/access_grant_mixin.rb +23 -19
  29. data/lib/doorkeeper/models/access_token_mixin.rb +157 -55
  30. data/lib/doorkeeper/models/application_mixin.rb +8 -7
  31. data/lib/doorkeeper/models/concerns/expirable.rb +1 -1
  32. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  33. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  34. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  35. data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
  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 +22 -9
  39. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  40. data/lib/doorkeeper/oauth/authorization/token.rb +23 -18
  41. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  42. data/lib/doorkeeper/oauth/authorization_code_request.rb +30 -20
  43. data/lib/doorkeeper/oauth/base_request.rb +19 -23
  44. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  45. data/lib/doorkeeper/oauth/client.rb +8 -9
  46. data/lib/doorkeeper/oauth/client_credentials/creator.rb +38 -12
  47. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
  48. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +7 -5
  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 +24 -14
  52. data/lib/doorkeeper/oauth/error.rb +1 -1
  53. data/lib/doorkeeper/oauth/error_response.rb +10 -11
  54. data/lib/doorkeeper/oauth/forbidden_token_response.rb +2 -1
  55. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
  56. data/lib/doorkeeper/oauth/helpers/unique_token.rb +10 -7
  57. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -19
  58. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  59. data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
  60. data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
  61. data/lib/doorkeeper/oauth/password_access_token_request.rb +28 -10
  62. data/lib/doorkeeper/oauth/pre_authorization.rb +73 -37
  63. data/lib/doorkeeper/oauth/refresh_token_request.rb +35 -26
  64. data/lib/doorkeeper/oauth/token.rb +6 -7
  65. data/lib/doorkeeper/oauth/token_introspection.rb +12 -16
  66. data/lib/doorkeeper/oauth/token_request.rb +3 -3
  67. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  68. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  69. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  70. data/lib/doorkeeper/orm/active_record/application.rb +5 -95
  71. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +69 -0
  72. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +60 -0
  73. data/lib/doorkeeper/orm/active_record/mixins/application.rb +199 -0
  74. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +8 -3
  75. data/lib/doorkeeper/orm/active_record.rb +5 -7
  76. data/lib/doorkeeper/rails/helpers.rb +4 -4
  77. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  78. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  79. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  80. data/lib/doorkeeper/rails/routes.rb +17 -25
  81. data/lib/doorkeeper/rake/db.rake +6 -6
  82. data/lib/doorkeeper/rake/setup.rake +5 -0
  83. data/lib/doorkeeper/request/authorization_code.rb +3 -3
  84. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  85. data/lib/doorkeeper/request/password.rb +3 -2
  86. data/lib/doorkeeper/request/refresh_token.rb +5 -4
  87. data/lib/doorkeeper/request/strategy.rb +2 -2
  88. data/lib/doorkeeper/request.rb +49 -12
  89. data/lib/doorkeeper/server.rb +5 -5
  90. data/lib/doorkeeper/stale_records_cleaner.rb +4 -4
  91. data/lib/doorkeeper/version.rb +2 -6
  92. data/lib/doorkeeper.rb +112 -81
  93. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  94. data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
  95. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  96. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  97. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  98. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +2 -2
  99. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  100. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  101. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  102. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  103. data/lib/generators/doorkeeper/templates/initializer.rb +99 -14
  104. data/lib/generators/doorkeeper/templates/migration.rb.erb +14 -5
  105. metadata +37 -306
  106. data/Appraisals +0 -40
  107. data/CODE_OF_CONDUCT.md +0 -46
  108. data/CONTRIBUTING.md +0 -49
  109. data/Dangerfile +0 -67
  110. data/Dockerfile +0 -29
  111. data/Gemfile +0 -25
  112. data/NEWS.md +0 -1
  113. data/RELEASING.md +0 -11
  114. data/Rakefile +0 -28
  115. data/SECURITY.md +0 -15
  116. data/UPGRADE.md +0 -2
  117. data/bin/console +0 -16
  118. data/doorkeeper.gemspec +0 -42
  119. data/gemfiles/rails_5_0.gemfile +0 -18
  120. data/gemfiles/rails_5_1.gemfile +0 -18
  121. data/gemfiles/rails_5_2.gemfile +0 -18
  122. data/gemfiles/rails_6_0.gemfile +0 -18
  123. data/gemfiles/rails_master.gemfile +0 -18
  124. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  125. data/spec/controllers/applications_controller_spec.rb +0 -273
  126. data/spec/controllers/authorizations_controller_spec.rb +0 -608
  127. data/spec/controllers/protected_resources_controller_spec.rb +0 -353
  128. data/spec/controllers/token_info_controller_spec.rb +0 -50
  129. data/spec/controllers/tokens_controller_spec.rb +0 -498
  130. data/spec/dummy/Rakefile +0 -9
  131. data/spec/dummy/app/assets/config/manifest.js +0 -2
  132. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  133. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  134. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  135. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  136. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  137. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  138. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  139. data/spec/dummy/app/models/user.rb +0 -7
  140. data/spec/dummy/app/views/home/index.html.erb +0 -0
  141. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  142. data/spec/dummy/config/application.rb +0 -49
  143. data/spec/dummy/config/boot.rb +0 -7
  144. data/spec/dummy/config/database.yml +0 -15
  145. data/spec/dummy/config/environment.rb +0 -5
  146. data/spec/dummy/config/environments/development.rb +0 -31
  147. data/spec/dummy/config/environments/production.rb +0 -64
  148. data/spec/dummy/config/environments/test.rb +0 -45
  149. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  150. data/spec/dummy/config/initializers/doorkeeper.rb +0 -166
  151. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  152. data/spec/dummy/config/initializers/session_store.rb +0 -10
  153. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  154. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  155. data/spec/dummy/config/routes.rb +0 -13
  156. data/spec/dummy/config.ru +0 -6
  157. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  158. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  159. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  160. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  161. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  162. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  163. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  164. data/spec/dummy/db/schema.rb +0 -68
  165. data/spec/dummy/public/404.html +0 -26
  166. data/spec/dummy/public/422.html +0 -26
  167. data/spec/dummy/public/500.html +0 -26
  168. data/spec/dummy/public/favicon.ico +0 -0
  169. data/spec/dummy/script/rails +0 -9
  170. data/spec/factories.rb +0 -30
  171. data/spec/generators/application_owner_generator_spec.rb +0 -28
  172. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  173. data/spec/generators/install_generator_spec.rb +0 -36
  174. data/spec/generators/migration_generator_spec.rb +0 -28
  175. data/spec/generators/pkce_generator_spec.rb +0 -28
  176. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  177. data/spec/generators/templates/routes.rb +0 -4
  178. data/spec/generators/views_generator_spec.rb +0 -29
  179. data/spec/grape/grape_integration_spec.rb +0 -137
  180. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  181. data/spec/lib/config_spec.rb +0 -739
  182. data/spec/lib/doorkeeper_spec.rb +0 -27
  183. data/spec/lib/models/expirable_spec.rb +0 -61
  184. data/spec/lib/models/reusable_spec.rb +0 -40
  185. data/spec/lib/models/revocable_spec.rb +0 -59
  186. data/spec/lib/models/scopes_spec.rb +0 -53
  187. data/spec/lib/models/secret_storable_spec.rb +0 -135
  188. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  189. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -168
  190. data/spec/lib/oauth/base_request_spec.rb +0 -222
  191. data/spec/lib/oauth/base_response_spec.rb +0 -47
  192. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  193. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -97
  194. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  195. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  196. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
  197. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
  198. data/spec/lib/oauth/client_spec.rb +0 -38
  199. data/spec/lib/oauth/code_request_spec.rb +0 -46
  200. data/spec/lib/oauth/code_response_spec.rb +0 -36
  201. data/spec/lib/oauth/error_response_spec.rb +0 -66
  202. data/spec/lib/oauth/error_spec.rb +0 -23
  203. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
  204. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
  205. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  206. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -262
  207. data/spec/lib/oauth/invalid_request_response_spec.rb +0 -75
  208. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
  209. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
  210. data/spec/lib/oauth/pre_authorization_spec.rb +0 -225
  211. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -178
  212. data/spec/lib/oauth/scopes_spec.rb +0 -148
  213. data/spec/lib/oauth/token_request_spec.rb +0 -153
  214. data/spec/lib/oauth/token_response_spec.rb +0 -86
  215. data/spec/lib/oauth/token_spec.rb +0 -158
  216. data/spec/lib/request/strategy_spec.rb +0 -54
  217. data/spec/lib/secret_storing/base_spec.rb +0 -60
  218. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  219. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  220. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  221. data/spec/lib/server_spec.rb +0 -49
  222. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  223. data/spec/models/doorkeeper/access_grant_spec.rb +0 -163
  224. data/spec/models/doorkeeper/access_token_spec.rb +0 -622
  225. data/spec/models/doorkeeper/application_spec.rb +0 -377
  226. data/spec/requests/applications/applications_request_spec.rb +0 -259
  227. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  228. data/spec/requests/endpoints/authorization_spec.rb +0 -89
  229. data/spec/requests/endpoints/token_spec.rb +0 -75
  230. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -79
  231. data/spec/requests/flows/authorization_code_spec.rb +0 -513
  232. data/spec/requests/flows/client_credentials_spec.rb +0 -166
  233. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -46
  234. data/spec/requests/flows/implicit_grant_spec.rb +0 -91
  235. data/spec/requests/flows/password_spec.rb +0 -296
  236. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  237. data/spec/requests/flows/revoke_token_spec.rb +0 -151
  238. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  239. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  240. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  241. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  242. data/spec/routing/default_routes_spec.rb +0 -41
  243. data/spec/routing/scoped_routes_spec.rb +0 -47
  244. data/spec/spec_helper.rb +0 -57
  245. data/spec/spec_helper_integration.rb +0 -4
  246. data/spec/support/dependencies/factory_bot.rb +0 -4
  247. data/spec/support/doorkeeper_rspec.rb +0 -22
  248. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  249. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  250. data/spec/support/helpers/config_helper.rb +0 -11
  251. data/spec/support/helpers/model_helper.rb +0 -78
  252. data/spec/support/helpers/request_spec_helper.rb +0 -110
  253. data/spec/support/helpers/url_helper.rb +0 -62
  254. data/spec/support/http_method_shim.rb +0 -29
  255. data/spec/support/orm/active_record.rb +0 -5
  256. data/spec/support/shared/controllers_shared_context.rb +0 -123
  257. data/spec/support/shared/hashing_shared_context.rb +0 -36
  258. data/spec/support/shared/models_shared_examples.rb +0 -54
  259. data/spec/validators/redirect_uri_validator_spec.rb +0 -183
  260. data/spec/version/version_spec.rb +0 -17
@@ -1,622 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require "spec_helper"
4
-
5
- module Doorkeeper
6
- describe AccessToken do
7
- let(:clazz) { Doorkeeper::AccessToken }
8
- subject { FactoryBot.build(:access_token) }
9
-
10
- it { expect(subject).to be_valid }
11
-
12
- it_behaves_like "an accessible token"
13
- it_behaves_like "a revocable token"
14
- it_behaves_like "a unique token" do
15
- let(:factory_name) { :access_token }
16
- end
17
-
18
- module CustomGeneratorArgs
19
- def self.generate; end
20
- end
21
-
22
- describe :generate_token do
23
- it "generates a token using the default method" do
24
- FactoryBot.create :access_token
25
-
26
- token = FactoryBot.create :access_token
27
- expect(token.token).to be_a(String)
28
- end
29
-
30
- context "with hashing enabled" do
31
- let(:token) { FactoryBot.create :access_token }
32
- include_context "with token hashing enabled"
33
-
34
- it "holds a volatile plaintext token when created" do
35
- expect(token.plaintext_token).to be_a(String)
36
- expect(token.token)
37
- .to eq(hashed_or_plain_token_func.call(token.plaintext_token))
38
-
39
- # Finder method only finds the hashed token
40
- loaded = clazz.find_by(token: token.token)
41
- expect(loaded).to eq(token)
42
- expect(loaded.plaintext_token).to be_nil
43
- expect(loaded.token).to eq(token.token)
44
- end
45
-
46
- it "does not find_by plain text tokens" do
47
- expect(clazz.find_by(token: token.plaintext_token)).to be_nil
48
- end
49
-
50
- describe "with having a plain text token" do
51
- let(:plain_text_token) { "plain text token" }
52
- let(:access_token) { FactoryBot.create :access_token }
53
-
54
- before do
55
- # Assume we have a plain text token from before activating the option
56
- access_token.update_column(:token, plain_text_token)
57
- end
58
-
59
- context "without fallback lookup" do
60
- it "does not provide lookups with either through by_token" do
61
- expect(clazz.by_token(plain_text_token)).to eq(nil)
62
- expect(clazz.by_token(access_token.token)).to eq(nil)
63
-
64
- # And it does not touch the token
65
- access_token.reload
66
- expect(access_token.token).to eq(plain_text_token)
67
- end
68
- end
69
-
70
- context "with fallback lookup" do
71
- include_context "with token hashing and fallback lookup enabled"
72
-
73
- it "upgrades a plain token when falling back to it" do
74
- # Side-effect: This will automatically upgrade the token
75
- expect(clazz).to receive(:upgrade_fallback_value).and_call_original
76
- expect(clazz.by_token(plain_text_token))
77
- .to have_attributes(
78
- resource_owner_id: access_token.resource_owner_id,
79
- application_id: access_token.application_id,
80
- scopes: access_token.scopes,
81
- )
82
-
83
- # Will find subsequently by hashing the token
84
- expect(clazz.by_token(plain_text_token))
85
- .to have_attributes(
86
- resource_owner_id: access_token.resource_owner_id,
87
- application_id: access_token.application_id,
88
- scopes: access_token.scopes,
89
- )
90
-
91
- # Not all the ORM support :id PK
92
- if access_token.respond_to?(:id)
93
- expect(clazz.by_token(plain_text_token).id).to eq(access_token.id)
94
- end
95
-
96
- # And it modifies the token value
97
- access_token.reload
98
- expect(access_token.token).not_to eq(plain_text_token)
99
- expect(clazz.find_by(token: plain_text_token)).to eq(nil)
100
- expect(clazz.find_by(token: access_token.token)).not_to be_nil
101
- end
102
- end
103
- end
104
- end
105
-
106
- it "generates a token using a custom object" do
107
- eigenclass = class << CustomGeneratorArgs; self; end
108
- eigenclass.class_eval do
109
- remove_method :generate
110
- end
111
- module CustomGeneratorArgs
112
- def self.generate(opts = {})
113
- "custom_generator_token_#{opts[:resource_owner_id]}"
114
- end
115
- end
116
-
117
- Doorkeeper.configure do
118
- orm DOORKEEPER_ORM
119
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
120
- end
121
-
122
- token = FactoryBot.create :access_token
123
- expect(token.token).to match(/custom_generator_token_\d+/)
124
- end
125
-
126
- it "allows the custom generator to access the application details" do
127
- eigenclass = class << CustomGeneratorArgs; self; end
128
- eigenclass.class_eval do
129
- remove_method :generate
130
- end
131
-
132
- module CustomGeneratorArgs
133
- def self.generate(opts = {})
134
- "custom_generator_token_#{opts[:application].name}"
135
- end
136
- end
137
-
138
- Doorkeeper.configure do
139
- orm DOORKEEPER_ORM
140
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
141
- end
142
-
143
- token = FactoryBot.create :access_token
144
- expect(token.token).to match(/custom_generator_token_Application \d+/)
145
- end
146
-
147
- it "allows the custom generator to access the scopes" do
148
- eigenclass = class << CustomGeneratorArgs; self; end
149
- eigenclass.class_eval do
150
- remove_method :generate
151
- end
152
- module CustomGeneratorArgs
153
- def self.generate(opts = {})
154
- "custom_generator_token_#{opts[:scopes].count}_#{opts[:scopes]}"
155
- end
156
- end
157
-
158
- Doorkeeper.configure do
159
- orm DOORKEEPER_ORM
160
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
161
- end
162
-
163
- token = FactoryBot.create :access_token, scopes: "public write"
164
-
165
- expect(token.token).to eq "custom_generator_token_2_public write"
166
- end
167
-
168
- it "allows the custom generator to access the expiry length" do
169
- eigenclass = class << CustomGeneratorArgs; self; end
170
- eigenclass.class_eval do
171
- remove_method :generate
172
- end
173
- module CustomGeneratorArgs
174
- def self.generate(opts = {})
175
- "custom_generator_token_#{opts[:expires_in]}"
176
- end
177
- end
178
-
179
- Doorkeeper.configure do
180
- orm DOORKEEPER_ORM
181
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
182
- end
183
-
184
- token = FactoryBot.create :access_token
185
- expect(token.token).to eq "custom_generator_token_7200"
186
- end
187
-
188
- it "allows the custom generator to access the created time" do
189
- module CustomGeneratorArgs
190
- def self.generate(opts = {})
191
- "custom_generator_token_#{opts[:created_at].to_i}"
192
- end
193
- end
194
-
195
- Doorkeeper.configure do
196
- orm DOORKEEPER_ORM
197
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
198
- end
199
-
200
- token = FactoryBot.create :access_token
201
- created_at = token.created_at
202
- expect(token.token).to eq "custom_generator_token_#{created_at.to_i}"
203
- end
204
-
205
- it "raises an error if the custom object does not support generate" do
206
- module NoGenerate
207
- end
208
-
209
- Doorkeeper.configure do
210
- orm DOORKEEPER_ORM
211
- access_token_generator "Doorkeeper::NoGenerate"
212
- end
213
-
214
- expect { FactoryBot.create :access_token }.to(
215
- raise_error(Doorkeeper::Errors::UnableToGenerateToken)
216
- )
217
- end
218
-
219
- it "raises original error if something went wrong in custom generator" do
220
- eigenclass = class << CustomGeneratorArgs; self; end
221
- eigenclass.class_eval do
222
- remove_method :generate
223
- end
224
-
225
- module CustomGeneratorArgs
226
- def self.generate(_opts = {})
227
- raise LoadError, "custom behaviour"
228
- end
229
- end
230
-
231
- Doorkeeper.configure do
232
- orm DOORKEEPER_ORM
233
- access_token_generator "Doorkeeper::CustomGeneratorArgs"
234
- end
235
-
236
- expect { FactoryBot.create :access_token }.to(
237
- raise_error(LoadError)
238
- )
239
- end
240
-
241
- it "raises an error if the custom object does not exist" do
242
- Doorkeeper.configure do
243
- orm DOORKEEPER_ORM
244
- access_token_generator "Doorkeeper::NotReal"
245
- end
246
-
247
- expect { FactoryBot.create :access_token }.to(
248
- raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/)
249
- )
250
- end
251
- end
252
-
253
- describe :refresh_token do
254
- it "has empty refresh token if it was not required" do
255
- token = FactoryBot.create :access_token
256
- expect(token.refresh_token).to be_nil
257
- end
258
-
259
- it "generates a refresh token if it was requested" do
260
- token = FactoryBot.create :access_token, use_refresh_token: true
261
- expect(token.refresh_token).not_to be_nil
262
- end
263
-
264
- it "is not valid if token exists" do
265
- token1 = FactoryBot.create :access_token, use_refresh_token: true
266
- token2 = FactoryBot.create :access_token, use_refresh_token: true
267
- token2.refresh_token = token1.refresh_token
268
- expect(token2).not_to be_valid
269
- end
270
-
271
- it "expects database to raise an error if refresh tokens are the same" do
272
- token1 = FactoryBot.create :access_token, use_refresh_token: true
273
- token2 = FactoryBot.create :access_token, use_refresh_token: true
274
- expect do
275
- token2.refresh_token = token1.refresh_token
276
- token2.save(validate: false)
277
- end.to raise_error(uniqueness_error)
278
- end
279
-
280
- context "with hashing enabled" do
281
- include_context "with token hashing enabled"
282
- let(:token) { FactoryBot.create :access_token, use_refresh_token: true }
283
-
284
- it "holds a volatile refresh token when created" do
285
- expect(token.plaintext_refresh_token).to be_a(String)
286
- expect(token.refresh_token)
287
- .to eq(hashed_or_plain_token_func.call(token.plaintext_refresh_token))
288
-
289
- # Finder method only finds the hashed token
290
- loaded = clazz.find_by(refresh_token: token.refresh_token)
291
- expect(loaded).to eq(token)
292
- expect(loaded.plaintext_refresh_token).to be_nil
293
- expect(loaded.refresh_token).to eq(token.refresh_token)
294
- end
295
-
296
- it "does not find_by plain text refresh tokens" do
297
- expect(clazz.find_by(refresh_token: token.plaintext_refresh_token)).to be_nil
298
- end
299
-
300
- describe "with having a plain text token" do
301
- let(:plain_refresh_token) { "plain refresh token" }
302
- let(:access_token) { FactoryBot.create :access_token }
303
-
304
- before do
305
- # Assume we have a plain text token from before activating the option
306
- access_token.update_column(:refresh_token, plain_refresh_token)
307
- end
308
-
309
- context "without fallback lookup" do
310
- it "does not provide lookups with either through by_token" do
311
- expect(clazz.by_refresh_token(plain_refresh_token)).to eq(nil)
312
- expect(clazz.by_refresh_token(access_token.refresh_token)).to eq(nil)
313
-
314
- # And it does not touch the token
315
- access_token.reload
316
- expect(access_token.refresh_token).to eq(plain_refresh_token)
317
- end
318
- end
319
-
320
- context "with fallback lookup" do
321
- include_context "with token hashing and fallback lookup enabled"
322
-
323
- it "upgrades a plain token when falling back to it" do
324
- # Side-effect: This will automatically upgrade the token
325
- expect(clazz).to receive(:upgrade_fallback_value).and_call_original
326
- expect(clazz.by_refresh_token(plain_refresh_token))
327
- .to have_attributes(
328
- token: access_token.token,
329
- resource_owner_id: access_token.resource_owner_id,
330
- application_id: access_token.application_id,
331
- )
332
-
333
- # Will find subsequently by hashing the token
334
- expect(clazz.by_refresh_token(plain_refresh_token))
335
- .to have_attributes(
336
- token: access_token.token,
337
- resource_owner_id: access_token.resource_owner_id,
338
- application_id: access_token.application_id,
339
- )
340
-
341
- # Not all the ORM support :id PK
342
- if access_token.respond_to?(:id)
343
- expect(clazz.by_refresh_token(plain_refresh_token).id).to eq(access_token.id)
344
- end
345
-
346
- # And it modifies the token value
347
- access_token.reload
348
- expect(access_token.refresh_token).not_to eq(plain_refresh_token)
349
- expect(clazz.find_by(refresh_token: plain_refresh_token)).to eq(nil)
350
- expect(clazz.find_by(refresh_token: access_token.refresh_token)).not_to be_nil
351
- end
352
- end
353
- end
354
- end
355
- end
356
-
357
- describe "validations" do
358
- it "is valid without resource_owner_id" do
359
- # For client credentials flow
360
- subject.resource_owner_id = nil
361
- expect(subject).to be_valid
362
- end
363
-
364
- it "is valid without application_id" do
365
- # For resource owner credentials flow
366
- subject.application_id = nil
367
- expect(subject).to be_valid
368
- end
369
- end
370
-
371
- describe "#same_credential?" do
372
- context "with default parameters" do
373
- let(:resource_owner_id) { 100 }
374
- let(:application) { FactoryBot.create :application }
375
- let(:default_attributes) do
376
- { application: application, resource_owner_id: resource_owner_id }
377
- end
378
- let(:access_token1) { FactoryBot.create :access_token, default_attributes }
379
-
380
- context "the second token has the same owner and same app" do
381
- let(:access_token2) { FactoryBot.create :access_token, default_attributes }
382
- it "success" do
383
- expect(access_token1.same_credential?(access_token2)).to be_truthy
384
- end
385
- end
386
-
387
- context "the second token has same owner and different app" do
388
- let(:other_application) { FactoryBot.create :application }
389
- let(:access_token2) do
390
- FactoryBot.create :access_token,
391
- application: other_application,
392
- resource_owner_id: resource_owner_id
393
- end
394
-
395
- it "fail" do
396
- expect(access_token1.same_credential?(access_token2)).to be_falsey
397
- end
398
- end
399
-
400
- context "the second token has different owner and different app" do
401
- let(:other_application) { FactoryBot.create :application }
402
- let(:access_token2) do
403
- FactoryBot.create :access_token, application: other_application, resource_owner_id: 42
404
- end
405
-
406
- it "fail" do
407
- expect(access_token1.same_credential?(access_token2)).to be_falsey
408
- end
409
- end
410
-
411
- context "the second token has different owner and same app" do
412
- let(:access_token2) do
413
- FactoryBot.create :access_token, application: application, resource_owner_id: 42
414
- end
415
-
416
- it "fail" do
417
- expect(access_token1.same_credential?(access_token2)).to be_falsey
418
- end
419
- end
420
- end
421
- end
422
-
423
- describe "#acceptable?" do
424
- context "a token that is not accessible" do
425
- let(:token) { FactoryBot.create(:access_token, created_at: 6.hours.ago) }
426
-
427
- it "should return false" do
428
- expect(token.acceptable?(nil)).to be false
429
- end
430
- end
431
-
432
- context "a token that has the incorrect scopes" do
433
- let(:token) { FactoryBot.create(:access_token) }
434
-
435
- it "should return false" do
436
- expect(token.acceptable?(["public"])).to be false
437
- end
438
- end
439
-
440
- context "a token is acceptable with the correct scopes" do
441
- let(:token) do
442
- token = FactoryBot.create(:access_token)
443
- token[:scopes] = "public"
444
- token
445
- end
446
-
447
- it "should return true" do
448
- expect(token.acceptable?(["public"])).to be true
449
- end
450
- end
451
- end
452
-
453
- describe ".revoke_all_for" do
454
- let(:resource_owner) { double(id: 100) }
455
- let(:application) { FactoryBot.create :application }
456
- let(:default_attributes) do
457
- { application: application, resource_owner_id: resource_owner.id }
458
- end
459
-
460
- it "revokes all tokens for given application and resource owner" do
461
- FactoryBot.create :access_token, default_attributes
462
- AccessToken.revoke_all_for application.id, resource_owner
463
- AccessToken.all.each do |token|
464
- expect(token).to be_revoked
465
- end
466
- end
467
-
468
- it "matches application" do
469
- access_token_for_different_app = FactoryBot.create(
470
- :access_token,
471
- default_attributes.merge(application: FactoryBot.create(:application))
472
- )
473
-
474
- AccessToken.revoke_all_for application.id, resource_owner
475
-
476
- expect(access_token_for_different_app.reload).not_to be_revoked
477
- end
478
-
479
- it "matches resource owner" do
480
- access_token_for_different_owner = FactoryBot.create(
481
- :access_token,
482
- default_attributes.merge(resource_owner_id: 90)
483
- )
484
-
485
- AccessToken.revoke_all_for application.id, resource_owner
486
-
487
- expect(access_token_for_different_owner.reload).not_to be_revoked
488
- end
489
- end
490
-
491
- describe ".matching_token_for" do
492
- let(:resource_owner_id) { 100 }
493
- let(:application) { FactoryBot.create :application }
494
- let(:scopes) { Doorkeeper::OAuth::Scopes.from_string("public write") }
495
- let(:default_attributes) do
496
- {
497
- application: application,
498
- resource_owner_id: resource_owner_id,
499
- scopes: scopes.to_s,
500
- }
501
- end
502
-
503
- before do
504
- default_scopes_exist(*scopes.all)
505
- end
506
-
507
- it "returns only one token" do
508
- token = FactoryBot.create :access_token, default_attributes
509
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
510
- expect(last_token).to eq(token)
511
- end
512
-
513
- it "accepts resource owner as object" do
514
- resource_owner = double(to_key: true, id: 100)
515
- token = FactoryBot.create :access_token, default_attributes
516
- last_token = AccessToken.matching_token_for(application, resource_owner, scopes)
517
- expect(last_token).to eq(token)
518
- end
519
-
520
- it "accepts nil as resource owner" do
521
- token = FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: nil)
522
- last_token = AccessToken.matching_token_for(application, nil, scopes)
523
- expect(last_token).to eq(token)
524
- end
525
-
526
- it "excludes revoked tokens" do
527
- FactoryBot.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
528
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
529
- expect(last_token).to be_nil
530
- end
531
-
532
- it "excludes tokens with a different application" do
533
- FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
534
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
535
- expect(last_token).to be_nil
536
- end
537
-
538
- it "excludes tokens with a different resource owner" do
539
- FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
540
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
541
- expect(last_token).to be_nil
542
- end
543
-
544
- it "excludes tokens with fewer scopes" do
545
- FactoryBot.create :access_token, default_attributes.merge(scopes: "public")
546
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
547
- expect(last_token).to be_nil
548
- end
549
-
550
- it "excludes tokens with different scopes" do
551
- FactoryBot.create :access_token, default_attributes.merge(scopes: "public email")
552
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
553
- expect(last_token).to be_nil
554
- end
555
-
556
- it "excludes tokens with additional scopes" do
557
- FactoryBot.create :access_token, default_attributes.merge(scopes: "public write email")
558
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
559
- expect(last_token).to be_nil
560
- end
561
-
562
- it "excludes tokens with scopes that are not present in server scopes" do
563
- FactoryBot.create :access_token, default_attributes.merge(
564
- application: application, scopes: "public read"
565
- )
566
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
567
- expect(last_token).to be_nil
568
- end
569
-
570
- it "excludes tokens with scopes that are not present in application scopes" do
571
- application = FactoryBot.create :application, scopes: "private read"
572
- FactoryBot.create :access_token, default_attributes.merge(
573
- application: application
574
- )
575
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
576
- expect(last_token).to be_nil
577
- end
578
-
579
- it "does not match token if empty scope requested and token/app scopes present" do
580
- application = FactoryBot.create :application, scopes: "sample:scope"
581
- app_params = {
582
- application_id: application.id, scopes: "sample:scope",
583
- resource_owner_id: 100,
584
- }
585
- FactoryBot.create :access_token, app_params
586
- empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
587
- last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
588
- expect(last_token).to be_nil
589
- end
590
-
591
- it "matches token if empty scope requested and no token scopes present" do
592
- empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
593
- token = FactoryBot.create :access_token, default_attributes.merge(scopes: empty_scopes)
594
- last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
595
- expect(last_token).to eq(token)
596
- end
597
-
598
- it "returns the last matching token" do
599
- FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
600
- matching_token = FactoryBot.create :access_token, default_attributes
601
- FactoryBot.create :access_token, default_attributes.merge(scopes: "public")
602
-
603
- last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
604
- expect(last_token).to eq(matching_token)
605
- end
606
- end
607
-
608
- describe "#as_json" do
609
- it "returns as_json hash" do
610
- token = FactoryBot.create :access_token
611
- token_hash = {
612
- resource_owner_id: token.resource_owner_id,
613
- scope: token.scopes,
614
- expires_in: token.expires_in_seconds,
615
- application: { uid: token.application.uid },
616
- created_at: token.created_at.to_i,
617
- }
618
- expect(token.as_json).to eq token_hash
619
- end
620
- end
621
- end
622
- end