doorkeeper 5.0.3 → 5.1.0.rc1
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/.travis.yml +7 -3
- data/Dangerfile +5 -2
- data/Gemfile +3 -1
- data/NEWS.md +20 -13
- data/README.md +1 -1
- data/app/controllers/doorkeeper/applications_controller.rb +3 -3
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +6 -6
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
- data/bin/console +15 -0
- data/gemfiles/rails_4_2.gemfile +1 -0
- data/gemfiles/rails_5_0.gemfile +1 -0
- data/gemfiles/rails_5_1.gemfile +1 -0
- data/gemfiles/rails_5_2.gemfile +2 -1
- data/gemfiles/rails_master.gemfile +1 -0
- data/lib/doorkeeper.rb +1 -0
- data/lib/doorkeeper/config.rb +73 -6
- data/lib/doorkeeper/helpers/controller.rb +3 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +8 -1
- data/lib/doorkeeper/models/access_token_mixin.rb +40 -9
- data/lib/doorkeeper/models/application_mixin.rb +52 -1
- data/lib/doorkeeper/models/concerns/hashable.rb +137 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/token.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +1 -1
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -3
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +32 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +8 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +4 -1
- data/lib/doorkeeper/oauth/token_response.rb +2 -2
- data/lib/doorkeeper/orm/active_record/access_grant.rb +22 -2
- data/lib/doorkeeper/orm/active_record/application.rb +12 -53
- data/lib/doorkeeper/version.rb +3 -3
- data/lib/generators/doorkeeper/templates/initializer.rb +41 -1
- data/spec/controllers/application_metal_controller_spec.rb +18 -4
- data/spec/controllers/tokens_controller_spec.rb +7 -11
- data/spec/dummy/app/controllers/application_controller.rb +1 -1
- data/spec/factories.rb +3 -3
- data/spec/lib/config_spec.rb +84 -0
- data/spec/lib/models/hashable_spec.rb +183 -0
- data/spec/lib/oauth/base_request_spec.rb +7 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +3 -0
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +52 -17
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +20 -2
- data/spec/lib/oauth/password_access_token_request_spec.rb +32 -11
- data/spec/lib/oauth/pre_authorization_spec.rb +24 -0
- data/spec/lib/oauth/token_response_spec.rb +13 -13
- data/spec/lib/oauth/token_spec.rb +14 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +61 -0
- data/spec/models/doorkeeper/access_token_spec.rb +123 -0
- data/spec/models/doorkeeper/application_spec.rb +227 -295
- data/spec/requests/flows/authorization_code_spec.rb +40 -0
- data/spec/requests/flows/password_spec.rb +4 -2
- data/spec/requests/flows/revoke_token_spec.rb +14 -30
- data/spec/spec_helper.rb +2 -1
- data/spec/support/ruby_2_6_rails_4_2_patch.rb +14 -0
- data/spec/support/shared/hashing_shared_context.rb +29 -0
- metadata +12 -4
data/spec/lib/config_spec.rb
CHANGED
@@ -141,6 +141,22 @@ describe Doorkeeper, 'configuration' do
|
|
141
141
|
end
|
142
142
|
end
|
143
143
|
|
144
|
+
describe 'scopes_by_grant_type' do
|
145
|
+
it 'is {} by default' do
|
146
|
+
expect(subject.scopes_by_grant_type).to eq({})
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'has hash value' do
|
150
|
+
hash = {}
|
151
|
+
Doorkeeper.configure do
|
152
|
+
orm DOORKEEPER_ORM
|
153
|
+
scopes_by_grant_type hash
|
154
|
+
end
|
155
|
+
|
156
|
+
expect(subject.scopes_by_grant_type).to eq(hash)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
144
160
|
describe 'use_refresh_token' do
|
145
161
|
it 'is false by default' do
|
146
162
|
expect(subject.refresh_token_enabled?).to eq(false)
|
@@ -525,4 +541,72 @@ describe Doorkeeper, 'configuration' do
|
|
525
541
|
expect(subject.handle_auth_errors).to eq(:raise)
|
526
542
|
end
|
527
543
|
end
|
544
|
+
|
545
|
+
describe 'hash_application_secrets' do
|
546
|
+
it 'is disabled by default' do
|
547
|
+
expect(subject.hash_application_secrets?).to eq(false)
|
548
|
+
expect(::Doorkeeper::Application.perform_secret_hashing?).to eq(false)
|
549
|
+
end
|
550
|
+
|
551
|
+
context 'when provided' do
|
552
|
+
before do
|
553
|
+
Doorkeeper.configure do
|
554
|
+
reuse_access_token
|
555
|
+
hash_application_secrets
|
556
|
+
end
|
557
|
+
end
|
558
|
+
|
559
|
+
it 'will enable hashing for applications' do
|
560
|
+
expect(subject.reuse_access_token).to eq(true)
|
561
|
+
expect(subject.hash_application_secrets?).to eq(true)
|
562
|
+
|
563
|
+
expect(::Doorkeeper::Application.perform_secret_hashing?).to eq(true)
|
564
|
+
end
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
describe 'hash_token_secrets' do
|
569
|
+
it 'is disabled by default' do
|
570
|
+
expect(subject.hash_token_secrets?).to eq(false)
|
571
|
+
expect(::Doorkeeper::AccessToken.perform_secret_hashing?).to eq(false)
|
572
|
+
expect(::Doorkeeper::AccessGrant.perform_secret_hashing?).to eq(false)
|
573
|
+
end
|
574
|
+
|
575
|
+
context 'when provided' do
|
576
|
+
include_context 'with token hashing enabled'
|
577
|
+
|
578
|
+
it 'will enable hashing for AccessToken and AccessGrant' do
|
579
|
+
expect(subject.hash_token_secrets?).to eq(true)
|
580
|
+
expect(::Doorkeeper::AccessToken.perform_secret_hashing?).to eq(true)
|
581
|
+
expect(::Doorkeeper::AccessGrant.perform_secret_hashing?).to eq(true)
|
582
|
+
end
|
583
|
+
end
|
584
|
+
end
|
585
|
+
|
586
|
+
describe 'fallback_to_plain_secrets' do
|
587
|
+
it 'is disabled by default' do
|
588
|
+
expect(subject.fallback_to_plain_secrets?).to eq(false)
|
589
|
+
end
|
590
|
+
|
591
|
+
context 'when provided' do
|
592
|
+
include_context 'with token hashing and fallback lookup enabled'
|
593
|
+
|
594
|
+
it 'will enable fallbacks' do
|
595
|
+
expect(subject.fallback_to_plain_secrets?).to eq(true)
|
596
|
+
end
|
597
|
+
end
|
598
|
+
end
|
599
|
+
|
600
|
+
describe 'hash_token_secrets together with reuse_access_token' do
|
601
|
+
it 'will disable reuse_access_token' do
|
602
|
+
expect(Rails.logger).to receive(:warn).with(/reuse_access_token will be disabled/)
|
603
|
+
|
604
|
+
Doorkeeper.configure do
|
605
|
+
reuse_access_token
|
606
|
+
hash_token_secrets
|
607
|
+
end
|
608
|
+
|
609
|
+
expect(subject.reuse_access_token).to eq(false)
|
610
|
+
end
|
611
|
+
end
|
528
612
|
end
|
@@ -0,0 +1,183 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe 'Hashable' do
|
6
|
+
let(:clazz) do
|
7
|
+
Class.new do
|
8
|
+
include Doorkeeper::Models::Hashable
|
9
|
+
|
10
|
+
def self.find_by(*)
|
11
|
+
raise 'stub this'
|
12
|
+
end
|
13
|
+
|
14
|
+
def update_column(*)
|
15
|
+
raise 'stub this'
|
16
|
+
end
|
17
|
+
|
18
|
+
def token
|
19
|
+
raise 'stub this'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe :hashed_or_plain_token do
|
25
|
+
let(:enabled_hashing?) { false }
|
26
|
+
subject { clazz.send(:hashed_or_plain_token, 'input') }
|
27
|
+
|
28
|
+
before do
|
29
|
+
allow(clazz).to receive(:perform_secret_hashing?)
|
30
|
+
.and_return enabled_hashing?
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'when no hash function set' do
|
34
|
+
it 'returns the plain input' do
|
35
|
+
expect(subject).to eq 'input'
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when hashing enabled' do
|
39
|
+
let(:enabled_hashing?) { true }
|
40
|
+
|
41
|
+
it 'uses the default function' do
|
42
|
+
expect(clazz)
|
43
|
+
.to receive(:default_hash_function)
|
44
|
+
.with('input')
|
45
|
+
.and_call_original
|
46
|
+
|
47
|
+
expect(subject).not_to eq 'input'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when hash_function defined' do
|
53
|
+
let(:hash_function) { ->(input) { input + '-hashed' } }
|
54
|
+
|
55
|
+
before do
|
56
|
+
clazz.secret_hash_function = hash_function
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'returns the plain input' do
|
60
|
+
expect(clazz).not_to receive(:default_hash_function)
|
61
|
+
expect(subject).to eq 'input'
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'when hashing enabled' do
|
65
|
+
let(:enabled_hashing?) { true }
|
66
|
+
|
67
|
+
it 'uses that function' do
|
68
|
+
expect(hash_function)
|
69
|
+
.to receive(:call)
|
70
|
+
.with('input')
|
71
|
+
.and_call_original
|
72
|
+
|
73
|
+
expect(subject).to eq 'input-hashed'
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
describe :secret_matches? do
|
80
|
+
context 'when comparer undefined' do
|
81
|
+
it 'uses a default compare' do
|
82
|
+
expect(clazz).to receive(:default_comparer).with('a', 'a').and_return true
|
83
|
+
expect(clazz.secret_matches?('a', 'a')).to be_truthy
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'when comparer defined' do
|
88
|
+
let(:comparer) do
|
89
|
+
->(*) { false }
|
90
|
+
end
|
91
|
+
|
92
|
+
before do
|
93
|
+
clazz.secret_comparer = comparer
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'uses that comparer' do
|
97
|
+
expect(comparer).to receive(:call).with('a', 'a').and_call_original
|
98
|
+
expect(clazz.secret_matches?('a', 'a')).to be_falsey
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
describe :find_by_fallback_token do
|
104
|
+
let(:old_token) { instance_double(clazz, token: 'input') }
|
105
|
+
subject { clazz.send(:find_by_fallback_token, :token, 'input') }
|
106
|
+
|
107
|
+
it 'does not call find_by when not configured' do
|
108
|
+
expect(clazz).not_to receive(:find_by)
|
109
|
+
expect(subject).to eq(nil)
|
110
|
+
end
|
111
|
+
|
112
|
+
context 'when fallback configured' do
|
113
|
+
include_context 'with token hashing and fallback lookup enabled'
|
114
|
+
let(:hashed_token) { hashed_or_plain_token_func.call('input') }
|
115
|
+
|
116
|
+
it 'upgrades the plain token if no hashed exists' do
|
117
|
+
expect(clazz).to receive(:find_by).with(token: 'input').and_return(old_token)
|
118
|
+
expect(old_token).to receive(:update_column).with(:token, hashed_token)
|
119
|
+
|
120
|
+
expect(subject).to eq(old_token)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe :find_by_plaintext_token do
|
126
|
+
let(:plain_token) { 'asdf' }
|
127
|
+
let(:subject) { clazz.send(:find_by_plaintext_token, :token, plain_token) }
|
128
|
+
let(:hashing_enabled?) { false }
|
129
|
+
|
130
|
+
before do
|
131
|
+
allow(clazz).to receive(:perform_secret_hashing?).and_return(hashing_enabled?)
|
132
|
+
end
|
133
|
+
|
134
|
+
context 'when not configured' do
|
135
|
+
it 'always finds with the plain value even when nil' do
|
136
|
+
expect(clazz).to receive(:find_by).with(token: plain_token).once.and_return(nil)
|
137
|
+
expect(subject).to eq(nil)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'when hashing configured' do
|
142
|
+
let(:hashing_enabled?) { true }
|
143
|
+
let(:hashed_token) { clazz.send(:default_hash_function, plain_token) }
|
144
|
+
|
145
|
+
it 'calls find_by only on the hashed value if it returns' do
|
146
|
+
expect(clazz).not_to receive(:find_by).with(token: plain_token)
|
147
|
+
expect(clazz).to receive(:find_by).with(token: hashed_token).and_return(:result)
|
148
|
+
|
149
|
+
expect(subject).to eq(:result)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'does not fall back to plain token' do
|
153
|
+
expect(clazz).not_to receive(:find_by).with(token: plain_token)
|
154
|
+
expect(clazz).to receive(:find_by).with(token: hashed_token).and_return(nil)
|
155
|
+
|
156
|
+
expect(subject).to eq(nil)
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'when fallback configured' do
|
160
|
+
let(:old_token) { instance_double(clazz, token: plain_token) }
|
161
|
+
let(:hashed_token) { hashed_or_plain_token_func.call(plain_token) }
|
162
|
+
|
163
|
+
include_context 'with token hashing and fallback lookup enabled'
|
164
|
+
|
165
|
+
it 'does not fallback if found by hashed token' do
|
166
|
+
expect(clazz).to receive(:find_by).with(token: hashed_token).and_return old_token
|
167
|
+
expect(clazz).not_to receive(:find_by).with(token: plain_token)
|
168
|
+
expect(clazz).not_to receive(:upgrade_fallback_value)
|
169
|
+
|
170
|
+
expect(subject).to eq(old_token)
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'also searches for the plain token if no hashed exists' do
|
174
|
+
expect(clazz).to receive(:find_by).with(token: hashed_token).and_return nil
|
175
|
+
expect(clazz).to receive(:find_by).with(token: plain_token).and_return(old_token)
|
176
|
+
expect(old_token).to receive(:update_column).with(:token, hashed_token)
|
177
|
+
|
178
|
+
expect(subject).to eq(old_token)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
182
|
+
end
|
183
|
+
end
|
@@ -4,13 +4,13 @@ module Doorkeeper::OAuth
|
|
4
4
|
describe BaseRequest do
|
5
5
|
let(:access_token) do
|
6
6
|
double :access_token,
|
7
|
-
|
8
|
-
expires_in:
|
9
|
-
expires_in_seconds:
|
10
|
-
scopes_string:
|
11
|
-
|
12
|
-
token_type:
|
13
|
-
created_at:
|
7
|
+
plaintext_token: "some-token",
|
8
|
+
expires_in: "3600",
|
9
|
+
expires_in_seconds: "300",
|
10
|
+
scopes_string: "two scopes",
|
11
|
+
plaintext_refresh_token: "some-refresh-token",
|
12
|
+
token_type: "bearer",
|
13
|
+
created_at: 0
|
14
14
|
end
|
15
15
|
|
16
16
|
let(:client) { double :client, id: '1' }
|
@@ -21,6 +21,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
21
21
|
context 'with scopes' do
|
22
22
|
it 'is invalid when scopes are not included in the server' do
|
23
23
|
server_scopes = Doorkeeper::OAuth::Scopes.from_string 'email'
|
24
|
+
allow(request).to receive(:grant_type).and_return(Doorkeeper::OAuth::CLIENT_CREDENTIALS)
|
24
25
|
allow(server).to receive(:scopes).and_return(server_scopes)
|
25
26
|
allow(request).to receive(:scopes).and_return(
|
26
27
|
Doorkeeper::OAuth::Scopes.from_string('invalid')
|
@@ -34,6 +35,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
34
35
|
server_scopes = Doorkeeper::OAuth::Scopes.from_string 'email app'
|
35
36
|
allow(application).to receive(:scopes).and_return(application_scopes)
|
36
37
|
allow(server).to receive(:scopes).and_return(server_scopes)
|
38
|
+
allow(request).to receive(:grant_type).and_return(Doorkeeper::OAuth::CLIENT_CREDENTIALS)
|
37
39
|
allow(request).to receive(:scopes).and_return(application_scopes)
|
38
40
|
expect(subject).to be_valid
|
39
41
|
end
|
@@ -42,6 +44,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
42
44
|
application_scopes = Doorkeeper::OAuth::Scopes.from_string 'app'
|
43
45
|
server_scopes = Doorkeeper::OAuth::Scopes.from_string 'email app'
|
44
46
|
allow(application).to receive(:scopes).and_return(application_scopes)
|
47
|
+
allow(request).to receive(:grant_type).and_return(Doorkeeper::OAuth::CLIENT_CREDENTIALS)
|
45
48
|
allow(server).to receive(:scopes).and_return(server_scopes)
|
46
49
|
allow(request).to receive(:scopes).and_return(
|
47
50
|
Doorkeeper::OAuth::Scopes.from_string('email')
|
@@ -6,31 +6,31 @@ module Doorkeeper::OAuth::Helpers
|
|
6
6
|
|
7
7
|
it 'is valid if scope is present' do
|
8
8
|
server_scopes.add :scope
|
9
|
-
expect(ScopeChecker.valid?('scope', server_scopes)).to be_truthy
|
9
|
+
expect(ScopeChecker.valid?(scope_str: 'scope', server_scopes: server_scopes)).to be_truthy
|
10
10
|
end
|
11
11
|
|
12
12
|
it 'is invalid if includes tabs space' do
|
13
|
-
expect(ScopeChecker.valid?("\tsomething", server_scopes)).to be_falsey
|
13
|
+
expect(ScopeChecker.valid?(scope_str: "\tsomething", server_scopes: server_scopes)).to be_falsey
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'is invalid if scope is not present' do
|
17
|
-
expect(ScopeChecker.valid?(nil, server_scopes)).to be_falsey
|
17
|
+
expect(ScopeChecker.valid?(scope_str: nil, server_scopes: server_scopes)).to be_falsey
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'is invalid if scope is blank' do
|
21
|
-
expect(ScopeChecker.valid?(' ', server_scopes)).to be_falsey
|
21
|
+
expect(ScopeChecker.valid?(scope_str: ' ', server_scopes: server_scopes)).to be_falsey
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'is invalid if includes return space' do
|
25
|
-
expect(ScopeChecker.valid?("scope\r", server_scopes)).to be_falsey
|
25
|
+
expect(ScopeChecker.valid?(scope_str: "scope\r", server_scopes: server_scopes)).to be_falsey
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'is invalid if includes new lines' do
|
29
|
-
expect(ScopeChecker.valid?("scope\nanother", server_scopes)).to be_falsey
|
29
|
+
expect(ScopeChecker.valid?(scope_str: "scope\nanother", server_scopes: server_scopes)).to be_falsey
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'is invalid if any scope is not included in server scopes' do
|
33
|
-
expect(ScopeChecker.valid?('scope another', server_scopes)).to be_falsey
|
33
|
+
expect(ScopeChecker.valid?(scope_str: 'scope another', server_scopes: server_scopes)).to be_falsey
|
34
34
|
end
|
35
35
|
|
36
36
|
context 'with application_scopes' do
|
@@ -42,19 +42,54 @@ module Doorkeeper::OAuth::Helpers
|
|
42
42
|
end
|
43
43
|
|
44
44
|
it 'is valid if scope is included in the application scope list' do
|
45
|
-
expect(ScopeChecker.valid?(
|
46
|
-
|
47
|
-
|
48
|
-
application_scopes
|
49
|
-
)).to be_truthy
|
45
|
+
expect(ScopeChecker.valid?(scope_str: 'app123',
|
46
|
+
server_scopes: server_scopes,
|
47
|
+
app_scopes: application_scopes)).to be_truthy
|
50
48
|
end
|
51
49
|
|
52
50
|
it 'is invalid if any scope is not included in the application' do
|
53
|
-
expect(ScopeChecker.valid?(
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
51
|
+
expect(ScopeChecker.valid?(scope_str: 'svr',
|
52
|
+
server_scopes: server_scopes,
|
53
|
+
app_scopes: application_scopes)).to be_falsey
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'with grant_type' do
|
58
|
+
let(:server_scopes) do
|
59
|
+
Doorkeeper::OAuth::Scopes.from_string 'scope1 scope2'
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with scopes_by_grant_type not configured for grant_type' do
|
63
|
+
it 'is valid if the scope is in server scopes' do
|
64
|
+
expect(ScopeChecker.valid?(scope_str: 'scope1',
|
65
|
+
server_scopes: server_scopes,
|
66
|
+
grant_type: Doorkeeper::OAuth::PASSWORD)).to be_truthy
|
67
|
+
end
|
68
|
+
|
69
|
+
it 'is invalid if the scope is not in server scopes' do
|
70
|
+
expect(ScopeChecker.valid?(scope_str: 'unknown',
|
71
|
+
server_scopes: server_scopes,
|
72
|
+
grant_type: Doorkeeper::OAuth::PASSWORD)).to be_falsey
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when scopes_by_grant_type configured for grant_type' do
|
77
|
+
before do
|
78
|
+
allow(Doorkeeper.configuration).to receive(:scopes_by_grant_type).
|
79
|
+
and_return(password: [:scope1])
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'is valid if the scope is permitted for grant_type' do
|
83
|
+
expect(ScopeChecker.valid?(scope_str: 'scope1',
|
84
|
+
server_scopes: server_scopes,
|
85
|
+
grant_type: Doorkeeper::OAuth::PASSWORD)).to be_truthy
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'is invalid if the scope is permitted for grant_type' do
|
89
|
+
expect(ScopeChecker.valid?(scope_str: 'scope2',
|
90
|
+
server_scopes: server_scopes,
|
91
|
+
grant_type: Doorkeeper::OAuth::PASSWORD)).to be_falsey
|
92
|
+
end
|
58
93
|
end
|
59
94
|
end
|
60
95
|
end
|
@@ -61,18 +61,36 @@ module Doorkeeper::OAuth::Helpers
|
|
61
61
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
62
62
|
end
|
63
63
|
|
64
|
-
it
|
64
|
+
it "doesn't allow non-matching domains through" do
|
65
65
|
uri = 'http://app.abc/?query=hello'
|
66
66
|
client_uri = 'http://app.co'
|
67
67
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
68
68
|
end
|
69
69
|
|
70
|
-
it
|
70
|
+
it "doesn't allow non-matching domains that don't start at the beginning" do
|
71
71
|
uri = 'http://app.co/?query=hello'
|
72
72
|
client_uri = 'http://example.com?app.co=test'
|
73
73
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
74
74
|
end
|
75
75
|
|
76
|
+
context 'loopback IP redirect URIs' do
|
77
|
+
it 'ignores port for same URIs' do
|
78
|
+
uri = 'http://127.0.0.1:5555/auth/callback'
|
79
|
+
client_uri = 'http://127.0.0.1:48599/auth/callback'
|
80
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
81
|
+
|
82
|
+
uri = 'http://[::1]:5555/auth/callback'
|
83
|
+
client_uri = 'http://[::1]:5555/auth/callback'
|
84
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
85
|
+
end
|
86
|
+
|
87
|
+
it "doesn't ignore port for URIs with different queries" do
|
88
|
+
uri = 'http://127.0.0.1:5555/auth/callback'
|
89
|
+
client_uri = 'http://127.0.0.1:48599/auth/callback2'
|
90
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
76
94
|
context "client registered query params" do
|
77
95
|
it "doesn't allow query being absent" do
|
78
96
|
uri = 'http://app.co'
|