doorkeeper 5.0.0 → 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 +5 -5
- data/.hound.yml +2 -1
- data/.rubocop.yml +37 -4
- data/.travis.yml +16 -21
- data/Appraisals +29 -7
- data/Dangerfile +67 -0
- data/Gemfile +19 -5
- data/NEWS.md +107 -10
- data/README.md +75 -470
- data/Rakefile +10 -8
- data/app/controllers/doorkeeper/application_controller.rb +3 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -13
- data/app/controllers/doorkeeper/applications_controller.rb +21 -7
- data/app/controllers/doorkeeper/authorizations_controller.rb +3 -3
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -0
- data/app/controllers/doorkeeper/token_info_controller.rb +4 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +13 -11
- data/app/helpers/doorkeeper/dashboard_helper.rb +3 -1
- data/app/validators/redirect_uri_validator.rb +7 -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 +28 -24
- 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 +197 -76
- data/lib/doorkeeper/engine.rb +3 -1
- data/lib/doorkeeper/errors.rb +17 -0
- data/lib/doorkeeper/grape/authorization_decorator.rb +6 -4
- data/lib/doorkeeper/grape/helpers.rb +5 -3
- data/lib/doorkeeper/helpers/controller.rb +5 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +25 -6
- data/lib/doorkeeper/models/access_token_mixin.rb +68 -22
- data/lib/doorkeeper/models/application_mixin.rb +45 -1
- data/lib/doorkeeper/models/concerns/accessible.rb +2 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +6 -2
- data/lib/doorkeeper/models/concerns/orderable.rb +2 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +3 -6
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +4 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +7 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +4 -2
- data/lib/doorkeeper/oauth/authorization/context.rb +2 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +14 -7
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +3 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +8 -4
- data/lib/doorkeeper/oauth/base_request.rb +2 -0
- data/lib/doorkeeper/oauth/base_response.rb +2 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +2 -0
- data/lib/doorkeeper/oauth/client.rb +3 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +7 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +3 -1
- data/lib/doorkeeper/oauth/code_request.rb +2 -0
- data/lib/doorkeeper/oauth/code_response.rb +4 -2
- data/lib/doorkeeper/oauth/error.rb +2 -0
- data/lib/doorkeeper/oauth/error_response.rb +20 -6
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +10 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +25 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +15 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +42 -3
- data/lib/doorkeeper/oauth/invalid_token_response.rb +22 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +13 -5
- data/lib/doorkeeper/oauth/refresh_token_request.rb +15 -4
- data/lib/doorkeeper/oauth/scopes.rb +7 -3
- data/lib/doorkeeper/oauth/token.rb +4 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +76 -8
- data/lib/doorkeeper/oauth/token_request.rb +2 -0
- data/lib/doorkeeper/oauth/token_response.rb +11 -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 +26 -7
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
- data/lib/doorkeeper/orm/active_record.rb +8 -6
- data/lib/doorkeeper/rails/helpers.rb +5 -1
- data/lib/doorkeeper/rails/routes/mapper.rb +2 -0
- data/lib/doorkeeper/rails/routes/mapping.rb +9 -7
- data/lib/doorkeeper/rails/routes.rb +19 -12
- data/lib/doorkeeper/rake/db.rake +17 -17
- data/lib/doorkeeper/rake.rb +1 -1
- data/lib/doorkeeper/request/authorization_code.rb +2 -0
- data/lib/doorkeeper/request/client_credentials.rb +2 -0
- data/lib/doorkeeper/request/code.rb +2 -0
- data/lib/doorkeeper/request/password.rb +2 -0
- data/lib/doorkeeper/request/refresh_token.rb +2 -0
- data/lib/doorkeeper/request/strategy.rb +2 -0
- data/lib/doorkeeper/request/token.rb +2 -0
- data/lib/doorkeeper/request.rb +3 -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/server.rb +2 -0
- data/lib/doorkeeper/stale_records_cleaner.rb +20 -0
- data/lib/doorkeeper/validations.rb +2 -0
- data/lib/doorkeeper/version.rb +4 -2
- data/lib/doorkeeper.rb +69 -59
- 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 +138 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +17 -10
- 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 +76 -78
- data/spec/controllers/authorizations_controller_spec.rb +189 -142
- data/spec/controllers/protected_resources_controller_spec.rb +111 -67
- data/spec/controllers/token_info_controller_spec.rb +14 -12
- data/spec/controllers/tokens_controller_spec.rb +170 -112
- 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 +3 -1
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/controllers/home_controller.rb +6 -5
- 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 +26 -2
- data/spec/dummy/config/boot.rb +2 -4
- data/spec/dummy/config/environment.rb +1 -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 +4 -2
- data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +7 -3
- 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 +20 -13
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +1 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/script/rails +7 -4
- data/spec/factories.rb +11 -9
- 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 +19 -14
- 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 -1
- data/spec/generators/views_generator_spec.rb +14 -12
- data/spec/grape/grape_integration_spec.rb +35 -33
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
- data/spec/lib/config_spec.rb +290 -104
- data/spec/lib/doorkeeper_spec.rb +8 -6
- 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 +43 -17
- data/spec/lib/oauth/base_request_spec.rb +24 -12
- data/spec/lib/oauth/base_response_spec.rb +3 -1
- data/spec/lib/oauth/client/credentials_spec.rb +26 -24
- data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -20
- data/spec/lib/oauth/client_credentials/validation_spec.rb +21 -15
- data/spec/lib/oauth/client_credentials_integration_spec.rb +8 -6
- 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 +10 -8
- 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 +124 -93
- data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +95 -34
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
- data/spec/lib/oauth/refresh_token_request_spec.rb +46 -39
- data/spec/lib/oauth/scopes_spec.rb +63 -61
- data/spec/lib/oauth/token_request_spec.rb +80 -25
- data/spec/lib/oauth/token_response_spec.rb +40 -38
- data/spec/lib/oauth/token_spec.rb +64 -45
- 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 +20 -18
- data/spec/lib/{orm/active_record/stale_records_cleaner_spec.rb → stale_records_cleaner_spec.rb} +28 -18
- data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
- data/spec/models/doorkeeper/access_token_spec.rb +212 -83
- data/spec/models/doorkeeper/application_spec.rb +146 -49
- data/spec/requests/applications/applications_request_spec.rb +100 -68
- data/spec/requests/applications/authorized_applications_spec.rb +20 -18
- data/spec/requests/endpoints/authorization_spec.rb +27 -25
- data/spec/requests/endpoints/token_spec.rb +38 -36
- data/spec/requests/flows/authorization_code_errors_spec.rb +27 -25
- data/spec/requests/flows/authorization_code_spec.rb +260 -158
- data/spec/requests/flows/client_credentials_spec.rb +54 -52
- data/spec/requests/flows/implicit_grant_errors_spec.rb +11 -9
- data/spec/requests/flows/implicit_grant_spec.rb +27 -25
- data/spec/requests/flows/password_spec.rb +64 -56
- data/spec/requests/flows/refresh_token_spec.rb +91 -32
- data/spec/requests/flows/revoke_token_spec.rb +49 -63
- 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 +37 -35
- 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 +5 -2
- 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 +11 -5
- data/spec/support/helpers/request_spec_helper.rb +5 -3
- data/spec/support/helpers/url_helper.rb +20 -18
- 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 +68 -10
- 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 +76 -47
- data/spec/version/version_spec.rb +7 -5
- metadata +70 -21
- data/gemfiles/rails_4_2.gemfile +0 -13
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -10
|
@@ -1,17 +1,19 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper
|
|
4
6
|
module OAuth
|
|
5
7
|
describe CodeResponse do
|
|
6
|
-
describe
|
|
7
|
-
context
|
|
8
|
+
describe ".redirect_uri" do
|
|
9
|
+
context "when generating the redirect URI for an implicit grant" do
|
|
8
10
|
let :pre_auth do
|
|
9
11
|
double(
|
|
10
12
|
:pre_auth,
|
|
11
13
|
client: double(:application, id: 1),
|
|
12
|
-
redirect_uri:
|
|
14
|
+
redirect_uri: "http://tst.com/cb",
|
|
13
15
|
state: nil,
|
|
14
|
-
scopes: Scopes.from_string(
|
|
16
|
+
scopes: Scopes.from_string("public")
|
|
15
17
|
)
|
|
16
18
|
end
|
|
17
19
|
|
|
@@ -24,8 +26,8 @@ module Doorkeeper
|
|
|
24
26
|
|
|
25
27
|
subject { CodeResponse.new(pre_auth, auth, response_on_fragment: true).redirect_uri }
|
|
26
28
|
|
|
27
|
-
it
|
|
28
|
-
expect(subject).to include(
|
|
29
|
+
it "includes the remaining TTL of the token relative to the time the token was generated" do
|
|
30
|
+
expect(subject).to include("expires_in=3600")
|
|
29
31
|
end
|
|
30
32
|
end
|
|
31
33
|
end
|
|
@@ -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,215 +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"
|
|
138
|
+
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
139
|
+
|
|
140
|
+
uri = client_uri = "http://app.co/aaa?b=c"
|
|
141
|
+
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "is true if uri includes blank query" do
|
|
145
|
+
uri = client_uri = "http://app.co/aaa?"
|
|
146
|
+
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
147
|
+
|
|
148
|
+
uri = "http://app.co/aaa?"
|
|
149
|
+
client_uri = "http://app.co/aaa"
|
|
150
|
+
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
151
|
+
|
|
152
|
+
uri = "http://app.co/aaa"
|
|
153
|
+
client_uri = "http://app.co/aaa?"
|
|
118
154
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
119
155
|
end
|
|
120
156
|
|
|
121
|
-
it
|
|
122
|
-
uri =
|
|
123
|
-
client_uri =
|
|
157
|
+
it "is false if valid and mismatches" do
|
|
158
|
+
uri = "http://app.co/aaa"
|
|
159
|
+
client_uri = "http://app.co/bbb"
|
|
124
160
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
|
|
125
161
|
end
|
|
126
162
|
|
|
127
|
-
it
|
|
128
|
-
uri =
|
|
163
|
+
it "is true if valid and included in array" do
|
|
164
|
+
uri = "http://app.co/aaa"
|
|
129
165
|
client_uri = "http://example.com/bbb\nhttp://app.co/aaa"
|
|
130
166
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
|
131
167
|
end
|
|
132
168
|
|
|
133
|
-
it
|
|
134
|
-
uri =
|
|
169
|
+
it "is false if valid and not included in array" do
|
|
170
|
+
uri = "http://app.co/aaa"
|
|
135
171
|
client_uri = "http://example.com/bbb\nhttp://app.co/cc"
|
|
136
172
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
|
|
137
173
|
end
|
|
138
174
|
|
|
139
|
-
it
|
|
140
|
-
uri =
|
|
141
|
-
|
|
142
|
-
end
|
|
143
|
-
|
|
144
|
-
it 'is false if invalid' do
|
|
145
|
-
uri = 'http://app.co/aaa?pankcakes=abc'
|
|
146
|
-
client_uri = 'http://app.co/aaa?waffles=abc'
|
|
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"
|
|
147
178
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be false
|
|
148
179
|
end
|
|
149
180
|
|
|
150
|
-
it
|
|
151
|
-
uri =
|
|
152
|
-
client_uri =
|
|
181
|
+
it "calls .matches?" do
|
|
182
|
+
uri = "http://app.co/aaa?pankcakes=abc"
|
|
183
|
+
client_uri = "http://app.co/aaa?waffles=abc"
|
|
153
184
|
expect(URIChecker).to receive(:matches?).with(uri, client_uri).once
|
|
154
185
|
URIChecker.valid_for_authorization?(uri, client_uri)
|
|
155
186
|
end
|
|
156
187
|
|
|
157
|
-
it
|
|
158
|
-
uri =
|
|
159
|
-
client_uri =
|
|
188
|
+
it "calls .valid?" do
|
|
189
|
+
uri = "http://app.co/aaa?pankcakes=abc"
|
|
190
|
+
client_uri = "http://app.co/aaa?waffles=abc"
|
|
160
191
|
expect(URIChecker).to receive(:valid?).with(uri).once
|
|
161
192
|
URIChecker.valid_for_authorization?(uri, client_uri)
|
|
162
193
|
end
|
|
163
194
|
end
|
|
164
195
|
|
|
165
|
-
describe
|
|
166
|
-
it
|
|
167
|
-
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
|
|
168
199
|
expect(URIChecker.query_matches?(nil, nil)).to be_truthy
|
|
169
200
|
end
|
|
170
201
|
|
|
171
|
-
it
|
|
172
|
-
expect(URIChecker.query_matches?(
|
|
202
|
+
it "is true if same query" do
|
|
203
|
+
expect(URIChecker.query_matches?("foo", "foo")).to be_truthy
|
|
173
204
|
end
|
|
174
205
|
|
|
175
|
-
it
|
|
176
|
-
expect(URIChecker.query_matches?(
|
|
206
|
+
it "is false if different query" do
|
|
207
|
+
expect(URIChecker.query_matches?("foo", "bar")).to be_falsey
|
|
177
208
|
end
|
|
178
209
|
|
|
179
|
-
it
|
|
180
|
-
expect(URIChecker.query_matches?(
|
|
210
|
+
it "is true if same queries" do
|
|
211
|
+
expect(URIChecker.query_matches?("foo&bar", "foo&bar")).to be_truthy
|
|
181
212
|
end
|
|
182
213
|
|
|
183
|
-
it
|
|
184
|
-
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
|
|
185
216
|
end
|
|
186
217
|
|
|
187
|
-
it
|
|
188
|
-
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
|
|
189
220
|
end
|
|
190
221
|
|
|
191
|
-
it
|
|
192
|
-
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
|
|
193
224
|
end
|
|
194
225
|
|
|
195
|
-
it
|
|
196
|
-
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
|
|
197
228
|
end
|
|
198
229
|
|
|
199
|
-
it
|
|
200
|
-
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
|
|
201
232
|
end
|
|
202
233
|
|
|
203
|
-
it
|
|
204
|
-
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
|
|
205
236
|
end
|
|
206
237
|
|
|
207
|
-
it
|
|
208
|
-
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
|
|
209
240
|
end
|
|
210
241
|
|
|
211
|
-
it
|
|
212
|
-
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
|
|
213
244
|
end
|
|
214
245
|
end
|
|
215
246
|
end
|