doorkeeper 4.2.5 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +2 -1
- data/.gitlab-ci.yml +16 -0
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +19 -4
- data/Appraisals +8 -4
- data/CODE_OF_CONDUCT.md +46 -0
- data/Gemfile +1 -1
- data/NEWS.md +115 -0
- data/README.md +175 -39
- data/RELEASING.md +5 -12
- data/Rakefile +6 -0
- data/SECURITY.md +15 -0
- data/UPGRADE.md +2 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -5
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +47 -13
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +24 -17
- data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
- data/app/validators/redirect_uri_validator.rb +13 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +31 -19
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +18 -6
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +8 -5
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +5 -1
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +19 -6
- data/doorkeeper.gemspec +20 -20
- 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 +17 -0
- data/lib/doorkeeper/config.rb +123 -71
- data/lib/doorkeeper/engine.rb +7 -3
- data/lib/doorkeeper/errors.rb +20 -5
- data/lib/doorkeeper/grape/helpers.rb +14 -9
- data/lib/doorkeeper/helpers/controller.rb +16 -22
- data/lib/doorkeeper/models/access_grant_mixin.rb +67 -23
- data/lib/doorkeeper/models/access_token_mixin.rb +54 -55
- data/lib/doorkeeper/models/application_mixin.rb +16 -30
- data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +46 -20
- data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
- data/lib/doorkeeper/oauth/base_request.rb +23 -7
- data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +2 -4
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
- data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +11 -4
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
- data/lib/doorkeeper/oauth/scopes.rb +19 -9
- data/lib/doorkeeper/oauth/token.rb +6 -3
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
- data/lib/doorkeeper/orm/active_record/application.rb +45 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +21 -8
- data/lib/doorkeeper/rails/helpers.rb +7 -10
- data/lib/doorkeeper/rails/routes.rb +21 -7
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +6 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request/authorization_code.rb +0 -2
- data/lib/doorkeeper/request/client_credentials.rb +0 -2
- data/lib/doorkeeper/request/code.rb +0 -2
- data/lib/doorkeeper/request/password.rb +1 -13
- data/lib/doorkeeper/request/refresh_token.rb +0 -2
- data/lib/doorkeeper/request/token.rb +0 -2
- data/lib/doorkeeper/request.rb +29 -30
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +14 -1
- data/lib/doorkeeper.rb +21 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -9
- data/lib/generators/doorkeeper/migration_generator.rb +26 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- 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/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +104 -12
- data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
- data/lib/generators/doorkeeper/views_generator.rb +3 -1
- data/spec/controllers/application_metal_controller_spec.rb +50 -0
- data/spec/controllers/applications_controller_spec.rb +141 -17
- data/spec/controllers/authorizations_controller_spec.rb +304 -27
- data/spec/controllers/protected_resources_controller_spec.rb +44 -35
- data/spec/controllers/token_info_controller_spec.rb +17 -21
- data/spec/controllers/tokens_controller_spec.rb +201 -17
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/config/environments/test.rb +4 -5
- data/spec/dummy/config/initializers/doorkeeper.rb +23 -2
- data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
- data/spec/dummy/db/schema.rb +38 -37
- data/spec/factories.rb +1 -1
- data/spec/generators/application_owner_generator_spec.rb +25 -6
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/migration_generator_spec.rb +25 -4
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
- data/spec/lib/config_spec.rb +199 -22
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -4
- data/spec/lib/models/revocable_spec.rb +2 -4
- data/spec/lib/models/scopes_spec.rb +0 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
- data/spec/lib/oauth/authorization_code_request_spec.rb +63 -13
- data/spec/lib/oauth/base_request_spec.rb +43 -10
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +5 -5
- data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
- data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +5 -5
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +1 -3
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
- data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
- data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
- data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
- data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
- data/spec/lib/oauth/scopes_spec.rb +28 -4
- data/spec/lib/oauth/token_request_spec.rb +10 -13
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +37 -14
- data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +10 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +45 -2
- data/spec/models/doorkeeper/access_token_spec.rb +132 -64
- data/spec/models/doorkeeper/application_spec.rb +114 -23
- data/spec/requests/applications/applications_request_spec.rb +139 -6
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +1 -1
- data/spec/requests/endpoints/token_spec.rb +15 -6
- data/spec/requests/flows/authorization_code_errors_spec.rb +12 -2
- data/spec/requests/flows/authorization_code_spec.rb +199 -2
- data/spec/requests/flows/client_credentials_spec.rb +73 -5
- data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +160 -24
- data/spec/requests/flows/refresh_token_spec.rb +6 -6
- data/spec/requests/flows/revoke_token_spec.rb +26 -26
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +2 -2
- data/spec/requests/protected_resources/private_api_spec.rb +2 -2
- data/spec/routing/custom_controller_routes_spec.rb +63 -7
- data/spec/routing/default_routes_spec.rb +6 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -64
- data/spec/support/dependencies/factory_bot.rb +2 -0
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/model_helper.rb +9 -4
- data/spec/support/helpers/request_spec_helper.rb +18 -6
- data/spec/support/helpers/url_helper.rb +15 -10
- data/spec/support/http_method_shim.rb +12 -16
- 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 +58 -7
- data/spec/version/version_spec.rb +15 -0
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +75 -33
- data/spec/controllers/application_metal_controller.rb +0 -10
- data/spec/support/dependencies/factory_girl.rb +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper::OAuth
|
|
4
4
|
describe AuthorizationCodeRequest do
|
|
@@ -6,19 +6,26 @@ module Doorkeeper::OAuth
|
|
|
6
6
|
double :server,
|
|
7
7
|
access_token_expires_in: 2.days,
|
|
8
8
|
refresh_token_enabled?: false,
|
|
9
|
-
custom_access_token_expires_in:
|
|
9
|
+
custom_access_token_expires_in: lambda { |context|
|
|
10
|
+
context.grant_type == Doorkeeper::OAuth::AUTHORIZATION_CODE ? 1234 : nil
|
|
11
|
+
}
|
|
10
12
|
end
|
|
11
|
-
|
|
13
|
+
|
|
14
|
+
let(:grant) { FactoryBot.create :access_grant }
|
|
12
15
|
let(:client) { grant.application }
|
|
16
|
+
let(:redirect_uri) { client.redirect_uri }
|
|
17
|
+
let(:params) { { redirect_uri: redirect_uri } }
|
|
13
18
|
|
|
14
19
|
subject do
|
|
15
|
-
AuthorizationCodeRequest.new server, grant, client,
|
|
20
|
+
AuthorizationCodeRequest.new server, grant, client, params
|
|
16
21
|
end
|
|
17
22
|
|
|
18
23
|
it 'issues a new token for the client' do
|
|
19
24
|
expect do
|
|
20
25
|
subject.authorize
|
|
21
26
|
end.to change { client.reload.access_tokens.count }.by(1)
|
|
27
|
+
|
|
28
|
+
expect(client.reload.access_tokens.sort_by(&:created_at).last.expires_in).to eq(1234)
|
|
22
29
|
end
|
|
23
30
|
|
|
24
31
|
it "issues the token with same grant's scopes" do
|
|
@@ -27,9 +34,7 @@ module Doorkeeper::OAuth
|
|
|
27
34
|
end
|
|
28
35
|
|
|
29
36
|
it 'revokes the grant' do
|
|
30
|
-
expect
|
|
31
|
-
subject.authorize
|
|
32
|
-
end.to change { grant.reload.accessible? }
|
|
37
|
+
expect { subject.authorize }.to change { grant.reload.accessible? }
|
|
33
38
|
end
|
|
34
39
|
|
|
35
40
|
it 'requires the grant to be accessible' do
|
|
@@ -63,18 +68,63 @@ module Doorkeeper::OAuth
|
|
|
63
68
|
end
|
|
64
69
|
|
|
65
70
|
it "matches the client with grant's one" do
|
|
66
|
-
subject.client =
|
|
71
|
+
subject.client = FactoryBot.create :application
|
|
67
72
|
subject.validate
|
|
68
73
|
expect(subject.error).to eq(:invalid_grant)
|
|
69
74
|
end
|
|
70
75
|
|
|
71
76
|
it 'skips token creation if there is a matching one' do
|
|
72
|
-
|
|
73
|
-
|
|
77
|
+
scopes = grant.scopes
|
|
78
|
+
|
|
79
|
+
Doorkeeper.configure do
|
|
80
|
+
orm DOORKEEPER_ORM
|
|
81
|
+
reuse_access_token
|
|
82
|
+
default_scopes(*scopes)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
FactoryBot.create(:access_token, application_id: client.id,
|
|
74
86
|
resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
87
|
+
|
|
88
|
+
expect { subject.authorize }.to_not change { Doorkeeper::AccessToken.count }
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "calls configured request callback methods" do
|
|
92
|
+
expect(Doorkeeper.configuration.before_successful_strategy_response).to receive(:call).with(subject).once
|
|
93
|
+
expect(Doorkeeper.configuration.after_successful_strategy_response).to receive(:call).with(subject, instance_of(Doorkeeper::OAuth::TokenResponse)).once
|
|
94
|
+
subject.authorize
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
context "when redirect_uri contains some query params" do
|
|
98
|
+
let(:redirect_uri) { client.redirect_uri + "?query=q" }
|
|
99
|
+
|
|
100
|
+
it "compares only host part with grant's redirect_uri" do
|
|
101
|
+
subject.validate
|
|
102
|
+
expect(subject.error).to eq(nil)
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
context "when redirect_uri is not an URI" do
|
|
107
|
+
let(:redirect_uri) { '123d#!s' }
|
|
108
|
+
|
|
109
|
+
it "responds with invalid_grant" do
|
|
110
|
+
subject.validate
|
|
111
|
+
expect(subject.error).to eq(:invalid_grant)
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context "when redirect_uri is the native one" do
|
|
116
|
+
let(:redirect_uri) { 'urn:ietf:wg:oauth:2.0:oob' }
|
|
117
|
+
|
|
118
|
+
it "invalidates when redirect_uri of the grant is not native" do
|
|
119
|
+
subject.validate
|
|
120
|
+
expect(subject.error).to eq(:invalid_grant)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "validates when redirect_uri of the grant is also native" do
|
|
124
|
+
allow(grant).to receive(:redirect_uri) { redirect_uri }
|
|
125
|
+
subject.validate
|
|
126
|
+
expect(subject.error).to eq(nil)
|
|
127
|
+
end
|
|
78
128
|
end
|
|
79
129
|
end
|
|
80
130
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper::OAuth
|
|
4
4
|
describe BaseRequest do
|
|
@@ -13,19 +13,14 @@ 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,
|
|
27
22
|
access_token_expires_in: 100,
|
|
28
|
-
custom_access_token_expires_in: ->(
|
|
23
|
+
custom_access_token_expires_in: ->(_context) { nil },
|
|
29
24
|
refresh_token_enabled?: false
|
|
30
25
|
end
|
|
31
26
|
|
|
@@ -74,7 +69,7 @@ module Doorkeeper::OAuth
|
|
|
74
69
|
it "returns an ErrorResponse object" do
|
|
75
70
|
error_description = I18n.translate(
|
|
76
71
|
"server_error",
|
|
77
|
-
scope: [
|
|
72
|
+
scope: %i[doorkeeper errors messages]
|
|
78
73
|
)
|
|
79
74
|
|
|
80
75
|
result = subject.authorize
|
|
@@ -110,6 +105,44 @@ module Doorkeeper::OAuth
|
|
|
110
105
|
|
|
111
106
|
expect(result).to be_an_instance_of(Doorkeeper::AccessToken)
|
|
112
107
|
end
|
|
108
|
+
|
|
109
|
+
it "respects custom_access_token_expires_in" do
|
|
110
|
+
server = double(:server,
|
|
111
|
+
access_token_expires_in: 100,
|
|
112
|
+
custom_access_token_expires_in: ->(context) { context.scopes == "public" ? 500 : nil },
|
|
113
|
+
refresh_token_enabled?: false)
|
|
114
|
+
result = subject.find_or_create_access_token(
|
|
115
|
+
client,
|
|
116
|
+
"1",
|
|
117
|
+
"public",
|
|
118
|
+
server
|
|
119
|
+
)
|
|
120
|
+
expect(result.expires_in).to eql(500)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "respects use_refresh_token with a block" do
|
|
124
|
+
server = double(:server,
|
|
125
|
+
access_token_expires_in: 100,
|
|
126
|
+
custom_access_token_expires_in: ->(_context) { nil },
|
|
127
|
+
refresh_token_enabled?: lambda { |context|
|
|
128
|
+
context.scopes == "public"
|
|
129
|
+
})
|
|
130
|
+
result = subject.find_or_create_access_token(
|
|
131
|
+
client,
|
|
132
|
+
"1",
|
|
133
|
+
"public",
|
|
134
|
+
server
|
|
135
|
+
)
|
|
136
|
+
expect(result.refresh_token).to_not be_nil
|
|
137
|
+
|
|
138
|
+
result = subject.find_or_create_access_token(
|
|
139
|
+
client,
|
|
140
|
+
"1",
|
|
141
|
+
"private",
|
|
142
|
+
server
|
|
143
|
+
)
|
|
144
|
+
expect(result.refresh_token).to be_nil
|
|
145
|
+
end
|
|
113
146
|
end
|
|
114
147
|
|
|
115
148
|
describe "#scopes" do
|
|
@@ -1,22 +1,22 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'active_support/core_ext/string'
|
|
3
|
-
require 'doorkeeper/oauth/client'
|
|
4
2
|
|
|
5
3
|
class Doorkeeper::OAuth::Client
|
|
6
4
|
describe Credentials do
|
|
7
5
|
let(:client_id) { 'some-uid' }
|
|
8
6
|
let(:client_secret) { 'some-secret' }
|
|
9
7
|
|
|
10
|
-
it 'is blank when
|
|
8
|
+
it 'is blank when the uid in credentials is blank' do
|
|
9
|
+
expect(Credentials.new(nil, nil)).to be_blank
|
|
11
10
|
expect(Credentials.new(nil, 'something')).to be_blank
|
|
12
|
-
expect(Credentials.new('something', nil)).to
|
|
11
|
+
expect(Credentials.new('something', nil)).to be_present
|
|
12
|
+
expect(Credentials.new('something', 'something')).to be_present
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
describe :from_request do
|
|
16
16
|
let(:request) { double.as_null_object }
|
|
17
17
|
|
|
18
18
|
let(:method) do
|
|
19
|
-
->(_request) {
|
|
19
|
+
->(_request) { ['uid', 'secret'] }
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
it 'accepts anything that responds to #call' do
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
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
|
+
before do
|
|
9
|
+
default_scopes_exist :public
|
|
10
|
+
end
|
|
11
|
+
|
|
8
12
|
it 'creates a new token' do
|
|
9
13
|
expect do
|
|
10
14
|
subject.call(client, scopes)
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'active_support/all'
|
|
3
|
-
require 'doorkeeper/oauth/client_credentials/issuer'
|
|
4
2
|
|
|
5
3
|
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
6
4
|
describe Issuer do
|
|
@@ -9,7 +7,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
|
9
7
|
double(
|
|
10
8
|
:server,
|
|
11
9
|
access_token_expires_in: 100,
|
|
12
|
-
custom_access_token_expires_in: ->(
|
|
10
|
+
custom_access_token_expires_in: ->(_context) { nil }
|
|
13
11
|
)
|
|
14
12
|
end
|
|
15
13
|
let(:validation) { double :validation, valid?: true }
|
|
@@ -63,23 +61,44 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
|
63
61
|
end
|
|
64
62
|
|
|
65
63
|
context 'with custom expirations' do
|
|
66
|
-
let(:
|
|
64
|
+
let(:custom_ttl_grant) { 1234 }
|
|
65
|
+
let(:custom_ttl_scope) { 1235 }
|
|
66
|
+
let(:custom_scope) { 'special' }
|
|
67
67
|
let(:server) do
|
|
68
68
|
double(
|
|
69
69
|
:server,
|
|
70
|
-
custom_access_token_expires_in:
|
|
70
|
+
custom_access_token_expires_in: lambda { |context|
|
|
71
|
+
# scopes is normally an object but is a string in this test
|
|
72
|
+
if context.scopes == custom_scope
|
|
73
|
+
custom_ttl_scope
|
|
74
|
+
elsif context.grant_type == Doorkeeper::OAuth::CLIENT_CREDENTIALS
|
|
75
|
+
custom_ttl_grant
|
|
76
|
+
else
|
|
77
|
+
nil
|
|
78
|
+
end
|
|
79
|
+
}
|
|
71
80
|
)
|
|
72
81
|
end
|
|
73
82
|
|
|
74
|
-
it '
|
|
83
|
+
it 'respects grant based rules' do
|
|
75
84
|
expect(creator).to receive(:call).with(
|
|
76
85
|
client,
|
|
77
86
|
scopes,
|
|
78
|
-
expires_in:
|
|
87
|
+
expires_in: custom_ttl_grant,
|
|
79
88
|
use_refresh_token: false
|
|
80
89
|
)
|
|
81
90
|
subject.create client, scopes, creator
|
|
82
91
|
end
|
|
92
|
+
|
|
93
|
+
it 'respects scope based rules' do
|
|
94
|
+
expect(creator).to receive(:call).with(
|
|
95
|
+
client,
|
|
96
|
+
custom_scope,
|
|
97
|
+
expires_in: custom_ttl_scope,
|
|
98
|
+
use_refresh_token: false
|
|
99
|
+
)
|
|
100
|
+
subject.create client, custom_scope, creator
|
|
101
|
+
end
|
|
83
102
|
end
|
|
84
103
|
end
|
|
85
104
|
end
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'active_support/all'
|
|
3
|
-
require 'doorkeeper/oauth/client_credentials/validation'
|
|
4
2
|
|
|
5
3
|
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
6
4
|
describe Validation do
|
|
@@ -45,7 +43,8 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
|
45
43
|
allow(application).to receive(:scopes).and_return(application_scopes)
|
|
46
44
|
allow(server).to receive(:scopes).and_return(server_scopes)
|
|
47
45
|
allow(request).to receive(:scopes).and_return(
|
|
48
|
-
Doorkeeper::OAuth::Scopes.from_string
|
|
46
|
+
Doorkeeper::OAuth::Scopes.from_string('email')
|
|
47
|
+
)
|
|
49
48
|
expect(subject).not_to be_valid
|
|
50
49
|
end
|
|
51
50
|
end
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper::OAuth
|
|
4
4
|
describe ClientCredentialsRequest do
|
|
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, {})
|
|
@@ -1,17 +1,16 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'active_support/all'
|
|
3
|
-
require 'active_model'
|
|
4
|
-
require 'doorkeeper/oauth/client_credentials_request'
|
|
5
2
|
|
|
6
3
|
module Doorkeeper::OAuth
|
|
7
4
|
describe ClientCredentialsRequest do
|
|
8
5
|
let(:server) do
|
|
9
6
|
double(
|
|
10
7
|
default_scopes: nil,
|
|
11
|
-
|
|
8
|
+
access_token_expires_in: 2.hours,
|
|
9
|
+
custom_access_token_expires_in: ->(_context) { nil }
|
|
12
10
|
)
|
|
13
11
|
end
|
|
14
|
-
|
|
12
|
+
|
|
13
|
+
let(:application) { FactoryBot.create(:application, scopes: '') }
|
|
15
14
|
let(:client) { double :client, application: application }
|
|
16
15
|
let(:token_creator) { double :issuer, create: true, token: double }
|
|
17
16
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper::OAuth
|
|
4
4
|
describe CodeRequest do
|
|
@@ -10,7 +10,9 @@ module Doorkeeper::OAuth
|
|
|
10
10
|
scopes: nil,
|
|
11
11
|
state: nil,
|
|
12
12
|
error: nil,
|
|
13
|
-
authorizable?: true
|
|
13
|
+
authorizable?: true,
|
|
14
|
+
code_challenge: nil,
|
|
15
|
+
code_challenge_method: nil,
|
|
14
16
|
)
|
|
15
17
|
end
|
|
16
18
|
|
|
@@ -32,9 +34,7 @@ module Doorkeeper::OAuth
|
|
|
32
34
|
|
|
33
35
|
it 'does not create grant when not authorizable' do
|
|
34
36
|
allow(pre_auth).to receive(:authorizable?).and_return(false)
|
|
35
|
-
expect
|
|
36
|
-
subject.authorize
|
|
37
|
-
end.to_not change { Doorkeeper::AccessGrant.count }
|
|
37
|
+
expect { subject.authorize }.not_to change { Doorkeeper::AccessGrant.count }
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
it 'returns a error response' do
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'active_support/i18n'
|
|
3
|
-
require 'doorkeeper/oauth/error'
|
|
4
2
|
|
|
5
3
|
module Doorkeeper::OAuth
|
|
6
4
|
describe Error do
|
|
@@ -13,7 +11,7 @@ module Doorkeeper::OAuth
|
|
|
13
11
|
it 'is translated from translation messages' do
|
|
14
12
|
expect(I18n).to receive(:translate).with(
|
|
15
13
|
:some_error,
|
|
16
|
-
scope: [
|
|
14
|
+
scope: %i[doorkeeper errors messages],
|
|
17
15
|
default: :server_error
|
|
18
16
|
)
|
|
19
17
|
error.description
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'active_model'
|
|
3
|
-
require 'doorkeeper'
|
|
4
|
-
require 'doorkeeper/oauth/forbidden_token_response'
|
|
5
2
|
|
|
6
3
|
module Doorkeeper::OAuth
|
|
7
4
|
describe ForbiddenTokenResponse do
|
|
8
5
|
describe '#name' do
|
|
9
|
-
it
|
|
6
|
+
it { expect(subject.name).to eq(:invalid_scope) }
|
|
10
7
|
end
|
|
11
8
|
|
|
12
9
|
describe '#status' do
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'uri'
|
|
3
|
-
require 'doorkeeper/oauth/helpers/uri_checker'
|
|
4
2
|
|
|
5
3
|
module Doorkeeper::OAuth::Helpers
|
|
6
4
|
describe URIChecker do
|
|
@@ -39,6 +37,16 @@ module Doorkeeper::OAuth::Helpers
|
|
|
39
37
|
uri = 'http://'
|
|
40
38
|
expect(URIChecker.valid?(uri)).to be_falsey
|
|
41
39
|
end
|
|
40
|
+
|
|
41
|
+
it 'is invalid if is not an uri' do
|
|
42
|
+
uri = ' '
|
|
43
|
+
expect(URIChecker.valid?(uri)).to be_falsey
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'is valid for native uris' do
|
|
47
|
+
uri = 'urn:ietf:wg:oauth:2.0:oob'
|
|
48
|
+
expect(URIChecker.valid?(uri)).to be_truthy
|
|
49
|
+
end
|
|
42
50
|
end
|
|
43
51
|
|
|
44
52
|
describe '.matches?' do
|
|
@@ -64,6 +72,44 @@ module Doorkeeper::OAuth::Helpers
|
|
|
64
72
|
client_uri = 'http://example.com?app.co=test'
|
|
65
73
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
66
74
|
end
|
|
75
|
+
|
|
76
|
+
context "client registered query params" do
|
|
77
|
+
it "doesn't allow query being absent" do
|
|
78
|
+
uri = 'http://app.co'
|
|
79
|
+
client_uri = 'http://app.co/?vendorId=AJ4L7XXW9'
|
|
80
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "is false if query values differ but key same" do
|
|
84
|
+
uri = 'http://app.co/?vendorId=pancakes'
|
|
85
|
+
client_uri = 'http://app.co/?vendorId=waffles'
|
|
86
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "is false if query values same but key differs" do
|
|
90
|
+
uri = 'http://app.co/?foo=pancakes'
|
|
91
|
+
client_uri = 'http://app.co/?bar=pancakes'
|
|
92
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it "is false if query present and match, but unknown queries present" do
|
|
96
|
+
uri = 'http://app.co/?vendorId=pancakes&unknown=query'
|
|
97
|
+
client_uri = 'http://app.co/?vendorId=waffles'
|
|
98
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "is true if queries are present and matche" do
|
|
102
|
+
uri = 'http://app.co/?vendorId=AJ4L7XXW9&foo=bar'
|
|
103
|
+
client_uri = 'http://app.co/?vendorId=AJ4L7XXW9&foo=bar'
|
|
104
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it "is true if queries are present, match and in different order" do
|
|
108
|
+
uri = 'http://app.co/?bing=bang&foo=bar'
|
|
109
|
+
client_uri = 'http://app.co/?foo=bar&bing=bang'
|
|
110
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
|
111
|
+
end
|
|
112
|
+
end
|
|
67
113
|
end
|
|
68
114
|
|
|
69
115
|
describe '.valid_for_authorization?' do
|
|
@@ -96,9 +142,75 @@ module Doorkeeper::OAuth::Helpers
|
|
|
96
142
|
end
|
|
97
143
|
|
|
98
144
|
it 'is false if invalid' do
|
|
99
|
-
uri =
|
|
145
|
+
uri = 'http://app.co/aaa?pankcakes=abc'
|
|
146
|
+
client_uri = 'http://app.co/aaa?waffles=abc'
|
|
100
147
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be false
|
|
101
148
|
end
|
|
149
|
+
|
|
150
|
+
it 'calls .matches?' do
|
|
151
|
+
uri = 'http://app.co/aaa?pankcakes=abc'
|
|
152
|
+
client_uri = 'http://app.co/aaa?waffles=abc'
|
|
153
|
+
expect(URIChecker).to receive(:matches?).with(uri, client_uri).once
|
|
154
|
+
URIChecker.valid_for_authorization?(uri, client_uri)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
it 'calls .valid?' do
|
|
158
|
+
uri = 'http://app.co/aaa?pankcakes=abc'
|
|
159
|
+
client_uri = 'http://app.co/aaa?waffles=abc'
|
|
160
|
+
expect(URIChecker).to receive(:valid?).with(uri).once
|
|
161
|
+
URIChecker.valid_for_authorization?(uri, client_uri)
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
describe '.query_matches?' do
|
|
166
|
+
it 'is true if no queries' do
|
|
167
|
+
expect(URIChecker.query_matches?('', '')).to be_truthy
|
|
168
|
+
expect(URIChecker.query_matches?(nil, nil)).to be_truthy
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it 'is true if same query' do
|
|
172
|
+
expect(URIChecker.query_matches?('foo', 'foo')).to be_truthy
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it 'is false if different query' do
|
|
176
|
+
expect(URIChecker.query_matches?('foo', 'bar')).to be_falsey
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
it 'is true if same queries' do
|
|
180
|
+
expect(URIChecker.query_matches?('foo&bar', 'foo&bar')).to be_truthy
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
it 'is true if same queries, different order' do
|
|
184
|
+
expect(URIChecker.query_matches?('foo&bar', 'bar&foo')).to be_truthy
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
it 'is false if one different query' do
|
|
188
|
+
expect(URIChecker.query_matches?('foo&bang', 'foo&bing')).to be_falsey
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
it 'is true if same query with same value' do
|
|
192
|
+
expect(URIChecker.query_matches?('foo=bar', 'foo=bar')).to be_truthy
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
it 'is true if same queries with same values' do
|
|
196
|
+
expect(URIChecker.query_matches?('foo=bar&bing=bang', 'foo=bar&bing=bang')).to be_truthy
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
it 'is true if same queries with same values, different order' do
|
|
200
|
+
expect(URIChecker.query_matches?('foo=bar&bing=bang', 'bing=bang&foo=bar')).to be_truthy
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it 'is false if same query with different value' do
|
|
204
|
+
expect(URIChecker.query_matches?('foo=bar', 'foo=bang')).to be_falsey
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it 'is false if some queries missing' do
|
|
208
|
+
expect(URIChecker.query_matches?('foo=bar', 'foo=bar&bing=bang')).to be_falsey
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'is false if some queries different value' do
|
|
212
|
+
expect(URIChecker.query_matches?('foo=bar&bing=bang', 'foo=bar&bing=banana')).to be_falsey
|
|
213
|
+
end
|
|
102
214
|
end
|
|
103
215
|
end
|
|
104
216
|
end
|
|
@@ -1,12 +1,9 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'active_model'
|
|
3
|
-
require 'doorkeeper'
|
|
4
|
-
require 'doorkeeper/oauth/invalid_token_response'
|
|
5
2
|
|
|
6
3
|
module Doorkeeper::OAuth
|
|
7
4
|
describe InvalidTokenResponse do
|
|
8
5
|
describe "#name" do
|
|
9
|
-
it
|
|
6
|
+
it { expect(subject.name).to eq(:invalid_token) }
|
|
10
7
|
end
|
|
11
8
|
|
|
12
9
|
describe "#status" do
|
|
@@ -40,7 +37,7 @@ module Doorkeeper::OAuth
|
|
|
40
37
|
end
|
|
41
38
|
end
|
|
42
39
|
|
|
43
|
-
context "
|
|
40
|
+
context "unknown" do
|
|
44
41
|
let(:access_token) { double(revoked?: false, expired?: false) }
|
|
45
42
|
|
|
46
43
|
it "sets a description" do
|