doorkeeper 5.2.6 → 5.3.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/Appraisals +2 -2
- data/CHANGELOG.md +15 -14
- data/Gemfile +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -2
- data/app/controllers/doorkeeper/applications_controller.rb +3 -3
- data/app/controllers/doorkeeper/authorizations_controller.rb +2 -2
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
- data/gemfiles/rails_5_0.gemfile +2 -2
- data/gemfiles/rails_5_1.gemfile +2 -2
- data/gemfiles/rails_5_2.gemfile +2 -2
- data/gemfiles/rails_6_0.gemfile +2 -2
- data/gemfiles/rails_master.gemfile +2 -2
- data/lib/doorkeeper.rb +2 -3
- data/lib/doorkeeper/config.rb +71 -39
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +10 -8
- data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
- data/lib/doorkeeper/models/access_token_mixin.rb +55 -18
- data/lib/doorkeeper/models/application_mixin.rb +3 -3
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
- data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +0 -27
- data/lib/doorkeeper/oauth/authorization/code.rb +4 -4
- data/lib/doorkeeper/oauth/authorization/token.rb +9 -6
- data/lib/doorkeeper/oauth/authorization_code_request.rb +13 -6
- data/lib/doorkeeper/oauth/base_request.rb +8 -4
- data/lib/doorkeeper/oauth/client.rb +7 -8
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +16 -9
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
- data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +4 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +5 -5
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +7 -5
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -1
- data/lib/doorkeeper/oauth/invalid_request_response.rb +3 -3
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
- data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -3
- data/lib/doorkeeper/oauth/pre_authorization.rb +7 -5
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -5
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +6 -6
- data/lib/doorkeeper/orm/active_record.rb +3 -3
- data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
- data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
- data/lib/doorkeeper/orm/active_record/application.rb +3 -155
- data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +53 -0
- data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +47 -0
- data/lib/doorkeeper/orm/active_record/mixins/application.rb +128 -0
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +3 -3
- data/lib/doorkeeper/rails/helpers.rb +4 -4
- data/lib/doorkeeper/rails/routes.rb +5 -7
- data/lib/doorkeeper/rake/db.rake +3 -3
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/request/authorization_code.rb +3 -3
- data/lib/doorkeeper/request/client_credentials.rb +2 -2
- data/lib/doorkeeper/request/password.rb +2 -2
- data/lib/doorkeeper/request/refresh_token.rb +3 -3
- data/lib/doorkeeper/server.rb +1 -1
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +2 -2
- data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
- data/lib/generators/doorkeeper/migration_generator.rb +1 -1
- data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +2 -2
- data/lib/generators/doorkeeper/templates/initializer.rb +39 -8
- data/spec/controllers/application_metal_controller_spec.rb +1 -1
- data/spec/controllers/applications_controller_spec.rb +3 -2
- data/spec/controllers/authorizations_controller_spec.rb +18 -18
- data/spec/controllers/protected_resources_controller_spec.rb +25 -17
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +1 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -3
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +1 -1
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +1 -1
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/previous_refresh_token_generator_spec.rb +2 -2
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +61 -21
- data/spec/lib/doorkeeper_spec.rb +1 -1
- data/spec/lib/models/revocable_spec.rb +3 -3
- data/spec/lib/oauth/authorization_code_request_spec.rb +127 -125
- data/spec/lib/oauth/base_request_spec.rb +160 -158
- data/spec/lib/oauth/base_response_spec.rb +27 -29
- data/spec/lib/oauth/client/credentials_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials/creator_spec.rb +42 -5
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +12 -12
- data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
- data/spec/lib/oauth/client_credentials_integration_spec.rb +16 -18
- data/spec/lib/oauth/client_credentials_request_spec.rb +78 -80
- data/spec/lib/oauth/client_spec.rb +26 -26
- data/spec/lib/oauth/code_request_spec.rb +34 -34
- data/spec/lib/oauth/code_response_spec.rb +21 -25
- data/spec/lib/oauth/error_response_spec.rb +42 -44
- data/spec/lib/oauth/error_spec.rb +12 -14
- data/spec/lib/oauth/forbidden_token_response_spec.rb +11 -13
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +30 -18
- data/spec/lib/oauth/invalid_request_response_spec.rb +48 -50
- data/spec/lib/oauth/invalid_token_response_spec.rb +32 -34
- data/spec/lib/oauth/password_access_token_request_spec.rb +145 -147
- data/spec/lib/oauth/pre_authorization_spec.rb +159 -161
- data/spec/lib/oauth/refresh_token_request_spec.rb +138 -139
- data/spec/lib/oauth/scopes_spec.rb +104 -106
- data/spec/lib/oauth/token_request_spec.rb +115 -111
- data/spec/lib/oauth/token_response_spec.rb +71 -73
- data/spec/lib/oauth/token_spec.rb +121 -123
- data/spec/models/doorkeeper/access_grant_spec.rb +3 -5
- data/spec/models/doorkeeper/access_token_spec.rb +7 -7
- data/spec/models/doorkeeper/application_spec.rb +295 -373
- data/spec/requests/applications/applications_request_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +5 -3
- data/spec/requests/flows/authorization_code_spec.rb +34 -22
- data/spec/requests/flows/client_credentials_spec.rb +1 -1
- data/spec/requests/flows/password_spec.rb +32 -12
- data/spec/requests/flows/refresh_token_spec.rb +19 -19
- data/spec/requests/flows/revoke_token_spec.rb +18 -12
- data/spec/spec_helper.rb +1 -4
- data/spec/support/shared/controllers_shared_context.rb +33 -23
- data/spec/validators/redirect_uri_validator_spec.rb +1 -1
- metadata +6 -5
- data/spec/support/http_method_shim.rb +0 -29
@@ -2,152 +2,156 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
end
|
5
|
+
describe Doorkeeper::OAuth::TokenRequest do
|
6
|
+
let :application do
|
7
|
+
FactoryBot.create(:application, scopes: "public")
|
8
|
+
end
|
10
9
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
let :pre_auth do
|
11
|
+
server = Doorkeeper.configuration
|
12
|
+
allow(server).to receive(:default_scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("public"))
|
13
|
+
allow(server).to receive(:grant_flows).and_return(Doorkeeper::OAuth::Scopes.from_string("implicit"))
|
15
14
|
|
16
|
-
|
15
|
+
client = Doorkeeper::OAuth::Client.new(application)
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
17
|
+
attributes = {
|
18
|
+
client_id: client.uid,
|
19
|
+
response_type: "token",
|
20
|
+
redirect_uri: "https://app.com/callback",
|
21
|
+
}
|
23
22
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
pre_auth = Doorkeeper::OAuth::PreAuthorization.new(server, attributes)
|
24
|
+
pre_auth.authorizable?
|
25
|
+
pre_auth
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
28
|
+
let :owner do
|
29
|
+
double :owner, id: 7866
|
30
|
+
end
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
32
|
+
subject do
|
33
|
+
described_class.new(pre_auth, owner)
|
34
|
+
end
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
36
|
+
it "creates an access token" do
|
37
|
+
expect do
|
38
|
+
subject.authorize
|
39
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
40
|
+
end
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
|
42
|
+
it "returns a code response" do
|
43
|
+
expect(subject.authorize).to be_a(Doorkeeper::OAuth::CodeResponse)
|
44
|
+
end
|
46
45
|
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
end
|
46
|
+
context "when pre_auth is denied" do
|
47
|
+
it "does not create token and returns a error response" do
|
48
|
+
expect { subject.deny }.not_to(change { Doorkeeper::AccessToken.count })
|
49
|
+
expect(subject.deny).to be_a(Doorkeeper::OAuth::ErrorResponse)
|
52
50
|
end
|
51
|
+
end
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
end
|
53
|
+
describe "with custom expiration" do
|
54
|
+
context "when proper TTL returned" do
|
55
|
+
before do
|
56
|
+
Doorkeeper.configure do
|
57
|
+
orm DOORKEEPER_ORM
|
58
|
+
custom_access_token_expires_in do |context|
|
59
|
+
context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
|
62
60
|
end
|
63
61
|
end
|
62
|
+
end
|
64
63
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
end
|
64
|
+
it "should use the custom ttl" do
|
65
|
+
subject.authorize
|
66
|
+
token = Doorkeeper::AccessToken.first
|
67
|
+
expect(token.expires_in).to eq(1234)
|
70
68
|
end
|
69
|
+
end
|
71
70
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
end
|
71
|
+
context "when nil TTL returned" do
|
72
|
+
before do
|
73
|
+
Doorkeeper.configure do
|
74
|
+
orm DOORKEEPER_ORM
|
75
|
+
access_token_expires_in 654
|
76
|
+
custom_access_token_expires_in do |_context|
|
77
|
+
nil
|
80
78
|
end
|
81
79
|
end
|
80
|
+
end
|
82
81
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
82
|
+
it "should fallback to access_token_expires_in" do
|
83
|
+
subject.authorize
|
84
|
+
token = Doorkeeper::AccessToken.first
|
85
|
+
expect(token.expires_in).to eq(654)
|
88
86
|
end
|
87
|
+
end
|
89
88
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
end
|
89
|
+
context "when infinite TTL returned" do
|
90
|
+
before do
|
91
|
+
Doorkeeper.configure do
|
92
|
+
orm DOORKEEPER_ORM
|
93
|
+
access_token_expires_in 654
|
94
|
+
custom_access_token_expires_in do |_context|
|
95
|
+
Float::INFINITY
|
98
96
|
end
|
99
97
|
end
|
98
|
+
end
|
100
99
|
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
end
|
100
|
+
it "should fallback to access_token_expires_in" do
|
101
|
+
subject.authorize
|
102
|
+
token = Doorkeeper::AccessToken.first
|
103
|
+
expect(token.expires_in).to be_nil
|
106
104
|
end
|
107
105
|
end
|
106
|
+
end
|
108
107
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
108
|
+
context "token reuse" do
|
109
|
+
it "creates a new token if there are no matching tokens" do
|
110
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
111
|
+
expect do
|
112
|
+
subject.authorize
|
113
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
114
|
+
end
|
116
115
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
116
|
+
it "creates a new token if scopes do not match" do
|
117
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
118
|
+
FactoryBot.create(
|
119
|
+
:access_token, application_id: pre_auth.client.id,
|
120
|
+
resource_owner_id: owner.id, scopes: "",
|
121
|
+
)
|
122
|
+
expect do
|
123
|
+
subject.authorize
|
124
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
125
|
+
end
|
125
126
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
127
|
+
it "skips token creation if there is a matching one reusable" do
|
128
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
129
|
+
allow(application.scopes).to receive(:has_scopes?).and_return(true)
|
130
|
+
allow(application.scopes).to receive(:all?).and_return(true)
|
130
131
|
|
131
|
-
|
132
|
-
|
132
|
+
FactoryBot.create(
|
133
|
+
:access_token, application_id: pre_auth.client.id,
|
134
|
+
resource_owner_id: owner.id, scopes: "public",
|
135
|
+
)
|
133
136
|
|
134
|
-
|
135
|
-
|
137
|
+
expect { subject.authorize }.not_to(change { Doorkeeper::AccessToken.count })
|
138
|
+
end
|
136
139
|
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
140
|
+
it "creates new token if there is a matching one but non reusable" do
|
141
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
142
|
+
allow(application.scopes).to receive(:has_scopes?).and_return(true)
|
143
|
+
allow(application.scopes).to receive(:all?).and_return(true)
|
141
144
|
|
142
|
-
|
143
|
-
|
145
|
+
FactoryBot.create(
|
146
|
+
:access_token, application_id: pre_auth.client.id,
|
147
|
+
resource_owner_id: owner.id, scopes: "public",
|
148
|
+
)
|
144
149
|
|
145
|
-
|
150
|
+
allow_any_instance_of(Doorkeeper::AccessToken).to receive(:reusable?).and_return(false)
|
146
151
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
end
|
152
|
+
expect do
|
153
|
+
subject.authorize
|
154
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
151
155
|
end
|
152
156
|
end
|
153
157
|
end
|
@@ -2,85 +2,83 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
5
|
+
describe Doorkeeper::OAuth::TokenResponse do
|
6
|
+
subject { described_class.new(double.as_null_object) }
|
7
|
+
|
8
|
+
it "includes access token response headers" do
|
9
|
+
headers = subject.headers
|
10
|
+
expect(headers.fetch("Cache-Control")).to eq("no-store")
|
11
|
+
expect(headers.fetch("Pragma")).to eq("no-cache")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "status is ok" do
|
15
|
+
expect(subject.status).to eq(:ok)
|
16
|
+
end
|
17
|
+
|
18
|
+
describe ".body" do
|
19
|
+
let(:access_token) do
|
20
|
+
double :access_token,
|
21
|
+
plaintext_token: "some-token",
|
22
|
+
expires_in: "3600",
|
23
|
+
expires_in_seconds: "300",
|
24
|
+
scopes_string: "two scopes",
|
25
|
+
plaintext_refresh_token: "some-refresh-token",
|
26
|
+
token_type: "bearer",
|
27
|
+
created_at: 0
|
28
|
+
end
|
29
|
+
|
30
|
+
subject { described_class.new(access_token).body }
|
31
|
+
|
32
|
+
it "includes :access_token" do
|
33
|
+
expect(subject["access_token"]).to eq("some-token")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "includes :token_type" do
|
37
|
+
expect(subject["token_type"]).to eq("bearer")
|
38
|
+
end
|
39
|
+
|
40
|
+
# expires_in_seconds is returned as `expires_in` in order to match
|
41
|
+
# the OAuth spec (section 4.2.2)
|
42
|
+
it "includes :expires_in" do
|
43
|
+
expect(subject["expires_in"]).to eq("300")
|
44
|
+
end
|
45
|
+
|
46
|
+
it "includes :scope" do
|
47
|
+
expect(subject["scope"]).to eq("two scopes")
|
13
48
|
end
|
14
49
|
|
15
|
-
it "
|
16
|
-
expect(subject
|
50
|
+
it "includes :refresh_token" do
|
51
|
+
expect(subject["refresh_token"]).to eq("some-refresh-token")
|
52
|
+
end
|
53
|
+
|
54
|
+
it "includes :created_at" do
|
55
|
+
expect(subject["created_at"]).to eq(0)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe ".body filters out empty values" do
|
60
|
+
let(:access_token) do
|
61
|
+
double :access_token,
|
62
|
+
plaintext_token: "some-token",
|
63
|
+
expires_in_seconds: "",
|
64
|
+
scopes_string: "",
|
65
|
+
plaintext_refresh_token: "",
|
66
|
+
token_type: "bearer",
|
67
|
+
created_at: 0
|
68
|
+
end
|
69
|
+
|
70
|
+
subject { described_class.new(access_token).body }
|
71
|
+
|
72
|
+
it "includes :expires_in" do
|
73
|
+
expect(subject["expires_in"]).to be_nil
|
17
74
|
end
|
18
75
|
|
19
|
-
|
20
|
-
|
21
|
-
double :access_token,
|
22
|
-
plaintext_token: "some-token",
|
23
|
-
expires_in: "3600",
|
24
|
-
expires_in_seconds: "300",
|
25
|
-
scopes_string: "two scopes",
|
26
|
-
plaintext_refresh_token: "some-refresh-token",
|
27
|
-
token_type: "bearer",
|
28
|
-
created_at: 0
|
29
|
-
end
|
30
|
-
|
31
|
-
subject { TokenResponse.new(access_token).body }
|
32
|
-
|
33
|
-
it "includes :access_token" do
|
34
|
-
expect(subject["access_token"]).to eq("some-token")
|
35
|
-
end
|
36
|
-
|
37
|
-
it "includes :token_type" do
|
38
|
-
expect(subject["token_type"]).to eq("bearer")
|
39
|
-
end
|
40
|
-
|
41
|
-
# expires_in_seconds is returned as `expires_in` in order to match
|
42
|
-
# the OAuth spec (section 4.2.2)
|
43
|
-
it "includes :expires_in" do
|
44
|
-
expect(subject["expires_in"]).to eq("300")
|
45
|
-
end
|
46
|
-
|
47
|
-
it "includes :scope" do
|
48
|
-
expect(subject["scope"]).to eq("two scopes")
|
49
|
-
end
|
50
|
-
|
51
|
-
it "includes :refresh_token" do
|
52
|
-
expect(subject["refresh_token"]).to eq("some-refresh-token")
|
53
|
-
end
|
54
|
-
|
55
|
-
it "includes :created_at" do
|
56
|
-
expect(subject["created_at"]).to eq(0)
|
57
|
-
end
|
76
|
+
it "includes :scope" do
|
77
|
+
expect(subject["scope"]).to be_nil
|
58
78
|
end
|
59
79
|
|
60
|
-
|
61
|
-
|
62
|
-
double :access_token,
|
63
|
-
plaintext_token: "some-token",
|
64
|
-
expires_in_seconds: "",
|
65
|
-
scopes_string: "",
|
66
|
-
plaintext_refresh_token: "",
|
67
|
-
token_type: "bearer",
|
68
|
-
created_at: 0
|
69
|
-
end
|
70
|
-
|
71
|
-
subject { TokenResponse.new(access_token).body }
|
72
|
-
|
73
|
-
it "includes :expires_in" do
|
74
|
-
expect(subject["expires_in"]).to be_nil
|
75
|
-
end
|
76
|
-
|
77
|
-
it "includes :scope" do
|
78
|
-
expect(subject["scope"]).to be_nil
|
79
|
-
end
|
80
|
-
|
81
|
-
it "includes :refresh_token" do
|
82
|
-
expect(subject["refresh_token"]).to be_nil
|
83
|
-
end
|
80
|
+
it "includes :refresh_token" do
|
81
|
+
expect(subject["refresh_token"]).to be_nil
|
84
82
|
end
|
85
83
|
end
|
86
84
|
end
|
@@ -7,152 +7,150 @@ module Doorkeeper
|
|
7
7
|
class AccessToken
|
8
8
|
end
|
9
9
|
end
|
10
|
+
end
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
let(:request) { double.as_null_object }
|
12
|
+
describe Doorkeeper::OAuth::Token do
|
13
|
+
describe ".from_request" do
|
14
|
+
let(:request) { double.as_null_object }
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
let(:method) do
|
17
|
+
->(*) { "token-value" }
|
18
|
+
end
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
it "accepts anything that responds to #call" do
|
21
|
+
expect(method).to receive(:call).with(request)
|
22
|
+
described_class.from_request request, method
|
23
|
+
end
|
24
24
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
25
|
+
it "delegates methods received as symbols to described_class class" do
|
26
|
+
expect(described_class).to receive(:from_params).with(request)
|
27
|
+
described_class.from_request request, :from_params
|
28
|
+
end
|
29
29
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
30
|
+
it "stops at the first credentials found" do
|
31
|
+
not_called_method = double
|
32
|
+
expect(not_called_method).not_to receive(:call)
|
33
|
+
described_class.from_request request, ->(_r) {}, method, not_called_method
|
34
|
+
end
|
35
35
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
it "returns the credential from extractor method" do
|
37
|
+
credentials = described_class.from_request request, method
|
38
|
+
expect(credentials).to eq("token-value")
|
39
|
+
end
|
40
|
+
end
|
41
41
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
42
|
+
describe ".from_access_token_param" do
|
43
|
+
it "returns token from access_token parameter" do
|
44
|
+
request = double parameters: { access_token: "some-token" }
|
45
|
+
token = described_class.from_access_token_param(request)
|
46
|
+
expect(token).to eq("some-token")
|
47
|
+
end
|
48
|
+
end
|
49
49
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
50
|
+
describe ".from_bearer_param" do
|
51
|
+
it "returns token from bearer_token parameter" do
|
52
|
+
request = double parameters: { bearer_token: "some-token" }
|
53
|
+
token = described_class.from_bearer_param(request)
|
54
|
+
expect(token).to eq("some-token")
|
55
|
+
end
|
56
|
+
end
|
57
57
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
58
|
+
describe ".from_bearer_authorization" do
|
59
|
+
it "returns token from capitalized authorization bearer" do
|
60
|
+
request = double authorization: "Bearer SomeToken"
|
61
|
+
token = described_class.from_bearer_authorization(request)
|
62
|
+
expect(token).to eq("SomeToken")
|
63
|
+
end
|
64
64
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
65
|
+
it "returns token from lowercased authorization bearer" do
|
66
|
+
request = double authorization: "bearer SomeToken"
|
67
|
+
token = described_class.from_bearer_authorization(request)
|
68
|
+
expect(token).to eq("SomeToken")
|
69
|
+
end
|
70
70
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
71
|
+
it "does not return token if authorization is not bearer" do
|
72
|
+
request = double authorization: "MAC SomeToken"
|
73
|
+
token = described_class.from_bearer_authorization(request)
|
74
|
+
expect(token).to be_blank
|
75
|
+
end
|
76
|
+
end
|
77
77
|
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
78
|
+
describe ".from_basic_authorization" do
|
79
|
+
it "returns token from capitalized authorization basic" do
|
80
|
+
request = double authorization: "Basic #{Base64.encode64 "SomeToken:"}"
|
81
|
+
token = described_class.from_basic_authorization(request)
|
82
|
+
expect(token).to eq("SomeToken")
|
83
|
+
end
|
84
84
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
85
|
+
it "returns token from lowercased authorization basic" do
|
86
|
+
request = double authorization: "basic #{Base64.encode64 "SomeToken:"}"
|
87
|
+
token = described_class.from_basic_authorization(request)
|
88
|
+
expect(token).to eq("SomeToken")
|
89
|
+
end
|
90
90
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
91
|
+
it "does not return token if authorization is not basic" do
|
92
|
+
request = double authorization: "MAC #{Base64.encode64 "SomeToken:"}"
|
93
|
+
token = described_class.from_basic_authorization(request)
|
94
|
+
expect(token).to be_blank
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe ".authenticate" do
|
99
|
+
context "refresh tokens are disabled (default)" do
|
100
|
+
context "refresh tokens are enabled" do
|
101
|
+
it "does not revoke previous refresh_token if token was found" do
|
102
|
+
token = ->(_r) { "token" }
|
103
|
+
expect(
|
104
|
+
Doorkeeper::AccessToken,
|
105
|
+
).to receive(:by_token).with("token").and_return(token)
|
106
|
+
expect(token).not_to receive(:revoke_previous_refresh_token!)
|
107
|
+
described_class.authenticate double, token
|
95
108
|
end
|
96
109
|
end
|
97
110
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
AccessToken
|
105
|
-
).to receive(:by_token).with("token").and_return(token)
|
106
|
-
expect(token).not_to receive(:revoke_previous_refresh_token!)
|
107
|
-
Token.authenticate double, token
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
it "calls the finder if token was returned" do
|
112
|
-
token = ->(_r) { "token" }
|
113
|
-
expect(AccessToken).to receive(:by_token).with("token")
|
114
|
-
Token.authenticate double, token
|
115
|
-
end
|
116
|
-
end
|
111
|
+
it "calls the finder if token was returned" do
|
112
|
+
token = ->(_r) { "token" }
|
113
|
+
expect(Doorkeeper::AccessToken).to receive(:by_token).with("token")
|
114
|
+
described_class.authenticate double, token
|
115
|
+
end
|
116
|
+
end
|
117
117
|
|
118
|
-
|
119
|
-
|
118
|
+
context "token hashing is enabled" do
|
119
|
+
include_context "with token hashing enabled"
|
120
120
|
|
121
|
-
|
122
|
-
|
121
|
+
let(:hashed_token) { hashed_or_plain_token_func.call("token") }
|
122
|
+
let(:token) { ->(_r) { "token" } }
|
123
123
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
124
|
+
it "searches with the hashed token" do
|
125
|
+
expect(
|
126
|
+
Doorkeeper::AccessToken,
|
127
|
+
).to receive(:find_by).with(token: hashed_token).and_return(token)
|
128
|
+
described_class.authenticate double, token
|
129
|
+
end
|
130
|
+
end
|
131
131
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
it "revokes previous refresh_token if token was found" do
|
141
|
-
token = ->(_r) { "token" }
|
142
|
-
expect(
|
143
|
-
AccessToken
|
144
|
-
).to receive(:by_token).with("token").and_return(token)
|
145
|
-
expect(token).to receive(:revoke_previous_refresh_token!)
|
146
|
-
Token.authenticate double, token
|
147
|
-
end
|
148
|
-
|
149
|
-
it "calls the finder if token was returned" do
|
150
|
-
token = ->(_r) { "token" }
|
151
|
-
expect(AccessToken).to receive(:by_token).with("token")
|
152
|
-
Token.authenticate double, token
|
153
|
-
end
|
132
|
+
context "refresh tokens are enabled" do
|
133
|
+
before do
|
134
|
+
Doorkeeper.configure do
|
135
|
+
orm DOORKEEPER_ORM
|
136
|
+
use_refresh_token
|
154
137
|
end
|
155
138
|
end
|
139
|
+
|
140
|
+
it "revokes previous refresh_token if token was found" do
|
141
|
+
token = ->(_r) { "token" }
|
142
|
+
expect(
|
143
|
+
Doorkeeper::AccessToken,
|
144
|
+
).to receive(:by_token).with("token").and_return(token)
|
145
|
+
expect(token).to receive(:revoke_previous_refresh_token!)
|
146
|
+
described_class.authenticate double, token
|
147
|
+
end
|
148
|
+
|
149
|
+
it "calls the finder if token was returned" do
|
150
|
+
token = ->(_r) { "token" }
|
151
|
+
expect(Doorkeeper::AccessToken).to receive(:by_token).with("token")
|
152
|
+
described_class.authenticate double, token
|
153
|
+
end
|
156
154
|
end
|
157
155
|
end
|
158
156
|
end
|