doorkeeper 5.1.0 → 5.5.0

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 (265) hide show
  1. checksums.yaml +4 -4
  2. data/{NEWS.md → CHANGELOG.md} +234 -25
  3. data/README.md +21 -11
  4. data/app/controllers/doorkeeper/application_controller.rb +2 -2
  5. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  6. data/app/controllers/doorkeeper/applications_controller.rb +8 -7
  7. data/app/controllers/doorkeeper/authorizations_controller.rb +56 -19
  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 +93 -25
  11. data/app/views/doorkeeper/applications/_form.html.erb +1 -7
  12. data/app/views/doorkeeper/applications/show.html.erb +35 -14
  13. data/app/views/doorkeeper/authorizations/form_post.html.erb +11 -0
  14. data/config/locales/en.yml +13 -3
  15. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  16. data/lib/doorkeeper/config/option.rb +20 -2
  17. data/lib/doorkeeper/config/validations.rb +53 -0
  18. data/lib/doorkeeper/config.rb +291 -121
  19. data/lib/doorkeeper/engine.rb +1 -1
  20. data/lib/doorkeeper/errors.rb +13 -18
  21. data/lib/doorkeeper/grant_flow/fallback_flow.rb +15 -0
  22. data/lib/doorkeeper/grant_flow/flow.rb +44 -0
  23. data/lib/doorkeeper/grant_flow/registry.rb +50 -0
  24. data/lib/doorkeeper/grant_flow.rb +45 -0
  25. data/lib/doorkeeper/grape/helpers.rb +7 -3
  26. data/lib/doorkeeper/helpers/controller.rb +36 -11
  27. data/lib/doorkeeper/models/access_grant_mixin.rb +22 -18
  28. data/lib/doorkeeper/models/access_token_mixin.rb +194 -51
  29. data/lib/doorkeeper/models/application_mixin.rb +8 -7
  30. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  31. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  32. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  33. data/lib/doorkeeper/models/concerns/revocable.rb +1 -28
  34. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  35. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  36. data/lib/doorkeeper/oauth/authorization/code.rb +25 -14
  37. data/lib/doorkeeper/oauth/authorization/context.rb +5 -5
  38. data/lib/doorkeeper/oauth/authorization/token.rb +24 -19
  39. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  40. data/lib/doorkeeper/oauth/authorization_code_request.rb +40 -21
  41. data/lib/doorkeeper/oauth/base_request.rb +21 -23
  42. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  43. data/lib/doorkeeper/oauth/client.rb +8 -9
  44. data/lib/doorkeeper/oauth/client_credentials/creator.rb +45 -5
  45. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +10 -8
  46. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +13 -3
  47. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  48. data/lib/doorkeeper/oauth/code_request.rb +6 -12
  49. data/lib/doorkeeper/oauth/code_response.rb +24 -14
  50. data/lib/doorkeeper/oauth/error.rb +1 -1
  51. data/lib/doorkeeper/oauth/error_response.rb +10 -11
  52. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +8 -12
  53. data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
  54. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -5
  55. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  56. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  57. data/lib/doorkeeper/oauth/invalid_token_response.rb +7 -4
  58. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  59. data/lib/doorkeeper/oauth/password_access_token_request.rb +32 -10
  60. data/lib/doorkeeper/oauth/pre_authorization.rb +111 -42
  61. data/lib/doorkeeper/oauth/refresh_token_request.rb +45 -33
  62. data/lib/doorkeeper/oauth/token.rb +6 -7
  63. data/lib/doorkeeper/oauth/token_introspection.rb +24 -18
  64. data/lib/doorkeeper/oauth/token_request.rb +6 -20
  65. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  66. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  67. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  68. data/lib/doorkeeper/orm/active_record/application.rb +5 -83
  69. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +68 -0
  70. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +59 -0
  71. data/lib/doorkeeper/orm/active_record/mixins/application.rb +198 -0
  72. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +66 -0
  73. data/lib/doorkeeper/orm/active_record.rb +20 -6
  74. data/lib/doorkeeper/rails/helpers.rb +4 -4
  75. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  76. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  77. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  78. data/lib/doorkeeper/rails/routes.rb +17 -25
  79. data/lib/doorkeeper/rake/db.rake +6 -6
  80. data/lib/doorkeeper/rake/setup.rake +5 -0
  81. data/lib/doorkeeper/request/authorization_code.rb +5 -3
  82. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  83. data/lib/doorkeeper/request/password.rb +2 -2
  84. data/lib/doorkeeper/request/refresh_token.rb +5 -4
  85. data/lib/doorkeeper/request/strategy.rb +2 -2
  86. data/lib/doorkeeper/request.rb +49 -17
  87. data/lib/doorkeeper/server.rb +7 -11
  88. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  89. data/lib/doorkeeper/version.rb +1 -5
  90. data/lib/doorkeeper.rb +114 -79
  91. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  92. data/lib/generators/doorkeeper/confidential_applications_generator.rb +2 -2
  93. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  94. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  95. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  96. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
  97. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +3 -1
  98. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  99. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  100. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  101. data/lib/generators/doorkeeper/templates/initializer.rb +205 -43
  102. data/lib/generators/doorkeeper/templates/migration.rb.erb +18 -6
  103. metadata +43 -310
  104. data/.coveralls.yml +0 -1
  105. data/.github/ISSUE_TEMPLATE.md +0 -25
  106. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  107. data/.gitignore +0 -20
  108. data/.gitlab-ci.yml +0 -16
  109. data/.hound.yml +0 -3
  110. data/.rspec +0 -1
  111. data/.rubocop.yml +0 -50
  112. data/.travis.yml +0 -35
  113. data/Appraisals +0 -40
  114. data/CODE_OF_CONDUCT.md +0 -46
  115. data/CONTRIBUTING.md +0 -47
  116. data/Dangerfile +0 -67
  117. data/Gemfile +0 -24
  118. data/RELEASING.md +0 -10
  119. data/Rakefile +0 -28
  120. data/SECURITY.md +0 -15
  121. data/UPGRADE.md +0 -2
  122. data/app/validators/redirect_uri_validator.rb +0 -50
  123. data/bin/console +0 -16
  124. data/doorkeeper.gemspec +0 -34
  125. data/gemfiles/rails_5_0.gemfile +0 -17
  126. data/gemfiles/rails_5_1.gemfile +0 -17
  127. data/gemfiles/rails_5_2.gemfile +0 -17
  128. data/gemfiles/rails_6_0.gemfile +0 -17
  129. data/gemfiles/rails_master.gemfile +0 -17
  130. data/spec/controllers/application_metal_controller_spec.rb +0 -64
  131. data/spec/controllers/applications_controller_spec.rb +0 -180
  132. data/spec/controllers/authorizations_controller_spec.rb +0 -527
  133. data/spec/controllers/protected_resources_controller_spec.rb +0 -353
  134. data/spec/controllers/token_info_controller_spec.rb +0 -50
  135. data/spec/controllers/tokens_controller_spec.rb +0 -330
  136. data/spec/dummy/Rakefile +0 -9
  137. data/spec/dummy/app/assets/config/manifest.js +0 -2
  138. data/spec/dummy/app/controllers/application_controller.rb +0 -5
  139. data/spec/dummy/app/controllers/custom_authorizations_controller.rb +0 -9
  140. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +0 -14
  141. data/spec/dummy/app/controllers/home_controller.rb +0 -18
  142. data/spec/dummy/app/controllers/metal_controller.rb +0 -13
  143. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +0 -13
  144. data/spec/dummy/app/helpers/application_helper.rb +0 -7
  145. data/spec/dummy/app/models/user.rb +0 -7
  146. data/spec/dummy/app/views/home/index.html.erb +0 -0
  147. data/spec/dummy/app/views/layouts/application.html.erb +0 -14
  148. data/spec/dummy/config/application.rb +0 -47
  149. data/spec/dummy/config/boot.rb +0 -7
  150. data/spec/dummy/config/database.yml +0 -15
  151. data/spec/dummy/config/environment.rb +0 -5
  152. data/spec/dummy/config/environments/development.rb +0 -31
  153. data/spec/dummy/config/environments/production.rb +0 -64
  154. data/spec/dummy/config/environments/test.rb +0 -45
  155. data/spec/dummy/config/initializers/backtrace_silencers.rb +0 -9
  156. data/spec/dummy/config/initializers/doorkeeper.rb +0 -121
  157. data/spec/dummy/config/initializers/secret_token.rb +0 -10
  158. data/spec/dummy/config/initializers/session_store.rb +0 -10
  159. data/spec/dummy/config/initializers/wrap_parameters.rb +0 -16
  160. data/spec/dummy/config/locales/doorkeeper.en.yml +0 -5
  161. data/spec/dummy/config/routes.rb +0 -13
  162. data/spec/dummy/config.ru +0 -6
  163. data/spec/dummy/db/migrate/20111122132257_create_users.rb +0 -11
  164. data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +0 -7
  165. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +0 -69
  166. data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +0 -9
  167. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +0 -13
  168. data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +0 -8
  169. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +0 -13
  170. data/spec/dummy/db/schema.rb +0 -68
  171. data/spec/dummy/public/404.html +0 -26
  172. data/spec/dummy/public/422.html +0 -26
  173. data/spec/dummy/public/500.html +0 -26
  174. data/spec/dummy/public/favicon.ico +0 -0
  175. data/spec/dummy/script/rails +0 -9
  176. data/spec/factories.rb +0 -30
  177. data/spec/generators/application_owner_generator_spec.rb +0 -28
  178. data/spec/generators/confidential_applications_generator_spec.rb +0 -29
  179. data/spec/generators/install_generator_spec.rb +0 -36
  180. data/spec/generators/migration_generator_spec.rb +0 -28
  181. data/spec/generators/pkce_generator_spec.rb +0 -28
  182. data/spec/generators/previous_refresh_token_generator_spec.rb +0 -44
  183. data/spec/generators/templates/routes.rb +0 -4
  184. data/spec/generators/views_generator_spec.rb +0 -29
  185. data/spec/grape/grape_integration_spec.rb +0 -137
  186. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +0 -26
  187. data/spec/lib/config_spec.rb +0 -697
  188. data/spec/lib/doorkeeper_spec.rb +0 -27
  189. data/spec/lib/models/expirable_spec.rb +0 -61
  190. data/spec/lib/models/reusable_spec.rb +0 -40
  191. data/spec/lib/models/revocable_spec.rb +0 -59
  192. data/spec/lib/models/scopes_spec.rb +0 -53
  193. data/spec/lib/models/secret_storable_spec.rb +0 -135
  194. data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -39
  195. data/spec/lib/oauth/authorization_code_request_spec.rb +0 -156
  196. data/spec/lib/oauth/base_request_spec.rb +0 -205
  197. data/spec/lib/oauth/base_response_spec.rb +0 -47
  198. data/spec/lib/oauth/client/credentials_spec.rb +0 -90
  199. data/spec/lib/oauth/client_credentials/creator_spec.rb +0 -94
  200. data/spec/lib/oauth/client_credentials/issuer_spec.rb +0 -112
  201. data/spec/lib/oauth/client_credentials/validation_spec.rb +0 -59
  202. data/spec/lib/oauth/client_credentials_integration_spec.rb +0 -29
  203. data/spec/lib/oauth/client_credentials_request_spec.rb +0 -109
  204. data/spec/lib/oauth/client_spec.rb +0 -38
  205. data/spec/lib/oauth/code_request_spec.rb +0 -47
  206. data/spec/lib/oauth/code_response_spec.rb +0 -36
  207. data/spec/lib/oauth/error_response_spec.rb +0 -66
  208. data/spec/lib/oauth/error_spec.rb +0 -23
  209. data/spec/lib/oauth/forbidden_token_response_spec.rb +0 -22
  210. data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -98
  211. data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -21
  212. data/spec/lib/oauth/helpers/uri_checker_spec.rb +0 -247
  213. data/spec/lib/oauth/invalid_token_response_spec.rb +0 -55
  214. data/spec/lib/oauth/password_access_token_request_spec.rb +0 -192
  215. data/spec/lib/oauth/pre_authorization_spec.rb +0 -215
  216. data/spec/lib/oauth/refresh_token_request_spec.rb +0 -177
  217. data/spec/lib/oauth/scopes_spec.rb +0 -148
  218. data/spec/lib/oauth/token_request_spec.rb +0 -150
  219. data/spec/lib/oauth/token_response_spec.rb +0 -86
  220. data/spec/lib/oauth/token_spec.rb +0 -158
  221. data/spec/lib/request/strategy_spec.rb +0 -54
  222. data/spec/lib/secret_storing/base_spec.rb +0 -60
  223. data/spec/lib/secret_storing/bcrypt_spec.rb +0 -49
  224. data/spec/lib/secret_storing/plain_spec.rb +0 -44
  225. data/spec/lib/secret_storing/sha256_hash_spec.rb +0 -48
  226. data/spec/lib/server_spec.rb +0 -61
  227. data/spec/lib/stale_records_cleaner_spec.rb +0 -89
  228. data/spec/models/doorkeeper/access_grant_spec.rb +0 -144
  229. data/spec/models/doorkeeper/access_token_spec.rb +0 -591
  230. data/spec/models/doorkeeper/application_spec.rb +0 -367
  231. data/spec/requests/applications/applications_request_spec.rb +0 -259
  232. data/spec/requests/applications/authorized_applications_spec.rb +0 -32
  233. data/spec/requests/endpoints/authorization_spec.rb +0 -73
  234. data/spec/requests/endpoints/token_spec.rb +0 -75
  235. data/spec/requests/flows/authorization_code_errors_spec.rb +0 -78
  236. data/spec/requests/flows/authorization_code_spec.rb +0 -447
  237. data/spec/requests/flows/client_credentials_spec.rb +0 -128
  238. data/spec/requests/flows/implicit_grant_errors_spec.rb +0 -34
  239. data/spec/requests/flows/implicit_grant_spec.rb +0 -90
  240. data/spec/requests/flows/password_spec.rb +0 -259
  241. data/spec/requests/flows/refresh_token_spec.rb +0 -233
  242. data/spec/requests/flows/revoke_token_spec.rb +0 -143
  243. data/spec/requests/flows/skip_authorization_spec.rb +0 -66
  244. data/spec/requests/protected_resources/metal_spec.rb +0 -16
  245. data/spec/requests/protected_resources/private_api_spec.rb +0 -83
  246. data/spec/routing/custom_controller_routes_spec.rb +0 -133
  247. data/spec/routing/default_routes_spec.rb +0 -41
  248. data/spec/routing/scoped_routes_spec.rb +0 -47
  249. data/spec/spec_helper.rb +0 -57
  250. data/spec/spec_helper_integration.rb +0 -4
  251. data/spec/support/dependencies/factory_bot.rb +0 -4
  252. data/spec/support/doorkeeper_rspec.rb +0 -22
  253. data/spec/support/helpers/access_token_request_helper.rb +0 -13
  254. data/spec/support/helpers/authorization_request_helper.rb +0 -43
  255. data/spec/support/helpers/config_helper.rb +0 -11
  256. data/spec/support/helpers/model_helper.rb +0 -78
  257. data/spec/support/helpers/request_spec_helper.rb +0 -98
  258. data/spec/support/helpers/url_helper.rb +0 -62
  259. data/spec/support/http_method_shim.rb +0 -29
  260. data/spec/support/orm/active_record.rb +0 -5
  261. data/spec/support/shared/controllers_shared_context.rb +0 -123
  262. data/spec/support/shared/hashing_shared_context.rb +0 -36
  263. data/spec/support/shared/models_shared_examples.rb +0 -54
  264. data/spec/validators/redirect_uri_validator_spec.rb +0 -158
  265. 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