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