doorkeeper 4.2.6 → 4.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/.github/ISSUE_TEMPLATE.md +19 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +1 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +13 -0
- data/.travis.yml +13 -5
- data/Appraisals +6 -2
- data/CODE_OF_CONDUCT.md +46 -0
- data/Gemfile +1 -1
- data/NEWS.md +24 -0
- data/README.md +39 -9
- data/SECURITY.md +13 -0
- data/app/controllers/doorkeeper/application_controller.rb +1 -5
- data/app/controllers/doorkeeper/applications_controller.rb +14 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +13 -1
- data/app/helpers/doorkeeper/dashboard_helper.rb +4 -2
- data/app/validators/redirect_uri_validator.rb +12 -2
- data/app/views/doorkeeper/applications/_form.html.erb +1 -1
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/config/locales/en.yml +3 -5
- data/doorkeeper.gemspec +4 -3
- data/gemfiles/rails_4_2.gemfile +6 -4
- data/gemfiles/rails_5_0.gemfile +4 -4
- data/gemfiles/rails_5_1.gemfile +6 -7
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper.rb +1 -0
- data/lib/doorkeeper/config.rb +55 -55
- data/lib/doorkeeper/engine.rb +3 -3
- data/lib/doorkeeper/grape/helpers.rb +13 -8
- data/lib/doorkeeper/helpers/controller.rb +8 -4
- data/lib/doorkeeper/models/access_token_mixin.rb +14 -7
- data/lib/doorkeeper/models/application_mixin.rb +11 -6
- data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
- data/lib/doorkeeper/oauth/authorization/token.rb +22 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -1
- data/lib/doorkeeper/oauth/base_request.rb +5 -5
- data/lib/doorkeeper/oauth/client.rb +2 -2
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -2
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +1 -2
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -3
- data/lib/doorkeeper/oauth/password_access_token_request.rb +1 -0
- data/lib/doorkeeper/oauth/refresh_token_request.rb +1 -0
- data/lib/doorkeeper/oauth/scopes.rb +18 -8
- data/lib/doorkeeper/oauth/token.rb +1 -1
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/orm/active_record.rb +20 -8
- data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_token.rb +1 -23
- data/lib/doorkeeper/orm/active_record/application.rb +1 -1
- data/lib/doorkeeper/orm/active_record/base_record.rb +11 -0
- data/lib/doorkeeper/rails/helpers.rb +5 -6
- data/lib/doorkeeper/rails/routes.rb +9 -7
- data/lib/doorkeeper/request.rb +7 -1
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +13 -1
- data/lib/generators/doorkeeper/application_owner_generator.rb +11 -2
- data/lib/generators/doorkeeper/migration_generator.rb +13 -1
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -1
- data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/initializer.rb +19 -3
- data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +1 -1
- data/spec/controllers/applications_controller_spec.rb +15 -4
- data/spec/controllers/authorizations_controller_spec.rb +5 -5
- data/spec/controllers/protected_resources_controller_spec.rb +28 -19
- data/spec/controllers/token_info_controller_spec.rb +17 -13
- data/spec/controllers/tokens_controller_spec.rb +138 -4
- data/spec/dummy/config/initializers/doorkeeper.rb +1 -1
- data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +1 -1
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/factories.rb +1 -1
- data/spec/generators/application_owner_generator_spec.rb +24 -5
- data/spec/generators/migration_generator_spec.rb +24 -3
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +115 -12
- data/spec/lib/models/revocable_spec.rb +2 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +39 -11
- data/spec/lib/oauth/base_request_spec.rb +2 -7
- data/spec/lib/oauth/client_credentials/creator_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +1 -0
- data/spec/lib/oauth/code_request_spec.rb +1 -3
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -0
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +9 -3
- data/spec/lib/oauth/refresh_token_request_spec.rb +19 -7
- data/spec/lib/oauth/scopes_spec.rb +28 -1
- data/spec/lib/oauth/token_request_spec.rb +6 -8
- data/spec/lib/server_spec.rb +10 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +72 -48
- data/spec/models/doorkeeper/application_spec.rb +51 -18
- data/spec/requests/applications/applications_request_spec.rb +5 -5
- data/spec/requests/endpoints/token_spec.rb +8 -1
- data/spec/requests/flows/authorization_code_spec.rb +1 -0
- data/spec/requests/flows/client_credentials_spec.rb +1 -1
- data/spec/requests/flows/implicit_grant_errors_spec.rb +2 -2
- data/spec/requests/flows/refresh_token_spec.rb +4 -4
- data/spec/requests/flows/revoke_token_spec.rb +15 -15
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +1 -1
- data/spec/routing/custom_controller_routes_spec.rb +4 -0
- data/spec/routing/default_routes_spec.rb +5 -1
- data/spec/spec_helper_integration.rb +15 -4
- data/spec/support/dependencies/factory_girl.rb +2 -2
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/model_helper.rb +9 -4
- data/spec/support/helpers/request_spec_helper.rb +7 -3
- data/spec/support/helpers/url_helper.rb +8 -8
- data/spec/support/shared/controllers_shared_context.rb +2 -6
- data/spec/support/shared/models_shared_examples.rb +4 -4
- data/spec/validators/redirect_uri_validator_spec.rb +51 -6
- data/spec/version/version_spec.rb +15 -0
- metadata +42 -13
@@ -38,11 +38,11 @@ describe 'Revocable' do
|
|
38
38
|
describe :revoke_previous_refresh_token! do
|
39
39
|
it "revokes the previous token if existing, and resets the
|
40
40
|
`previous_refresh_token` attribute" do
|
41
|
-
previous_token =
|
41
|
+
previous_token = FactoryBot.create(
|
42
42
|
:access_token,
|
43
43
|
refresh_token: "refresh_token"
|
44
44
|
)
|
45
|
-
current_token =
|
45
|
+
current_token = FactoryBot.create(
|
46
46
|
:access_token,
|
47
47
|
previous_refresh_token: previous_token.refresh_token
|
48
48
|
)
|
@@ -8,11 +8,14 @@ module Doorkeeper::OAuth
|
|
8
8
|
refresh_token_enabled?: false,
|
9
9
|
custom_access_token_expires_in: ->(_app) { nil }
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
|
+
let(:grant) { FactoryBot.create :access_grant }
|
12
13
|
let(:client) { grant.application }
|
14
|
+
let(:redirect_uri) { client.redirect_uri }
|
15
|
+
let(:params) { { redirect_uri: redirect_uri } }
|
13
16
|
|
14
17
|
subject do
|
15
|
-
AuthorizationCodeRequest.new server, grant, client,
|
18
|
+
AuthorizationCodeRequest.new server, grant, client, params
|
16
19
|
end
|
17
20
|
|
18
21
|
it 'issues a new token for the client' do
|
@@ -27,9 +30,7 @@ module Doorkeeper::OAuth
|
|
27
30
|
end
|
28
31
|
|
29
32
|
it 'revokes the grant' do
|
30
|
-
expect
|
31
|
-
subject.authorize
|
32
|
-
end.to change { grant.reload.accessible? }
|
33
|
+
expect { subject.authorize }.to change { grant.reload.accessible? }
|
33
34
|
end
|
34
35
|
|
35
36
|
it 'requires the grant to be accessible' do
|
@@ -63,18 +64,45 @@ module Doorkeeper::OAuth
|
|
63
64
|
end
|
64
65
|
|
65
66
|
it "matches the client with grant's one" do
|
66
|
-
subject.client =
|
67
|
+
subject.client = FactoryBot.create :application
|
67
68
|
subject.validate
|
68
69
|
expect(subject.error).to eq(:invalid_grant)
|
69
70
|
end
|
70
71
|
|
71
72
|
it 'skips token creation if there is a matching one' do
|
72
|
-
|
73
|
-
|
73
|
+
Doorkeeper.configure do
|
74
|
+
orm DOORKEEPER_ORM
|
75
|
+
reuse_access_token
|
76
|
+
end
|
77
|
+
|
78
|
+
FactoryBot.create(:access_token, application_id: client.id,
|
74
79
|
resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s)
|
75
|
-
|
76
|
-
|
77
|
-
|
80
|
+
|
81
|
+
expect { subject.authorize }.to_not change { Doorkeeper::AccessToken.count }
|
82
|
+
end
|
83
|
+
|
84
|
+
it "calls BaseRequest callback methods" do
|
85
|
+
expect_any_instance_of(BaseRequest).to receive(:before_successful_response).once
|
86
|
+
expect_any_instance_of(BaseRequest).to receive(:after_successful_response).once
|
87
|
+
subject.authorize
|
88
|
+
end
|
89
|
+
|
90
|
+
context "when redirect_uri contains some query params" do
|
91
|
+
let(:redirect_uri) { client.redirect_uri + "?query=q" }
|
92
|
+
|
93
|
+
it "compares only host part with grant's redirect_uri" do
|
94
|
+
subject.validate
|
95
|
+
expect(subject.error).to eq(nil)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "when redirect_uri is not an URI" do
|
100
|
+
let(:redirect_uri) { '123d#!s' }
|
101
|
+
|
102
|
+
it "responds with invalid_grant" do
|
103
|
+
subject.validate
|
104
|
+
expect(subject.error).to eq(:invalid_grant)
|
105
|
+
end
|
78
106
|
end
|
79
107
|
end
|
80
108
|
end
|
@@ -13,14 +13,9 @@ module Doorkeeper::OAuth
|
|
13
13
|
created_at: 0
|
14
14
|
end
|
15
15
|
|
16
|
-
let(:client)
|
17
|
-
double :client,
|
18
|
-
id: '1'
|
19
|
-
end
|
16
|
+
let(:client) { double :client, id: '1' }
|
20
17
|
|
21
|
-
let(:scopes_array)
|
22
|
-
%w(public write)
|
23
|
-
end
|
18
|
+
let(:scopes_array) { %w[public write] }
|
24
19
|
|
25
20
|
let(:server) do
|
26
21
|
double :server,
|
@@ -2,7 +2,7 @@ require 'spec_helper_integration'
|
|
2
2
|
|
3
3
|
class Doorkeeper::OAuth::ClientCredentialsRequest
|
4
4
|
describe Creator do
|
5
|
-
let(:client) {
|
5
|
+
let(:client) { FactoryBot.create :application }
|
6
6
|
let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public') }
|
7
7
|
|
8
8
|
it 'creates a new token' do
|
@@ -5,7 +5,7 @@ module Doorkeeper::OAuth
|
|
5
5
|
let(:server) { Doorkeeper.configuration }
|
6
6
|
|
7
7
|
context 'with a valid request' do
|
8
|
-
let(:client) {
|
8
|
+
let(:client) { FactoryBot.create :application }
|
9
9
|
|
10
10
|
it 'issues an access token' do
|
11
11
|
request = ClientCredentialsRequest.new(server, client, {})
|
@@ -11,6 +11,7 @@ module Doorkeeper::OAuth
|
|
11
11
|
custom_access_token_expires_in: ->(_app) { nil }
|
12
12
|
)
|
13
13
|
end
|
14
|
+
|
14
15
|
let(:application) { double :application, scopes: Scopes.from_string('') }
|
15
16
|
let(:client) { double :client, application: application }
|
16
17
|
let(:token_creator) { double :issuer, create: true, token: double }
|
@@ -32,9 +32,7 @@ module Doorkeeper::OAuth
|
|
32
32
|
|
33
33
|
it 'does not create grant when not authorizable' do
|
34
34
|
allow(pre_auth).to receive(:authorizable?).and_return(false)
|
35
|
-
expect
|
36
|
-
subject.authorize
|
37
|
-
end.to_not change { Doorkeeper::AccessGrant.count }
|
35
|
+
expect { subject.authorize }.not_to change { Doorkeeper::AccessGrant.count }
|
38
36
|
end
|
39
37
|
|
40
38
|
it 'returns a error response' do
|
@@ -11,7 +11,7 @@ module Doorkeeper::OAuth
|
|
11
11
|
custom_access_token_expires_in: ->(_app) { nil }
|
12
12
|
)
|
13
13
|
end
|
14
|
-
let(:client) {
|
14
|
+
let(:client) { FactoryBot.create(:application) }
|
15
15
|
let(:owner) { double :owner, id: 99 }
|
16
16
|
|
17
17
|
subject do
|
@@ -53,7 +53,7 @@ module Doorkeeper::OAuth
|
|
53
53
|
end
|
54
54
|
|
55
55
|
it 'creates token even when there is already one (default)' do
|
56
|
-
|
56
|
+
FactoryBot.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
|
57
57
|
expect do
|
58
58
|
subject.authorize
|
59
59
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
@@ -61,12 +61,18 @@ module Doorkeeper::OAuth
|
|
61
61
|
|
62
62
|
it 'skips token creation if there is already one' do
|
63
63
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
64
|
-
|
64
|
+
FactoryBot.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
|
65
65
|
expect do
|
66
66
|
subject.authorize
|
67
67
|
end.to_not change { Doorkeeper::AccessToken.count }
|
68
68
|
end
|
69
69
|
|
70
|
+
it "calls BaseRequest callback methods" do
|
71
|
+
expect_any_instance_of(BaseRequest).to receive(:before_successful_response).once
|
72
|
+
expect_any_instance_of(BaseRequest).to receive(:after_successful_response).once
|
73
|
+
subject.authorize
|
74
|
+
end
|
75
|
+
|
70
76
|
describe 'with scopes' do
|
71
77
|
subject do
|
72
78
|
PasswordAccessTokenRequest.new(server, client, owner, scope: 'public')
|
@@ -5,14 +5,17 @@ module Doorkeeper::OAuth
|
|
5
5
|
before do
|
6
6
|
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
7
7
|
end
|
8
|
+
|
8
9
|
let(:server) do
|
9
10
|
double :server,
|
10
11
|
access_token_expires_in: 2.minutes,
|
11
12
|
custom_access_token_expires_in: -> (_oauth_client) { nil }
|
12
13
|
end
|
14
|
+
|
13
15
|
let(:refresh_token) do
|
14
|
-
|
16
|
+
FactoryBot.create(:access_token, use_refresh_token: true)
|
15
17
|
end
|
18
|
+
|
16
19
|
let(:client) { refresh_token.application }
|
17
20
|
let(:credentials) { Client::Credentials.new(client.uid, client.secret) }
|
18
21
|
|
@@ -20,7 +23,8 @@ module Doorkeeper::OAuth
|
|
20
23
|
|
21
24
|
it 'issues a new token for the client' do
|
22
25
|
expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
|
23
|
-
|
26
|
+
# #sort_by used for MongoDB ORM extensions for valid ordering
|
27
|
+
expect(client.reload.access_tokens.sort_by(&:created_at).last.expires_in).to eq(120)
|
24
28
|
end
|
25
29
|
|
26
30
|
it 'issues a new token for the client with custom expires_in' do
|
@@ -32,13 +36,20 @@ module Doorkeeper::OAuth
|
|
32
36
|
|
33
37
|
RefreshTokenRequest.new(server, refresh_token, credentials).authorize
|
34
38
|
|
35
|
-
|
39
|
+
# #sort_by used for MongoDB ORM extensions for valid ordering
|
40
|
+
expect(client.reload.access_tokens.sort_by(&:created_at).last.expires_in).to eq(1234)
|
36
41
|
end
|
37
42
|
|
38
43
|
it 'revokes the previous token' do
|
39
44
|
expect { subject.authorize }.to change { refresh_token.revoked? }.from(false).to(true)
|
40
45
|
end
|
41
46
|
|
47
|
+
it "calls BaseRequest callback methods" do
|
48
|
+
expect_any_instance_of(BaseRequest).to receive(:before_successful_response).once
|
49
|
+
expect_any_instance_of(BaseRequest).to receive(:after_successful_response).once
|
50
|
+
subject.authorize
|
51
|
+
end
|
52
|
+
|
42
53
|
it 'requires the refresh token' do
|
43
54
|
subject.refresh_token = nil
|
44
55
|
subject.validate
|
@@ -52,7 +63,7 @@ module Doorkeeper::OAuth
|
|
52
63
|
end
|
53
64
|
|
54
65
|
it "requires the token's client and current client to match" do
|
55
|
-
subject.client =
|
66
|
+
subject.client = FactoryBot.create(:application)
|
56
67
|
subject.validate
|
57
68
|
expect(subject.error).to eq(:invalid_grant)
|
58
69
|
end
|
@@ -93,13 +104,14 @@ module Doorkeeper::OAuth
|
|
93
104
|
it 'sets the previous refresh token in the new access token' do
|
94
105
|
subject.authorize
|
95
106
|
expect(
|
96
|
-
|
107
|
+
# #sort_by used for MongoDB ORM extensions for valid ordering
|
108
|
+
client.access_tokens.sort_by(&:created_at).last.previous_refresh_token
|
97
109
|
).to eq(refresh_token.refresh_token)
|
98
110
|
end
|
99
111
|
end
|
100
112
|
|
101
113
|
context 'clientless access tokens' do
|
102
|
-
let!(:refresh_token) {
|
114
|
+
let!(:refresh_token) { FactoryBot.create(:clientless_access_token, use_refresh_token: true) }
|
103
115
|
|
104
116
|
subject { RefreshTokenRequest.new server, refresh_token, nil }
|
105
117
|
|
@@ -110,7 +122,7 @@ module Doorkeeper::OAuth
|
|
110
122
|
|
111
123
|
context 'with scopes' do
|
112
124
|
let(:refresh_token) do
|
113
|
-
|
125
|
+
FactoryBot.create :access_token,
|
114
126
|
use_refresh_token: true,
|
115
127
|
scopes: 'public write'
|
116
128
|
end
|
@@ -62,7 +62,7 @@ module Doorkeeper::OAuth
|
|
62
62
|
describe '#+' do
|
63
63
|
it 'can add to another scope object' do
|
64
64
|
scopes = Scopes.from_string('public') + Scopes.from_string('admin')
|
65
|
-
expect(scopes.all).to eq(%w
|
65
|
+
expect(scopes.all).to eq(%w[public admin])
|
66
66
|
end
|
67
67
|
|
68
68
|
it 'does not change the existing object' do
|
@@ -70,6 +70,11 @@ module Doorkeeper::OAuth
|
|
70
70
|
expect(origin.to_s).to eq('public')
|
71
71
|
end
|
72
72
|
|
73
|
+
it 'can add an array to a scope object' do
|
74
|
+
scopes = Scopes.from_string('public') + ['admin']
|
75
|
+
expect(scopes.all).to eq(%w[public admin])
|
76
|
+
end
|
77
|
+
|
73
78
|
it 'raises an error if cannot handle addition' do
|
74
79
|
expect do
|
75
80
|
Scopes.from_string('public') + 'admin'
|
@@ -77,6 +82,24 @@ module Doorkeeper::OAuth
|
|
77
82
|
end
|
78
83
|
end
|
79
84
|
|
85
|
+
describe '#&' do
|
86
|
+
it 'can get intersection with another scope object' do
|
87
|
+
scopes = Scopes.from_string('public admin') & Scopes.from_string('write admin')
|
88
|
+
expect(scopes.all).to eq(%w[admin])
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'does not change the existing object' do
|
92
|
+
origin = Scopes.from_string('public admin')
|
93
|
+
origin & Scopes.from_string('write admin')
|
94
|
+
expect(origin.to_s).to eq('public admin')
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'can get intersection with an array' do
|
98
|
+
scopes = Scopes.from_string('public admin') & %w[write admin]
|
99
|
+
expect(scopes.all).to eq(%w[admin])
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
80
103
|
describe '#==' do
|
81
104
|
it 'is equal to another set of scopes' do
|
82
105
|
expect(Scopes.from_string('public')).to eq(Scopes.from_string('public'))
|
@@ -89,6 +112,10 @@ module Doorkeeper::OAuth
|
|
89
112
|
it 'differs from another set of scopes when scopes are not the same' do
|
90
113
|
expect(Scopes.from_string('public write')).not_to eq(Scopes.from_string('write'))
|
91
114
|
end
|
115
|
+
|
116
|
+
it "does not raise an error when compared to a non-enumerable object" do
|
117
|
+
expect { Scopes.from_string("public") == false }.not_to raise_error
|
118
|
+
end
|
92
119
|
end
|
93
120
|
|
94
121
|
describe '#has_scopes?' do
|
@@ -6,6 +6,7 @@ module Doorkeeper::OAuth
|
|
6
6
|
scopes = double(all: ['public'])
|
7
7
|
double(:application, id: 9990, scopes: scopes)
|
8
8
|
end
|
9
|
+
|
9
10
|
let :pre_auth do
|
10
11
|
double(
|
11
12
|
:pre_auth,
|
@@ -38,9 +39,7 @@ module Doorkeeper::OAuth
|
|
38
39
|
|
39
40
|
it 'does not create token when not authorizable' do
|
40
41
|
allow(pre_auth).to receive(:authorizable?).and_return(false)
|
41
|
-
expect
|
42
|
-
subject.authorize
|
43
|
-
end.to_not change { Doorkeeper::AccessToken.count }
|
42
|
+
expect { subject.authorize }.not_to change { Doorkeeper::AccessToken.count }
|
44
43
|
end
|
45
44
|
|
46
45
|
it 'returns a error response' do
|
@@ -75,7 +74,7 @@ module Doorkeeper::OAuth
|
|
75
74
|
|
76
75
|
it 'creates a new token if scopes do not match' do
|
77
76
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
78
|
-
|
77
|
+
FactoryBot.create(:access_token, application_id: pre_auth.client.id,
|
79
78
|
resource_owner_id: owner.id, scopes: '')
|
80
79
|
expect do
|
81
80
|
subject.authorize
|
@@ -86,12 +85,11 @@ module Doorkeeper::OAuth
|
|
86
85
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
87
86
|
allow(application.scopes).to receive(:has_scopes?).and_return(true)
|
88
87
|
allow(application.scopes).to receive(:all?).and_return(true)
|
89
|
-
|
88
|
+
|
89
|
+
FactoryBot.create(:access_token, application_id: pre_auth.client.id,
|
90
90
|
resource_owner_id: owner.id, scopes: 'public')
|
91
91
|
|
92
|
-
expect
|
93
|
-
subject.authorize
|
94
|
-
end.to_not change { Doorkeeper::AccessToken.count }
|
92
|
+
expect { subject.authorize }.not_to change { Doorkeeper::AccessToken.count }
|
95
93
|
end
|
96
94
|
end
|
97
95
|
end
|
data/spec/lib/server_spec.rb
CHANGED
@@ -45,5 +45,15 @@ describe Doorkeeper::Server do
|
|
45
45
|
expect(fake_class).to receive(:new).with(subject)
|
46
46
|
subject.authorization_request :code
|
47
47
|
end
|
48
|
+
|
49
|
+
it 'builds the request with composit strategy name' do
|
50
|
+
allow(Doorkeeper.configuration).
|
51
|
+
to receive(:authorization_response_types).
|
52
|
+
and_return(['id_token token'])
|
53
|
+
|
54
|
+
stub_const 'Doorkeeper::Request::IdTokenToken', fake_class
|
55
|
+
expect(fake_class).to receive(:new).with(subject)
|
56
|
+
subject.authorization_request 'id_token token'
|
57
|
+
end
|
48
58
|
end
|
49
59
|
end
|
@@ -2,7 +2,7 @@ require 'spec_helper_integration'
|
|
2
2
|
|
3
3
|
module Doorkeeper
|
4
4
|
describe AccessToken do
|
5
|
-
subject {
|
5
|
+
subject { FactoryBot.build(:access_token) }
|
6
6
|
|
7
7
|
it { expect(subject).to be_valid }
|
8
8
|
|
@@ -19,9 +19,9 @@ module Doorkeeper
|
|
19
19
|
|
20
20
|
describe :generate_token do
|
21
21
|
it 'generates a token using the default method' do
|
22
|
-
|
22
|
+
FactoryBot.create :access_token
|
23
23
|
|
24
|
-
token =
|
24
|
+
token = FactoryBot.create :access_token
|
25
25
|
expect(token.token).to be_a(String)
|
26
26
|
end
|
27
27
|
|
@@ -41,7 +41,7 @@ module Doorkeeper
|
|
41
41
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
42
42
|
end
|
43
43
|
|
44
|
-
token =
|
44
|
+
token = FactoryBot.create :access_token
|
45
45
|
expect(token.token).to match(%r{custom_generator_token_\d+})
|
46
46
|
end
|
47
47
|
|
@@ -61,7 +61,7 @@ module Doorkeeper
|
|
61
61
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
62
62
|
end
|
63
63
|
|
64
|
-
token =
|
64
|
+
token = FactoryBot.create :access_token
|
65
65
|
expect(token.token).to match(%r{custom_generator_token_Application \d+})
|
66
66
|
end
|
67
67
|
|
@@ -81,7 +81,7 @@ module Doorkeeper
|
|
81
81
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
82
82
|
end
|
83
83
|
|
84
|
-
token =
|
84
|
+
token = FactoryBot.create :access_token, scopes: 'public write'
|
85
85
|
|
86
86
|
expect(token.token).to eq 'custom_generator_token_2_public write'
|
87
87
|
end
|
@@ -102,7 +102,7 @@ module Doorkeeper
|
|
102
102
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
103
103
|
end
|
104
104
|
|
105
|
-
token =
|
105
|
+
token = FactoryBot.create :access_token
|
106
106
|
expect(token.token).to eq 'custom_generator_token_7200'
|
107
107
|
end
|
108
108
|
|
@@ -118,7 +118,7 @@ module Doorkeeper
|
|
118
118
|
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
119
119
|
end
|
120
120
|
|
121
|
-
token =
|
121
|
+
token = FactoryBot.create :access_token
|
122
122
|
created_at = token.created_at
|
123
123
|
expect(token.token).to eq "custom_generator_token_#{created_at.to_i}"
|
124
124
|
end
|
@@ -132,8 +132,31 @@ module Doorkeeper
|
|
132
132
|
access_token_generator "Doorkeeper::NoGenerate"
|
133
133
|
end
|
134
134
|
|
135
|
-
expect {
|
136
|
-
raise_error(Doorkeeper::Errors::UnableToGenerateToken)
|
135
|
+
expect { FactoryBot.create :access_token }.to(
|
136
|
+
raise_error(Doorkeeper::Errors::UnableToGenerateToken)
|
137
|
+
)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'raises original error if something went wrong in custom generator' do
|
141
|
+
eigenclass = class << CustomGeneratorArgs; self; end
|
142
|
+
eigenclass.class_eval do
|
143
|
+
remove_method :generate
|
144
|
+
end
|
145
|
+
|
146
|
+
module CustomGeneratorArgs
|
147
|
+
def self.generate(opts = {})
|
148
|
+
raise LoadError, 'custom behaviour'
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
Doorkeeper.configure do
|
153
|
+
orm DOORKEEPER_ORM
|
154
|
+
access_token_generator "Doorkeeper::CustomGeneratorArgs"
|
155
|
+
end
|
156
|
+
|
157
|
+
expect { FactoryBot.create :access_token }.to(
|
158
|
+
raise_error(LoadError)
|
159
|
+
)
|
137
160
|
end
|
138
161
|
|
139
162
|
it 'raises an error if the custom object does not exist' do
|
@@ -142,32 +165,33 @@ module Doorkeeper
|
|
142
165
|
access_token_generator "Doorkeeper::NotReal"
|
143
166
|
end
|
144
167
|
|
145
|
-
expect {
|
146
|
-
raise_error(Doorkeeper::Errors::TokenGeneratorNotFound)
|
168
|
+
expect { FactoryBot.create :access_token }.to(
|
169
|
+
raise_error(Doorkeeper::Errors::TokenGeneratorNotFound, /NotReal/)
|
170
|
+
)
|
147
171
|
end
|
148
172
|
end
|
149
173
|
|
150
174
|
describe :refresh_token do
|
151
175
|
it 'has empty refresh token if it was not required' do
|
152
|
-
token =
|
176
|
+
token = FactoryBot.create :access_token
|
153
177
|
expect(token.refresh_token).to be_nil
|
154
178
|
end
|
155
179
|
|
156
180
|
it 'generates a refresh token if it was requested' do
|
157
|
-
token =
|
181
|
+
token = FactoryBot.create :access_token, use_refresh_token: true
|
158
182
|
expect(token.refresh_token).not_to be_nil
|
159
183
|
end
|
160
184
|
|
161
185
|
it 'is not valid if token exists' do
|
162
|
-
token1 =
|
163
|
-
token2 =
|
186
|
+
token1 = FactoryBot.create :access_token, use_refresh_token: true
|
187
|
+
token2 = FactoryBot.create :access_token, use_refresh_token: true
|
164
188
|
token2.refresh_token = token1.refresh_token
|
165
189
|
expect(token2).not_to be_valid
|
166
190
|
end
|
167
191
|
|
168
192
|
it 'expects database to raise an error if refresh tokens are the same' do
|
169
|
-
token1 =
|
170
|
-
token2 =
|
193
|
+
token1 = FactoryBot.create :access_token, use_refresh_token: true
|
194
|
+
token2 = FactoryBot.create :access_token, use_refresh_token: true
|
171
195
|
expect do
|
172
196
|
token2.refresh_token = token1.refresh_token
|
173
197
|
token2.save(validate: false)
|
@@ -194,22 +218,22 @@ module Doorkeeper
|
|
194
218
|
context 'with default parameters' do
|
195
219
|
|
196
220
|
let(:resource_owner_id) { 100 }
|
197
|
-
let(:application) {
|
221
|
+
let(:application) { FactoryBot.create :application }
|
198
222
|
let(:default_attributes) do
|
199
223
|
{ application: application, resource_owner_id: resource_owner_id }
|
200
224
|
end
|
201
|
-
let(:access_token1) {
|
225
|
+
let(:access_token1) { FactoryBot.create :access_token, default_attributes }
|
202
226
|
|
203
227
|
context 'the second token has the same owner and same app' do
|
204
|
-
let(:access_token2) {
|
228
|
+
let(:access_token2) { FactoryBot.create :access_token, default_attributes }
|
205
229
|
it 'success' do
|
206
230
|
expect(access_token1.same_credential?(access_token2)).to be_truthy
|
207
231
|
end
|
208
232
|
end
|
209
233
|
|
210
234
|
context 'the second token has same owner and different app' do
|
211
|
-
let(:other_application) {
|
212
|
-
let(:access_token2) {
|
235
|
+
let(:other_application) { FactoryBot.create :application }
|
236
|
+
let(:access_token2) { FactoryBot.create :access_token, application: other_application, resource_owner_id: resource_owner_id }
|
213
237
|
|
214
238
|
it 'fail' do
|
215
239
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
@@ -218,8 +242,8 @@ module Doorkeeper
|
|
218
242
|
|
219
243
|
context 'the second token has different owner and different app' do
|
220
244
|
|
221
|
-
let(:other_application) {
|
222
|
-
let(:access_token2) {
|
245
|
+
let(:other_application) { FactoryBot.create :application }
|
246
|
+
let(:access_token2) { FactoryBot.create :access_token, application: other_application, resource_owner_id: 42 }
|
223
247
|
|
224
248
|
it 'fail' do
|
225
249
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
@@ -227,7 +251,7 @@ module Doorkeeper
|
|
227
251
|
end
|
228
252
|
|
229
253
|
context 'the second token has different owner and same app' do
|
230
|
-
let(:access_token2) {
|
254
|
+
let(:access_token2) { FactoryBot.create :access_token, application: application, resource_owner_id: 42 }
|
231
255
|
|
232
256
|
it 'fail' do
|
233
257
|
expect(access_token1.same_credential?(access_token2)).to be_falsey
|
@@ -238,7 +262,7 @@ module Doorkeeper
|
|
238
262
|
|
239
263
|
describe '#acceptable?' do
|
240
264
|
context 'a token that is not accessible' do
|
241
|
-
let(:token) {
|
265
|
+
let(:token) { FactoryBot.create(:access_token, created_at: 6.hours.ago) }
|
242
266
|
|
243
267
|
it 'should return false' do
|
244
268
|
expect(token.acceptable?(nil)).to be false
|
@@ -246,7 +270,7 @@ module Doorkeeper
|
|
246
270
|
end
|
247
271
|
|
248
272
|
context 'a token that has the incorrect scopes' do
|
249
|
-
let(:token) {
|
273
|
+
let(:token) { FactoryBot.create(:access_token) }
|
250
274
|
|
251
275
|
it 'should return false' do
|
252
276
|
expect(token.acceptable?(['public'])).to be false
|
@@ -255,7 +279,7 @@ module Doorkeeper
|
|
255
279
|
|
256
280
|
context 'a token is acceptable with the correct scopes' do
|
257
281
|
let(:token) do
|
258
|
-
token =
|
282
|
+
token = FactoryBot.create(:access_token)
|
259
283
|
token[:scopes] = 'public'
|
260
284
|
token
|
261
285
|
end
|
@@ -268,13 +292,13 @@ module Doorkeeper
|
|
268
292
|
|
269
293
|
describe '.revoke_all_for' do
|
270
294
|
let(:resource_owner) { double(id: 100) }
|
271
|
-
let(:application) {
|
295
|
+
let(:application) { FactoryBot.create :application }
|
272
296
|
let(:default_attributes) do
|
273
297
|
{ application: application, resource_owner_id: resource_owner.id }
|
274
298
|
end
|
275
299
|
|
276
300
|
it 'revokes all tokens for given application and resource owner' do
|
277
|
-
|
301
|
+
FactoryBot.create :access_token, default_attributes
|
278
302
|
AccessToken.revoke_all_for application.id, resource_owner
|
279
303
|
AccessToken.all.each do |token|
|
280
304
|
expect(token).to be_revoked
|
@@ -282,13 +306,13 @@ module Doorkeeper
|
|
282
306
|
end
|
283
307
|
|
284
308
|
it 'matches application' do
|
285
|
-
|
309
|
+
FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
|
286
310
|
AccessToken.revoke_all_for application.id, resource_owner
|
287
311
|
expect(AccessToken.all).not_to be_empty
|
288
312
|
end
|
289
313
|
|
290
314
|
it 'matches resource owner' do
|
291
|
-
|
315
|
+
FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 90)
|
292
316
|
AccessToken.revoke_all_for application.id, resource_owner
|
293
317
|
expect(AccessToken.all).not_to be_empty
|
294
318
|
end
|
@@ -296,7 +320,7 @@ module Doorkeeper
|
|
296
320
|
|
297
321
|
describe '.matching_token_for' do
|
298
322
|
let(:resource_owner_id) { 100 }
|
299
|
-
let(:application) {
|
323
|
+
let(:application) { FactoryBot.create :application }
|
300
324
|
let(:scopes) { Doorkeeper::OAuth::Scopes.from_string('public write') }
|
301
325
|
let(:default_attributes) do
|
302
326
|
{
|
@@ -307,63 +331,63 @@ module Doorkeeper
|
|
307
331
|
end
|
308
332
|
|
309
333
|
it 'returns only one token' do
|
310
|
-
token =
|
334
|
+
token = FactoryBot.create :access_token, default_attributes
|
311
335
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
312
336
|
expect(last_token).to eq(token)
|
313
337
|
end
|
314
338
|
|
315
339
|
it 'accepts resource owner as object' do
|
316
340
|
resource_owner = double(to_key: true, id: 100)
|
317
|
-
token =
|
341
|
+
token = FactoryBot.create :access_token, default_attributes
|
318
342
|
last_token = AccessToken.matching_token_for(application, resource_owner, scopes)
|
319
343
|
expect(last_token).to eq(token)
|
320
344
|
end
|
321
345
|
|
322
346
|
it 'accepts nil as resource owner' do
|
323
|
-
token =
|
347
|
+
token = FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: nil)
|
324
348
|
last_token = AccessToken.matching_token_for(application, nil, scopes)
|
325
349
|
expect(last_token).to eq(token)
|
326
350
|
end
|
327
351
|
|
328
352
|
it 'excludes revoked tokens' do
|
329
|
-
|
353
|
+
FactoryBot.create :access_token, default_attributes.merge(revoked_at: 1.day.ago)
|
330
354
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
331
355
|
expect(last_token).to be_nil
|
332
356
|
end
|
333
357
|
|
334
358
|
it 'matches the application' do
|
335
|
-
|
359
|
+
FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
|
336
360
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
337
361
|
expect(last_token).to be_nil
|
338
362
|
end
|
339
363
|
|
340
364
|
it 'matches the resource owner' do
|
341
|
-
|
365
|
+
FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
|
342
366
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
343
367
|
expect(last_token).to be_nil
|
344
368
|
end
|
345
369
|
|
346
370
|
it 'matches token with fewer scopes' do
|
347
|
-
|
371
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
|
348
372
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
349
373
|
expect(last_token).to be_nil
|
350
374
|
end
|
351
375
|
|
352
376
|
it 'matches token with different scopes' do
|
353
|
-
|
377
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public email')
|
354
378
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
355
379
|
expect(last_token).to be_nil
|
356
380
|
end
|
357
381
|
|
358
382
|
it 'matches token with more scopes' do
|
359
|
-
|
383
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public write email')
|
360
384
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
361
385
|
expect(last_token).to be_nil
|
362
386
|
end
|
363
387
|
|
364
388
|
it 'matches application scopes' do
|
365
|
-
application =
|
366
|
-
|
389
|
+
application = FactoryBot.create :application, scopes: "private read"
|
390
|
+
FactoryBot.create :access_token, default_attributes.merge(
|
367
391
|
application: application
|
368
392
|
)
|
369
393
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
@@ -371,14 +395,14 @@ module Doorkeeper
|
|
371
395
|
end
|
372
396
|
|
373
397
|
it 'returns the last created token' do
|
374
|
-
|
375
|
-
token =
|
398
|
+
FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
|
399
|
+
token = FactoryBot.create :access_token, default_attributes
|
376
400
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
377
401
|
expect(last_token).to eq(token)
|
378
402
|
end
|
379
403
|
|
380
404
|
it 'returns as_json hash' do
|
381
|
-
token =
|
405
|
+
token = FactoryBot.create :access_token, default_attributes
|
382
406
|
token_hash = {
|
383
407
|
resource_owner_id: token.resource_owner_id,
|
384
408
|
scopes: token.scopes,
|