doorkeeper 5.1.2 → 5.6.6

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