doorkeeper 5.0.3 → 5.1.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/.hound.yml +2 -1
- data/.rubocop.yml +37 -4
- data/.travis.yml +11 -21
- data/Appraisals +29 -7
- data/Dangerfile +5 -2
- data/Gemfile +19 -5
- data/NEWS.md +81 -21
- data/README.md +75 -485
- data/Rakefile +10 -8
- data/app/controllers/doorkeeper/application_controller.rb +1 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -13
- data/app/controllers/doorkeeper/applications_controller.rb +20 -8
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/token_info_controller.rb +2 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +11 -11
- data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
- data/app/validators/redirect_uri_validator.rb +5 -2
- data/app/views/doorkeeper/applications/_form.html.erb +6 -0
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
- data/bin/console +16 -0
- data/config/locales/en.yml +1 -0
- data/doorkeeper.gemspec +24 -21
- data/gemfiles/rails_5_0.gemfile +9 -4
- data/gemfiles/rails_5_1.gemfile +9 -4
- data/gemfiles/rails_5_2.gemfile +10 -5
- data/gemfiles/rails_6_0.gemfile +17 -0
- data/gemfiles/rails_master.gemfile +9 -9
- data/lib/doorkeeper/config/option.rb +64 -0
- data/lib/doorkeeper/config.rb +191 -75
- data/lib/doorkeeper/engine.rb +1 -1
- data/lib/doorkeeper/grape/authorization_decorator.rb +4 -4
- data/lib/doorkeeper/grape/helpers.rb +3 -3
- data/lib/doorkeeper/helpers/controller.rb +3 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +20 -3
- data/lib/doorkeeper/models/access_token_mixin.rb +63 -19
- data/lib/doorkeeper/models/application_mixin.rb +43 -1
- data/lib/doorkeeper/models/concerns/expirable.rb +4 -2
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +2 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +12 -7
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -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_response.rb +10 -6
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -1
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +11 -5
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
- data/lib/doorkeeper/oauth/scopes.rb +5 -3
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +74 -8
- data/lib/doorkeeper/oauth/token_response.rb +9 -9
- data/lib/doorkeeper/oauth.rb +5 -5
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
- data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
- data/lib/doorkeeper/orm/active_record/application.rb +21 -57
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
- data/lib/doorkeeper/orm/active_record.rb +6 -6
- data/lib/doorkeeper/rails/helpers.rb +1 -1
- data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
- data/lib/doorkeeper/rails/routes.rb +11 -11
- data/lib/doorkeeper/rake/db.rake +13 -13
- data/lib/doorkeeper/rake.rb +1 -1
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/secret_storing/base.rb +64 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +3 -3
- data/lib/doorkeeper.rb +69 -60
- data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
- data/lib/generators/doorkeeper/install_generator.rb +11 -9
- data/lib/generators/doorkeeper/migration_generator.rb +9 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
- data/lib/generators/doorkeeper/templates/initializer.rb +120 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -7
- data/lib/generators/doorkeeper/views_generator.rb +6 -4
- data/spec/controllers/application_metal_controller_spec.rb +24 -10
- data/spec/controllers/applications_controller_spec.rb +54 -52
- data/spec/controllers/authorizations_controller_spec.rb +139 -145
- data/spec/controllers/protected_resources_controller_spec.rb +78 -76
- data/spec/controllers/token_info_controller_spec.rb +14 -12
- data/spec/controllers/tokens_controller_spec.rb +167 -108
- data/spec/dummy/Rakefile +3 -1
- data/spec/dummy/app/controllers/application_controller.rb +3 -1
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +2 -0
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/controllers/home_controller.rb +5 -3
- data/spec/dummy/app/controllers/metal_controller.rb +2 -0
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/config/application.rb +25 -1
- data/spec/dummy/config/environments/development.rb +2 -0
- data/spec/dummy/config/environments/production.rb +2 -0
- data/spec/dummy/config/environments/test.rb +3 -1
- data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +5 -2
- data/spec/dummy/config/initializers/secret_token.rb +3 -1
- data/spec/dummy/config/initializers/session_store.rb +3 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
- data/spec/dummy/config.ru +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +17 -10
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/script/rails +5 -3
- data/spec/factories.rb +8 -6
- data/spec/generators/application_owner_generator_spec.rb +13 -26
- data/spec/generators/confidential_applications_generator_spec.rb +12 -28
- data/spec/generators/install_generator_spec.rb +17 -15
- data/spec/generators/migration_generator_spec.rb +13 -26
- data/spec/generators/pkce_generator_spec.rb +11 -26
- data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
- data/spec/generators/templates/routes.rb +2 -0
- data/spec/generators/views_generator_spec.rb +14 -12
- data/spec/grape/grape_integration_spec.rb +34 -32
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
- data/spec/lib/config_spec.rb +268 -99
- data/spec/lib/doorkeeper_spec.rb +3 -1
- data/spec/lib/models/expirable_spec.rb +22 -8
- data/spec/lib/models/reusable_spec.rb +40 -0
- data/spec/lib/models/revocable_spec.rb +8 -6
- data/spec/lib/models/scopes_spec.rb +27 -13
- data/spec/lib/models/secret_storable_spec.rb +135 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
- data/spec/lib/oauth/authorization_code_request_spec.rb +34 -11
- data/spec/lib/oauth/base_request_spec.rb +20 -8
- data/spec/lib/oauth/base_response_spec.rb +3 -1
- data/spec/lib/oauth/client/credentials_spec.rb +24 -22
- data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
- data/spec/lib/oauth/client_credentials/validation_spec.rb +20 -15
- data/spec/lib/oauth/client_credentials_integration_spec.rb +7 -5
- data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
- data/spec/lib/oauth/client_spec.rb +15 -13
- data/spec/lib/oauth/code_request_spec.rb +8 -6
- data/spec/lib/oauth/code_response_spec.rb +9 -7
- data/spec/lib/oauth/error_response_spec.rb +19 -11
- data/spec/lib/oauth/error_spec.rb +4 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
- data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -95
- data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +79 -30
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
- data/spec/lib/oauth/refresh_token_request_spec.rb +36 -33
- data/spec/lib/oauth/scopes_spec.rb +63 -61
- data/spec/lib/oauth/token_request_spec.rb +79 -24
- data/spec/lib/oauth/token_response_spec.rb +40 -38
- data/spec/lib/oauth/token_spec.rb +60 -44
- data/spec/lib/request/strategy_spec.rb +3 -1
- data/spec/lib/secret_storing/base_spec.rb +60 -0
- data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
- data/spec/lib/secret_storing/plain_spec.rb +44 -0
- data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
- data/spec/lib/server_spec.rb +16 -14
- data/spec/lib/stale_records_cleaner_spec.rb +17 -17
- data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
- data/spec/models/doorkeeper/access_token_spec.rb +198 -73
- data/spec/models/doorkeeper/application_spec.rb +280 -288
- data/spec/requests/applications/applications_request_spec.rb +98 -66
- data/spec/requests/applications/authorized_applications_spec.rb +20 -18
- data/spec/requests/endpoints/authorization_spec.rb +25 -23
- data/spec/requests/endpoints/token_spec.rb +38 -36
- data/spec/requests/flows/authorization_code_errors_spec.rb +26 -24
- data/spec/requests/flows/authorization_code_spec.rb +193 -151
- data/spec/requests/flows/client_credentials_spec.rb +54 -52
- data/spec/requests/flows/implicit_grant_errors_spec.rb +10 -8
- data/spec/requests/flows/implicit_grant_spec.rb +27 -25
- data/spec/requests/flows/password_spec.rb +59 -55
- data/spec/requests/flows/refresh_token_spec.rb +45 -43
- data/spec/requests/flows/revoke_token_spec.rb +40 -54
- data/spec/requests/flows/skip_authorization_spec.rb +23 -21
- data/spec/requests/protected_resources/metal_spec.rb +7 -5
- data/spec/requests/protected_resources/private_api_spec.rb +35 -33
- data/spec/routing/custom_controller_routes_spec.rb +71 -65
- data/spec/routing/default_routes_spec.rb +22 -20
- data/spec/routing/scoped_routes_spec.rb +20 -18
- data/spec/spec_helper.rb +15 -13
- data/spec/spec_helper_integration.rb +3 -1
- data/spec/support/dependencies/factory_bot.rb +3 -1
- data/spec/support/doorkeeper_rspec.rb +3 -1
- data/spec/support/helpers/access_token_request_helper.rb +3 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -2
- data/spec/support/helpers/config_helper.rb +2 -0
- data/spec/support/helpers/model_helper.rb +3 -1
- data/spec/support/helpers/request_spec_helper.rb +5 -3
- data/spec/support/helpers/url_helper.rb +9 -7
- data/spec/support/http_method_shim.rb +4 -9
- data/spec/support/orm/active_record.rb +3 -1
- data/spec/support/shared/controllers_shared_context.rb +18 -16
- data/spec/support/shared/hashing_shared_context.rb +36 -0
- data/spec/support/shared/models_shared_examples.rb +12 -10
- data/spec/validators/redirect_uri_validator_spec.rb +74 -45
- data/spec/version/version_spec.rb +7 -5
- metadata +60 -26
- data/gemfiles/rails_4_2.gemfile +0 -13
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
|
@@ -1,50 +1,58 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper::OAuth
|
|
4
6
|
describe ErrorResponse do
|
|
5
|
-
describe
|
|
6
|
-
it
|
|
7
|
+
describe "#status" do
|
|
8
|
+
it "should have a status of bad_request" do
|
|
9
|
+
expect(subject.status).to eq(:bad_request)
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should have a status of unauthorized for an invalid_client error" do
|
|
13
|
+
subject = described_class.new(name: :invalid_client)
|
|
14
|
+
|
|
7
15
|
expect(subject.status).to eq(:unauthorized)
|
|
8
16
|
end
|
|
9
17
|
end
|
|
10
18
|
|
|
11
19
|
describe :from_request do
|
|
12
|
-
it
|
|
20
|
+
it "has the error from request" do
|
|
13
21
|
error = ErrorResponse.from_request double(error: :some_error)
|
|
14
22
|
expect(error.name).to eq(:some_error)
|
|
15
23
|
end
|
|
16
24
|
|
|
17
|
-
it
|
|
25
|
+
it "ignores state if request does not respond to state" do
|
|
18
26
|
error = ErrorResponse.from_request double(error: :some_error)
|
|
19
27
|
expect(error.state).to be_nil
|
|
20
28
|
end
|
|
21
29
|
|
|
22
|
-
it
|
|
30
|
+
it "has state if request responds to state" do
|
|
23
31
|
error = ErrorResponse.from_request double(error: :some_error, state: :hello)
|
|
24
32
|
expect(error.state).to eq(:hello)
|
|
25
33
|
end
|
|
26
34
|
end
|
|
27
35
|
|
|
28
|
-
it
|
|
36
|
+
it "ignores empty error values" do
|
|
29
37
|
subject = ErrorResponse.new(error: :some_error, state: nil)
|
|
30
38
|
expect(subject.body).not_to have_key(:state)
|
|
31
39
|
end
|
|
32
40
|
|
|
33
|
-
describe
|
|
41
|
+
describe ".body" do
|
|
34
42
|
subject { ErrorResponse.new(name: :some_error, state: :some_state).body }
|
|
35
43
|
|
|
36
|
-
describe
|
|
44
|
+
describe "#body" do
|
|
37
45
|
it { expect(subject).to have_key(:error) }
|
|
38
46
|
it { expect(subject).to have_key(:error_description) }
|
|
39
47
|
it { expect(subject).to have_key(:state) }
|
|
40
48
|
end
|
|
41
49
|
end
|
|
42
50
|
|
|
43
|
-
describe
|
|
51
|
+
describe ".headers" do
|
|
44
52
|
let(:error_response) { ErrorResponse.new(name: :some_error, state: :some_state) }
|
|
45
53
|
subject { error_response.headers }
|
|
46
54
|
|
|
47
|
-
it { expect(subject).to include
|
|
55
|
+
it { expect(subject).to include "WWW-Authenticate" }
|
|
48
56
|
|
|
49
57
|
describe "WWW-Authenticate header" do
|
|
50
58
|
subject { error_response.headers["WWW-Authenticate"] }
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper::OAuth
|
|
4
6
|
describe Error do
|
|
@@ -8,7 +10,7 @@ module Doorkeeper::OAuth
|
|
|
8
10
|
it { expect(subject).to respond_to(:state) }
|
|
9
11
|
|
|
10
12
|
describe :description do
|
|
11
|
-
it
|
|
13
|
+
it "is translated from translation messages" do
|
|
12
14
|
expect(I18n).to receive(:translate).with(
|
|
13
15
|
:some_error,
|
|
14
16
|
scope: %i[doorkeeper errors messages],
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper::OAuth
|
|
4
6
|
describe ForbiddenTokenResponse do
|
|
5
|
-
describe
|
|
7
|
+
describe "#name" do
|
|
6
8
|
it { expect(subject.name).to eq(:invalid_scope) }
|
|
7
9
|
end
|
|
8
10
|
|
|
9
|
-
describe
|
|
11
|
+
describe "#status" do
|
|
10
12
|
it { expect(subject.status).to eq(:forbidden) }
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
describe :from_scopes do
|
|
14
|
-
it
|
|
16
|
+
it "should have a list of acceptable scopes" do
|
|
15
17
|
response = ForbiddenTokenResponse.from_scopes(["public"])
|
|
16
|
-
expect(response.description).to include(
|
|
18
|
+
expect(response.description).to include("public")
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -1,60 +1,97 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper::OAuth::Helpers
|
|
4
|
-
describe ScopeChecker,
|
|
6
|
+
describe ScopeChecker, ".valid?" do
|
|
5
7
|
let(:server_scopes) { Doorkeeper::OAuth::Scopes.new }
|
|
6
8
|
|
|
7
|
-
it
|
|
9
|
+
it "is valid if scope is present" do
|
|
8
10
|
server_scopes.add :scope
|
|
9
|
-
expect(ScopeChecker.valid?(
|
|
11
|
+
expect(ScopeChecker.valid?(scope_str: "scope", server_scopes: server_scopes)).to be_truthy
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
it
|
|
13
|
-
expect(ScopeChecker.valid?("\tsomething", server_scopes)).to be_falsey
|
|
14
|
+
it "is invalid if includes tabs space" do
|
|
15
|
+
expect(ScopeChecker.valid?(scope_str: "\tsomething", server_scopes: server_scopes)).to be_falsey
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
it
|
|
17
|
-
expect(ScopeChecker.valid?(nil, server_scopes)).to be_falsey
|
|
18
|
+
it "is invalid if scope is not present" do
|
|
19
|
+
expect(ScopeChecker.valid?(scope_str: nil, server_scopes: server_scopes)).to be_falsey
|
|
18
20
|
end
|
|
19
21
|
|
|
20
|
-
it
|
|
21
|
-
expect(ScopeChecker.valid?(
|
|
22
|
+
it "is invalid if scope is blank" do
|
|
23
|
+
expect(ScopeChecker.valid?(scope_str: " ", server_scopes: server_scopes)).to be_falsey
|
|
22
24
|
end
|
|
23
25
|
|
|
24
|
-
it
|
|
25
|
-
expect(ScopeChecker.valid?("scope\r", server_scopes)).to be_falsey
|
|
26
|
+
it "is invalid if includes return space" do
|
|
27
|
+
expect(ScopeChecker.valid?(scope_str: "scope\r", server_scopes: server_scopes)).to be_falsey
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
it
|
|
29
|
-
expect(ScopeChecker.valid?("scope\nanother", server_scopes)).to be_falsey
|
|
30
|
+
it "is invalid if includes new lines" do
|
|
31
|
+
expect(ScopeChecker.valid?(scope_str: "scope\nanother", server_scopes: server_scopes)).to be_falsey
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
it
|
|
33
|
-
expect(ScopeChecker.valid?(
|
|
34
|
+
it "is invalid if any scope is not included in server scopes" do
|
|
35
|
+
expect(ScopeChecker.valid?(scope_str: "scope another", server_scopes: server_scopes)).to be_falsey
|
|
34
36
|
end
|
|
35
37
|
|
|
36
|
-
context
|
|
38
|
+
context "with application_scopes" do
|
|
37
39
|
let(:server_scopes) do
|
|
38
|
-
Doorkeeper::OAuth::Scopes.from_string
|
|
40
|
+
Doorkeeper::OAuth::Scopes.from_string "common svr"
|
|
39
41
|
end
|
|
40
42
|
let(:application_scopes) do
|
|
41
|
-
Doorkeeper::OAuth::Scopes.from_string
|
|
43
|
+
Doorkeeper::OAuth::Scopes.from_string "app123"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "is valid if scope is included in the application scope list" do
|
|
47
|
+
expect(ScopeChecker.valid?(scope_str: "app123",
|
|
48
|
+
server_scopes: server_scopes,
|
|
49
|
+
app_scopes: application_scopes)).to be_truthy
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "is invalid if any scope is not included in the application" do
|
|
53
|
+
expect(ScopeChecker.valid?(scope_str: "svr",
|
|
54
|
+
server_scopes: server_scopes,
|
|
55
|
+
app_scopes: application_scopes)).to be_falsey
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
context "with grant_type" do
|
|
60
|
+
let(:server_scopes) do
|
|
61
|
+
Doorkeeper::OAuth::Scopes.from_string "scope1 scope2"
|
|
42
62
|
end
|
|
43
63
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
64
|
+
context "with scopes_by_grant_type not configured for grant_type" do
|
|
65
|
+
it "is valid if the scope is in server scopes" do
|
|
66
|
+
expect(ScopeChecker.valid?(scope_str: "scope1",
|
|
67
|
+
server_scopes: server_scopes,
|
|
68
|
+
grant_type: Doorkeeper::OAuth::PASSWORD)).to be_truthy
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "is invalid if the scope is not in server scopes" do
|
|
72
|
+
expect(ScopeChecker.valid?(scope_str: "unknown",
|
|
73
|
+
server_scopes: server_scopes,
|
|
74
|
+
grant_type: Doorkeeper::OAuth::PASSWORD)).to be_falsey
|
|
75
|
+
end
|
|
50
76
|
end
|
|
51
77
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
context "when scopes_by_grant_type configured for grant_type" do
|
|
79
|
+
before do
|
|
80
|
+
allow(Doorkeeper.configuration).to receive(:scopes_by_grant_type)
|
|
81
|
+
.and_return(password: [:scope1])
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "is valid if the scope is permitted for grant_type" do
|
|
85
|
+
expect(ScopeChecker.valid?(scope_str: "scope1",
|
|
86
|
+
server_scopes: server_scopes,
|
|
87
|
+
grant_type: Doorkeeper::OAuth::PASSWORD)).to be_truthy
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "is invalid if the scope is permitted for grant_type" do
|
|
91
|
+
expect(ScopeChecker.valid?(scope_str: "scope2",
|
|
92
|
+
server_scopes: server_scopes,
|
|
93
|
+
grant_type: Doorkeeper::OAuth::PASSWORD)).to be_falsey
|
|
94
|
+
end
|
|
58
95
|
end
|
|
59
96
|
end
|
|
60
97
|
end
|
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper::OAuth::Helpers
|
|
4
6
|
describe UniqueToken do
|
|
5
7
|
let :generator do
|
|
6
|
-
->(size) {
|
|
8
|
+
->(size) { "a" * size }
|
|
7
9
|
end
|
|
8
10
|
|
|
9
|
-
it
|
|
11
|
+
it "is able to customize the generator method" do
|
|
10
12
|
token = UniqueToken.generate(generator: generator)
|
|
11
|
-
expect(token).to eq(
|
|
13
|
+
expect(token).to eq("a" * 32)
|
|
12
14
|
end
|
|
13
15
|
|
|
14
|
-
it
|
|
16
|
+
it "is able to customize the size of the token" do
|
|
15
17
|
token = UniqueToken.generate(generator: generator, size: 2)
|
|
16
|
-
expect(token).to eq(
|
|
18
|
+
expect(token).to eq("aa")
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
end
|
|
@@ -1,226 +1,246 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper::OAuth::Helpers
|
|
4
6
|
describe URIChecker do
|
|
5
|
-
describe
|
|
6
|
-
it
|
|
7
|
-
uri =
|
|
7
|
+
describe ".valid?" do
|
|
8
|
+
it "is valid for valid uris" do
|
|
9
|
+
uri = "http://app.co"
|
|
8
10
|
expect(URIChecker.valid?(uri)).to be_truthy
|
|
9
11
|
end
|
|
10
12
|
|
|
11
|
-
it
|
|
12
|
-
uri =
|
|
13
|
+
it "is valid if include path param" do
|
|
14
|
+
uri = "http://app.co/path"
|
|
13
15
|
expect(URIChecker.valid?(uri)).to be_truthy
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
it
|
|
17
|
-
uri =
|
|
18
|
+
it "is valid if include query param" do
|
|
19
|
+
uri = "http://app.co/?query=1"
|
|
18
20
|
expect(URIChecker.valid?(uri)).to be_truthy
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
it
|
|
22
|
-
uri =
|
|
23
|
+
it "is invalid if uri includes fragment" do
|
|
24
|
+
uri = "http://app.co/test#fragment"
|
|
23
25
|
expect(URIChecker.valid?(uri)).to be_falsey
|
|
24
26
|
end
|
|
25
27
|
|
|
26
|
-
it
|
|
27
|
-
uri =
|
|
28
|
+
it "is invalid if scheme is missing" do
|
|
29
|
+
uri = "app.co"
|
|
28
30
|
expect(URIChecker.valid?(uri)).to be_falsey
|
|
29
31
|
end
|
|
30
32
|
|
|
31
|
-
it
|
|
32
|
-
uri =
|
|
33
|
+
it "is invalid if is a relative uri" do
|
|
34
|
+
uri = "/abc/123"
|
|
33
35
|
expect(URIChecker.valid?(uri)).to be_falsey
|
|
34
36
|
end
|
|
35
37
|
|
|
36
|
-
it
|
|
37
|
-
uri =
|
|
38
|
+
it "is invalid if is not a url" do
|
|
39
|
+
uri = "http://"
|
|
38
40
|
expect(URIChecker.valid?(uri)).to be_falsey
|
|
39
41
|
end
|
|
40
42
|
|
|
41
|
-
it
|
|
42
|
-
uri =
|
|
43
|
+
it "is invalid if is not an uri" do
|
|
44
|
+
uri = " "
|
|
43
45
|
expect(URIChecker.valid?(uri)).to be_falsey
|
|
44
46
|
end
|
|
45
47
|
|
|
46
|
-
it
|
|
47
|
-
uri =
|
|
48
|
+
it "is valid for native uris" do
|
|
49
|
+
uri = "urn:ietf:wg:oauth:2.0:oob"
|
|
48
50
|
expect(URIChecker.valid?(uri)).to be_truthy
|
|
49
51
|
end
|
|
50
52
|
end
|
|
51
53
|
|
|
52
|
-
describe
|
|
53
|
-
it
|
|
54
|
-
uri = client_uri =
|
|
54
|
+
describe ".matches?" do
|
|
55
|
+
it "is true if both url matches" do
|
|
56
|
+
uri = client_uri = "http://app.co/aaa"
|
|
55
57
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
|
56
58
|
end
|
|
57
59
|
|
|
58
|
-
it
|
|
59
|
-
uri =
|
|
60
|
-
client_uri =
|
|
60
|
+
it "ignores query parameter on comparsion" do
|
|
61
|
+
uri = "http://app.co/?query=hello"
|
|
62
|
+
client_uri = "http://app.co"
|
|
61
63
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
|
62
64
|
end
|
|
63
65
|
|
|
64
|
-
it
|
|
65
|
-
uri =
|
|
66
|
-
client_uri =
|
|
66
|
+
it "doesn't allow non-matching domains through" do
|
|
67
|
+
uri = "http://app.abc/?query=hello"
|
|
68
|
+
client_uri = "http://app.co"
|
|
67
69
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
68
70
|
end
|
|
69
71
|
|
|
70
|
-
it
|
|
71
|
-
uri =
|
|
72
|
-
client_uri =
|
|
72
|
+
it "doesn't allow non-matching domains that don't start at the beginning" do
|
|
73
|
+
uri = "http://app.co/?query=hello"
|
|
74
|
+
client_uri = "http://example.com?app.co=test"
|
|
73
75
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
74
76
|
end
|
|
75
77
|
|
|
78
|
+
context "loopback IP redirect URIs" do
|
|
79
|
+
it "ignores port for same URIs" do
|
|
80
|
+
uri = "http://127.0.0.1:5555/auth/callback"
|
|
81
|
+
client_uri = "http://127.0.0.1:48599/auth/callback"
|
|
82
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
|
83
|
+
|
|
84
|
+
uri = "http://[::1]:5555/auth/callback"
|
|
85
|
+
client_uri = "http://[::1]:5555/auth/callback"
|
|
86
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "doesn't ignore port for URIs with different queries" do
|
|
90
|
+
uri = "http://127.0.0.1:5555/auth/callback"
|
|
91
|
+
client_uri = "http://127.0.0.1:48599/auth/callback2"
|
|
92
|
+
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
76
96
|
context "client registered query params" do
|
|
77
97
|
it "doesn't allow query being absent" do
|
|
78
|
-
uri =
|
|
79
|
-
client_uri =
|
|
98
|
+
uri = "http://app.co"
|
|
99
|
+
client_uri = "http://app.co/?vendorId=AJ4L7XXW9"
|
|
80
100
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
81
101
|
end
|
|
82
102
|
|
|
83
103
|
it "is false if query values differ but key same" do
|
|
84
|
-
uri =
|
|
85
|
-
client_uri =
|
|
104
|
+
uri = "http://app.co/?vendorId=pancakes"
|
|
105
|
+
client_uri = "http://app.co/?vendorId=waffles"
|
|
86
106
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
87
107
|
end
|
|
88
108
|
|
|
89
109
|
it "is false if query values same but key differs" do
|
|
90
|
-
uri =
|
|
91
|
-
client_uri =
|
|
110
|
+
uri = "http://app.co/?foo=pancakes"
|
|
111
|
+
client_uri = "http://app.co/?bar=pancakes"
|
|
92
112
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
93
113
|
end
|
|
94
114
|
|
|
95
115
|
it "is false if query present and match, but unknown queries present" do
|
|
96
|
-
uri =
|
|
97
|
-
client_uri =
|
|
116
|
+
uri = "http://app.co/?vendorId=pancakes&unknown=query"
|
|
117
|
+
client_uri = "http://app.co/?vendorId=waffles"
|
|
98
118
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
|
99
119
|
end
|
|
100
120
|
|
|
101
121
|
it "is true if queries are present and matche" do
|
|
102
|
-
uri =
|
|
103
|
-
client_uri =
|
|
122
|
+
uri = "http://app.co/?vendorId=AJ4L7XXW9&foo=bar"
|
|
123
|
+
client_uri = "http://app.co/?vendorId=AJ4L7XXW9&foo=bar"
|
|
104
124
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
|
105
125
|
end
|
|
106
126
|
|
|
107
127
|
it "is true if queries are present, match and in different order" do
|
|
108
|
-
uri =
|
|
109
|
-
client_uri =
|
|
128
|
+
uri = "http://app.co/?bing=bang&foo=bar"
|
|
129
|
+
client_uri = "http://app.co/?foo=bar&bing=bang"
|
|
110
130
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
|
111
131
|
end
|
|
112
132
|
end
|
|
113
133
|
end
|
|
114
134
|
|
|
115
|
-
describe
|
|
116
|
-
it
|
|
117
|
-
uri = client_uri =
|
|
135
|
+
describe ".valid_for_authorization?" do
|
|
136
|
+
it "is true if valid and matches" do
|
|
137
|
+
uri = client_uri = "http://app.co/aaa"
|
|
118
138
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
119
139
|
|
|
120
|
-
uri = client_uri =
|
|
140
|
+
uri = client_uri = "http://app.co/aaa?b=c"
|
|
121
141
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
122
142
|
end
|
|
123
143
|
|
|
124
|
-
it
|
|
125
|
-
uri = client_uri =
|
|
144
|
+
it "is true if uri includes blank query" do
|
|
145
|
+
uri = client_uri = "http://app.co/aaa?"
|
|
126
146
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
127
147
|
|
|
128
|
-
uri =
|
|
129
|
-
client_uri =
|
|
148
|
+
uri = "http://app.co/aaa?"
|
|
149
|
+
client_uri = "http://app.co/aaa"
|
|
130
150
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
131
151
|
|
|
132
|
-
uri =
|
|
133
|
-
client_uri =
|
|
152
|
+
uri = "http://app.co/aaa"
|
|
153
|
+
client_uri = "http://app.co/aaa?"
|
|
134
154
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
135
155
|
end
|
|
136
156
|
|
|
137
|
-
it
|
|
138
|
-
uri =
|
|
139
|
-
client_uri =
|
|
157
|
+
it "is false if valid and mismatches" do
|
|
158
|
+
uri = "http://app.co/aaa"
|
|
159
|
+
client_uri = "http://app.co/bbb"
|
|
140
160
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
|
|
141
161
|
end
|
|
142
162
|
|
|
143
|
-
it
|
|
144
|
-
uri =
|
|
163
|
+
it "is true if valid and included in array" do
|
|
164
|
+
uri = "http://app.co/aaa"
|
|
145
165
|
client_uri = "http://example.com/bbb\nhttp://app.co/aaa"
|
|
146
166
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
147
167
|
end
|
|
148
168
|
|
|
149
|
-
it
|
|
150
|
-
uri =
|
|
169
|
+
it "is false if valid and not included in array" do
|
|
170
|
+
uri = "http://app.co/aaa"
|
|
151
171
|
client_uri = "http://example.com/bbb\nhttp://app.co/cc"
|
|
152
172
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
|
|
153
173
|
end
|
|
154
174
|
|
|
155
|
-
it
|
|
156
|
-
uri =
|
|
157
|
-
client_uri =
|
|
175
|
+
it "is false if queries does not match" do
|
|
176
|
+
uri = "http://app.co/aaa?pankcakes=abc"
|
|
177
|
+
client_uri = "http://app.co/aaa?waffles=abc"
|
|
158
178
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be false
|
|
159
179
|
end
|
|
160
180
|
|
|
161
|
-
it
|
|
162
|
-
uri =
|
|
163
|
-
client_uri =
|
|
181
|
+
it "calls .matches?" do
|
|
182
|
+
uri = "http://app.co/aaa?pankcakes=abc"
|
|
183
|
+
client_uri = "http://app.co/aaa?waffles=abc"
|
|
164
184
|
expect(URIChecker).to receive(:matches?).with(uri, client_uri).once
|
|
165
185
|
URIChecker.valid_for_authorization?(uri, client_uri)
|
|
166
186
|
end
|
|
167
187
|
|
|
168
|
-
it
|
|
169
|
-
uri =
|
|
170
|
-
client_uri =
|
|
188
|
+
it "calls .valid?" do
|
|
189
|
+
uri = "http://app.co/aaa?pankcakes=abc"
|
|
190
|
+
client_uri = "http://app.co/aaa?waffles=abc"
|
|
171
191
|
expect(URIChecker).to receive(:valid?).with(uri).once
|
|
172
192
|
URIChecker.valid_for_authorization?(uri, client_uri)
|
|
173
193
|
end
|
|
174
194
|
end
|
|
175
195
|
|
|
176
|
-
describe
|
|
177
|
-
it
|
|
178
|
-
expect(URIChecker.query_matches?(
|
|
196
|
+
describe ".query_matches?" do
|
|
197
|
+
it "is true if no queries" do
|
|
198
|
+
expect(URIChecker.query_matches?("", "")).to be_truthy
|
|
179
199
|
expect(URIChecker.query_matches?(nil, nil)).to be_truthy
|
|
180
200
|
end
|
|
181
201
|
|
|
182
|
-
it
|
|
183
|
-
expect(URIChecker.query_matches?(
|
|
202
|
+
it "is true if same query" do
|
|
203
|
+
expect(URIChecker.query_matches?("foo", "foo")).to be_truthy
|
|
184
204
|
end
|
|
185
205
|
|
|
186
|
-
it
|
|
187
|
-
expect(URIChecker.query_matches?(
|
|
206
|
+
it "is false if different query" do
|
|
207
|
+
expect(URIChecker.query_matches?("foo", "bar")).to be_falsey
|
|
188
208
|
end
|
|
189
209
|
|
|
190
|
-
it
|
|
191
|
-
expect(URIChecker.query_matches?(
|
|
210
|
+
it "is true if same queries" do
|
|
211
|
+
expect(URIChecker.query_matches?("foo&bar", "foo&bar")).to be_truthy
|
|
192
212
|
end
|
|
193
213
|
|
|
194
|
-
it
|
|
195
|
-
expect(URIChecker.query_matches?(
|
|
214
|
+
it "is true if same queries, different order" do
|
|
215
|
+
expect(URIChecker.query_matches?("foo&bar", "bar&foo")).to be_truthy
|
|
196
216
|
end
|
|
197
217
|
|
|
198
|
-
it
|
|
199
|
-
expect(URIChecker.query_matches?(
|
|
218
|
+
it "is false if one different query" do
|
|
219
|
+
expect(URIChecker.query_matches?("foo&bang", "foo&bing")).to be_falsey
|
|
200
220
|
end
|
|
201
221
|
|
|
202
|
-
it
|
|
203
|
-
expect(URIChecker.query_matches?(
|
|
222
|
+
it "is true if same query with same value" do
|
|
223
|
+
expect(URIChecker.query_matches?("foo=bar", "foo=bar")).to be_truthy
|
|
204
224
|
end
|
|
205
225
|
|
|
206
|
-
it
|
|
207
|
-
expect(URIChecker.query_matches?(
|
|
226
|
+
it "is true if same queries with same values" do
|
|
227
|
+
expect(URIChecker.query_matches?("foo=bar&bing=bang", "foo=bar&bing=bang")).to be_truthy
|
|
208
228
|
end
|
|
209
229
|
|
|
210
|
-
it
|
|
211
|
-
expect(URIChecker.query_matches?(
|
|
230
|
+
it "is true if same queries with same values, different order" do
|
|
231
|
+
expect(URIChecker.query_matches?("foo=bar&bing=bang", "bing=bang&foo=bar")).to be_truthy
|
|
212
232
|
end
|
|
213
233
|
|
|
214
|
-
it
|
|
215
|
-
expect(URIChecker.query_matches?(
|
|
234
|
+
it "is false if same query with different value" do
|
|
235
|
+
expect(URIChecker.query_matches?("foo=bar", "foo=bang")).to be_falsey
|
|
216
236
|
end
|
|
217
237
|
|
|
218
|
-
it
|
|
219
|
-
expect(URIChecker.query_matches?(
|
|
238
|
+
it "is false if some queries missing" do
|
|
239
|
+
expect(URIChecker.query_matches?("foo=bar", "foo=bar&bing=bang")).to be_falsey
|
|
220
240
|
end
|
|
221
241
|
|
|
222
|
-
it
|
|
223
|
-
expect(URIChecker.query_matches?(
|
|
242
|
+
it "is false if some queries different value" do
|
|
243
|
+
expect(URIChecker.query_matches?("foo=bar&bing=bang", "foo=bar&bing=banana")).to be_falsey
|
|
224
244
|
end
|
|
225
245
|
end
|
|
226
246
|
end
|