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