doorkeeper 5.1.0.rc2 → 5.1.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.hound.yml +2 -1
- data/.rubocop.yml +37 -4
- data/.travis.yml +4 -27
- data/Appraisals +8 -12
- data/Gemfile +6 -2
- data/NEWS.md +16 -0
- data/README.md +11 -2
- 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 +17 -5
- data/app/controllers/doorkeeper/token_info_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +7 -7
- 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/bin/console +5 -4
- data/config/locales/en.yml +1 -0
- data/doorkeeper.gemspec +24 -22
- data/gemfiles/rails_5_0.gemfile +2 -1
- data/gemfiles/rails_5_1.gemfile +2 -1
- data/gemfiles/rails_5_2.gemfile +2 -1
- data/gemfiles/rails_6_0.gemfile +1 -0
- data/gemfiles/rails_master.gemfile +1 -0
- data/lib/doorkeeper.rb +68 -66
- data/lib/doorkeeper/config.rb +53 -90
- data/lib/doorkeeper/config/option.rb +64 -0
- 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 +1 -1
- data/lib/doorkeeper/models/access_grant_mixin.rb +4 -2
- data/lib/doorkeeper/models/access_token_mixin.rb +10 -10
- data/lib/doorkeeper/models/application_mixin.rb +1 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +1 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
- data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +2 -0
- data/lib/doorkeeper/oauth.rb +5 -5
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/token.rb +9 -6
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +5 -3
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +5 -5
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +6 -2
- data/lib/doorkeeper/oauth/invalid_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/pre_authorization.rb +4 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +1 -1
- data/lib/doorkeeper/oauth/scopes.rb +5 -3
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +4 -4
- data/lib/doorkeeper/oauth/token_response.rb +9 -9
- data/lib/doorkeeper/orm/active_record.rb +6 -6
- data/lib/doorkeeper/orm/active_record/access_grant.rb +5 -12
- data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
- data/lib/doorkeeper/orm/active_record/application.rb +6 -5
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
- data/lib/doorkeeper/rails/helpers.rb +1 -1
- data/lib/doorkeeper/rails/routes.rb +11 -11
- data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
- data/lib/doorkeeper/rake.rb +1 -1
- data/lib/doorkeeper/rake/db.rake +13 -13
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/secret_storing/base.rb +7 -6
- data/lib/doorkeeper/secret_storing/bcrypt.rb +4 -3
- data/lib/doorkeeper/secret_storing/plain.rb +4 -4
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +3 -2
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +2 -2
- 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 +30 -5
- 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 +10 -10
- data/spec/controllers/applications_controller_spec.rb +54 -52
- data/spec/controllers/authorizations_controller_spec.rb +136 -142
- data/spec/controllers/protected_resources_controller_spec.rb +78 -76
- data/spec/controllers/token_info_controller_spec.rb +13 -11
- data/spec/controllers/tokens_controller_spec.rb +109 -94
- data/spec/dummy/Rakefile +3 -1
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- 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.ru +3 -1
- data/spec/dummy/config/application.rb +13 -0
- 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/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 +5 -3
- 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 +137 -136
- data/spec/lib/doorkeeper_spec.rb +3 -1
- data/spec/lib/models/expirable_spec.rb +12 -10
- data/spec/lib/models/reusable_spec.rb +6 -6
- data/spec/lib/models/revocable_spec.rb +8 -6
- data/spec/lib/models/scopes_spec.rb +19 -17
- data/spec/lib/models/secret_storable_spec.rb +71 -49
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
- data/spec/lib/oauth/authorization_code_request_spec.rb +18 -12
- 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 +13 -11
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
- data/spec/lib/oauth/client_credentials/validation_spec.rb +17 -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 +14 -12
- 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 +35 -33
- data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +103 -101
- data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +52 -34
- data/spec/lib/oauth/pre_authorization_spec.rb +64 -62
- 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 +66 -26
- data/spec/lib/oauth/token_response_spec.rb +39 -37
- data/spec/lib/oauth/token_spec.rb +51 -49
- data/spec/lib/request/strategy_spec.rb +3 -1
- data/spec/lib/secret_storing/base_spec.rb +23 -23
- data/spec/lib/secret_storing/bcrypt_spec.rb +18 -18
- data/spec/lib/secret_storing/plain_spec.rb +17 -17
- data/spec/lib/secret_storing/sha256_hash_spec.rb +16 -16
- 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 +30 -26
- data/spec/models/doorkeeper/access_token_spec.rb +97 -95
- data/spec/models/doorkeeper/application_spec.rb +98 -57
- 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 +161 -159
- data/spec/requests/flows/client_credentials_spec.rb +53 -51
- 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 +56 -54
- data/spec/requests/flows/refresh_token_spec.rb +45 -43
- data/spec/requests/flows/revoke_token_spec.rb +29 -27
- 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 +67 -65
- data/spec/routing/default_routes_spec.rb +22 -20
- data/spec/routing/scoped_routes_spec.rb +20 -18
- data/spec/spec_helper.rb +14 -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 +3 -3
- 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 +12 -16
- data/gemfiles/rails_4_2.gemfile +0 -17
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
- data/spec/support/ruby_2_6_rails_4_2_patch.rb +0 -14
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
3
|
+
require "coveralls"
|
4
|
+
|
5
|
+
Coveralls.wear!("rails") do
|
6
|
+
add_filter("/spec/")
|
7
|
+
add_filter("/lib/generators/doorkeeper/templates/")
|
6
8
|
end
|
7
9
|
|
8
|
-
ENV[
|
10
|
+
ENV["RAILS_ENV"] ||= "test"
|
9
11
|
|
10
12
|
$LOAD_PATH.unshift File.dirname(__FILE__)
|
11
13
|
|
@@ -13,15 +15,15 @@ require "#{File.dirname(__FILE__)}/support/doorkeeper_rspec.rb"
|
|
13
15
|
|
14
16
|
DOORKEEPER_ORM = Doorkeeper::RSpec.detect_orm
|
15
17
|
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
18
|
+
require "dummy/config/environment"
|
19
|
+
require "rspec/rails"
|
20
|
+
require "capybara/rspec"
|
21
|
+
require "database_cleaner"
|
22
|
+
require "generator_spec/test_case"
|
21
23
|
|
22
24
|
# Load JRuby SQLite3 if in that platform
|
23
25
|
if defined? JRUBY_VERSION
|
24
|
-
require
|
26
|
+
require "jdbc/sqlite3"
|
25
27
|
Jdbc::SQLite3.load_driver
|
26
28
|
end
|
27
29
|
|
@@ -29,7 +31,6 @@ Doorkeeper::RSpec.print_configuration_info
|
|
29
31
|
|
30
32
|
# Remove after dropping support of Rails 4.2
|
31
33
|
require "#{File.dirname(__FILE__)}/support/http_method_shim"
|
32
|
-
require "#{File.dirname(__FILE__)}/support/ruby_2_6_rails_4_2_patch"
|
33
34
|
|
34
35
|
require "support/orm/#{DOORKEEPER_ORM}"
|
35
36
|
|
@@ -52,5 +53,5 @@ RSpec.configure do |config|
|
|
52
53
|
DatabaseCleaner.clean
|
53
54
|
end
|
54
55
|
|
55
|
-
config.order =
|
56
|
+
config.order = "random"
|
56
57
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Doorkeeper
|
2
4
|
class RSpec
|
3
5
|
# Print's useful information about env: Ruby / Rails versions,
|
@@ -13,7 +15,7 @@ module Doorkeeper
|
|
13
15
|
|
14
16
|
# Tries to find ORM from the Gemfile used to run test suite
|
15
17
|
def self.detect_orm
|
16
|
-
orm = (ENV[
|
18
|
+
orm = (ENV["BUNDLE_GEMFILE"] || "").match(/Gemfile\.(.+)\.rb/)
|
17
19
|
(orm && orm[1] || :active_record).to_sym
|
18
20
|
end
|
19
21
|
end
|
@@ -1,8 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AccessTokenRequestHelper
|
2
4
|
def client_is_authorized(client, resource_owner, access_token_attributes = {})
|
3
5
|
attributes = {
|
4
6
|
application: client,
|
5
|
-
resource_owner_id: resource_owner.id
|
7
|
+
resource_owner_id: resource_owner.id,
|
6
8
|
}.merge(access_token_attributes)
|
7
9
|
FactoryBot.create(:access_token, attributes)
|
8
10
|
end
|
@@ -1,11 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module AuthorizationRequestHelper
|
2
4
|
def resource_owner_is_authenticated(resource_owner = nil)
|
3
|
-
resource_owner ||= User.create!(name:
|
5
|
+
resource_owner ||= User.create!(name: "Joe", password: "sekret")
|
4
6
|
Doorkeeper.configuration.instance_variable_set(:@authenticate_resource_owner, proc { resource_owner })
|
5
7
|
end
|
6
8
|
|
7
9
|
def resource_owner_is_not_authenticated
|
8
|
-
Doorkeeper.configuration.instance_variable_set(:@authenticate_resource_owner, proc { redirect_to(
|
10
|
+
Doorkeeper.configuration.instance_variable_set(:@authenticate_resource_owner, proc { redirect_to("/sign_in") })
|
9
11
|
end
|
10
12
|
|
11
13
|
def default_scopes_exist(*scopes)
|
@@ -1,10 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module ModelHelper
|
2
4
|
def client_exists(client_attributes = {})
|
3
5
|
@client = FactoryBot.create(:application, client_attributes)
|
4
6
|
end
|
5
7
|
|
6
8
|
def create_resource_owner
|
7
|
-
@resource_owner = User.create!(name:
|
9
|
+
@resource_owner = User.create!(name: "Joe", password: "sekret")
|
8
10
|
end
|
9
11
|
|
10
12
|
def authorization_code_exists(options = {})
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RequestSpecHelper
|
2
4
|
def i_am_logged_in
|
3
5
|
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) {})
|
@@ -48,7 +50,7 @@ module RequestSpecHelper
|
|
48
50
|
end
|
49
51
|
|
50
52
|
def with_access_token_header(token)
|
51
|
-
with_header
|
53
|
+
with_header "Authorization", "Bearer #{token}"
|
52
54
|
end
|
53
55
|
|
54
56
|
def with_header(header, value)
|
@@ -72,8 +74,8 @@ module RequestSpecHelper
|
|
72
74
|
end
|
73
75
|
|
74
76
|
def sign_in
|
75
|
-
visit
|
76
|
-
click_on
|
77
|
+
visit "/"
|
78
|
+
click_on "Sign in"
|
77
79
|
end
|
78
80
|
|
79
81
|
def create_access_token(authorization_code, client, code_verifier = nil)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module UrlHelper
|
2
4
|
def token_endpoint_url(options = {})
|
3
5
|
parameters = {
|
@@ -5,9 +7,9 @@ module UrlHelper
|
|
5
7
|
client_id: options[:client_id] || options[:client].try(:uid),
|
6
8
|
client_secret: options[:client_secret] || options[:client].try(:secret),
|
7
9
|
redirect_uri: options[:redirect_uri] || options[:client].try(:redirect_uri),
|
8
|
-
grant_type: options[:grant_type] ||
|
10
|
+
grant_type: options[:grant_type] || "authorization_code",
|
9
11
|
code_verifier: options[:code_verifier],
|
10
|
-
code_challenge_method: options[:code_challenge_method]
|
12
|
+
code_challenge_method: options[:code_challenge_method],
|
11
13
|
}.reject { |_, v| v.blank? }
|
12
14
|
"/oauth/token?#{build_query(parameters)}"
|
13
15
|
end
|
@@ -20,7 +22,7 @@ module UrlHelper
|
|
20
22
|
username: options[:resource_owner_username] || options[:resource_owner].try(:name),
|
21
23
|
password: options[:resource_owner_password] || options[:resource_owner].try(:password),
|
22
24
|
scope: options[:scope],
|
23
|
-
grant_type:
|
25
|
+
grant_type: "password",
|
24
26
|
}
|
25
27
|
"/oauth/token?#{build_query(parameters)}"
|
26
28
|
end
|
@@ -29,11 +31,11 @@ module UrlHelper
|
|
29
31
|
parameters = {
|
30
32
|
client_id: options[:client_id] || options[:client].try(:uid),
|
31
33
|
redirect_uri: options[:redirect_uri] || options[:client].try(:redirect_uri),
|
32
|
-
response_type: options[:response_type] ||
|
34
|
+
response_type: options[:response_type] || "code",
|
33
35
|
scope: options[:scope],
|
34
36
|
state: options[:state],
|
35
37
|
code_challenge: options[:code_challenge],
|
36
|
-
code_challenge_method: options[:code_challenge_method]
|
38
|
+
code_challenge_method: options[:code_challenge_method],
|
37
39
|
}.reject { |_, v| v.blank? }
|
38
40
|
"/oauth/authorize?#{build_query(parameters)}"
|
39
41
|
end
|
@@ -43,13 +45,13 @@ module UrlHelper
|
|
43
45
|
refresh_token: options[:refresh_token],
|
44
46
|
client_id: options[:client_id] || options[:client].try(:uid),
|
45
47
|
client_secret: options[:client_secret] || options[:client].try(:secret),
|
46
|
-
grant_type: options[:grant_type] ||
|
48
|
+
grant_type: options[:grant_type] || "refresh_token",
|
47
49
|
}
|
48
50
|
"/oauth/token?#{build_query(parameters)}"
|
49
51
|
end
|
50
52
|
|
51
53
|
def revocation_token_endpoint_url
|
52
|
-
|
54
|
+
"/oauth/revoke"
|
53
55
|
end
|
54
56
|
|
55
57
|
def build_query(hash)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# Rails 5 deprecates calling HTTP action methods with positional arguments
|
2
4
|
# in favor of keyword arguments. However, the keyword argument form is only
|
3
5
|
# supported in Rails 5+. Since we support back to 4, we need some sort of shim
|
@@ -17,18 +19,11 @@ module RoutingHTTPMethodShim
|
|
17
19
|
end
|
18
20
|
|
19
21
|
module ControllerHTTPMethodShim
|
20
|
-
def process(action, http_method =
|
22
|
+
def process(action, http_method = "GET", **args)
|
21
23
|
if (as = args.delete(:as))
|
22
|
-
@request.headers[
|
24
|
+
@request.headers["Content-Type"] = Mime[as].to_s
|
23
25
|
end
|
24
26
|
|
25
27
|
super(action, http_method, args[:params], args[:session], args[:flash])
|
26
28
|
end
|
27
29
|
end
|
28
|
-
|
29
|
-
if ::Rails::VERSION::MAJOR < 5
|
30
|
-
RSpec.configure do |config|
|
31
|
-
config.include ControllerHTTPMethodShim, type: :controller
|
32
|
-
config.include RoutingHTTPMethodShim, type: :request
|
33
|
-
end
|
34
|
-
end
|
@@ -1,5 +1,7 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_context "valid token", token: :valid do
|
4
|
+
let(:token_string) { "1A2B3C4D" }
|
3
5
|
|
4
6
|
let :token do
|
5
7
|
double(Doorkeeper::AccessToken,
|
@@ -14,8 +16,8 @@ shared_context 'valid token', token: :valid do
|
|
14
16
|
end
|
15
17
|
end
|
16
18
|
|
17
|
-
shared_context
|
18
|
-
let(:token_string) {
|
19
|
+
shared_context "invalid token", token: :invalid do
|
20
|
+
let(:token_string) { "1A2B3C4D" }
|
19
21
|
|
20
22
|
let :token do
|
21
23
|
double(Doorkeeper::AccessToken,
|
@@ -31,22 +33,22 @@ shared_context 'invalid token', token: :invalid do
|
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
|
-
shared_context
|
36
|
+
shared_context "authenticated resource owner" do
|
35
37
|
before do
|
36
38
|
user = double(:resource, id: 1)
|
37
39
|
allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { user } }
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
shared_context
|
43
|
+
shared_context "not authenticated resource owner" do
|
42
44
|
before do
|
43
|
-
allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { redirect_to
|
45
|
+
allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { redirect_to "/" } }
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
47
|
-
shared_context
|
49
|
+
shared_context "valid authorization request" do
|
48
50
|
let :authorization do
|
49
|
-
double(:authorization, valid?: true, authorize: true, success_redirect_uri:
|
51
|
+
double(:authorization, valid?: true, authorize: true, success_redirect_uri: "http://something.com/cb?code=token")
|
50
52
|
end
|
51
53
|
|
52
54
|
before do
|
@@ -54,7 +56,7 @@ shared_context 'valid authorization request' do
|
|
54
56
|
end
|
55
57
|
end
|
56
58
|
|
57
|
-
shared_context
|
59
|
+
shared_context "invalid authorization request" do
|
58
60
|
let :authorization do
|
59
61
|
double(:authorization, valid?: false, authorize: false, redirect_on_error?: false)
|
60
62
|
end
|
@@ -64,9 +66,9 @@ shared_context 'invalid authorization request' do
|
|
64
66
|
end
|
65
67
|
end
|
66
68
|
|
67
|
-
shared_context
|
69
|
+
shared_context "expired token", token: :expired do
|
68
70
|
let :token_string do
|
69
|
-
|
71
|
+
"1A2B3C4DEXP"
|
70
72
|
end
|
71
73
|
|
72
74
|
let :token do
|
@@ -83,9 +85,9 @@ shared_context 'expired token', token: :expired do
|
|
83
85
|
end
|
84
86
|
end
|
85
87
|
|
86
|
-
shared_context
|
88
|
+
shared_context "revoked token", token: :revoked do
|
87
89
|
let :token_string do
|
88
|
-
|
90
|
+
"1A2B3C4DREV"
|
89
91
|
end
|
90
92
|
|
91
93
|
let :token do
|
@@ -102,9 +104,9 @@ shared_context 'revoked token', token: :revoked do
|
|
102
104
|
end
|
103
105
|
end
|
104
106
|
|
105
|
-
shared_context
|
107
|
+
shared_context "forbidden token", token: :forbidden do
|
106
108
|
let :token_string do
|
107
|
-
|
109
|
+
"1A2B3C4DFORB"
|
108
110
|
end
|
109
111
|
|
110
112
|
let :token do
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
shared_context
|
3
|
+
shared_context "with token hashing enabled" do
|
4
4
|
let(:hashed_or_plain_token_func) do
|
5
5
|
Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
|
6
6
|
end
|
@@ -12,7 +12,7 @@ shared_context 'with token hashing enabled' do
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
shared_context
|
15
|
+
shared_context "with token hashing and fallback lookup enabled" do
|
16
16
|
let(:hashed_or_plain_token_func) do
|
17
17
|
Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
|
18
18
|
end
|
@@ -24,7 +24,7 @@ shared_context 'with token hashing and fallback lookup enabled' do
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
shared_context
|
27
|
+
shared_context "with application hashing enabled" do
|
28
28
|
let(:hashed_or_plain_token_func) do
|
29
29
|
Doorkeeper::SecretStoring::Sha256Hash.method(:transform_secret)
|
30
30
|
end
|
@@ -1,46 +1,48 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
shared_examples "an accessible token" do
|
2
4
|
describe :accessible? do
|
3
|
-
it
|
5
|
+
it "is accessible if token is not expired" do
|
4
6
|
allow(subject).to receive(:expired?).and_return(false)
|
5
7
|
should be_accessible
|
6
8
|
end
|
7
9
|
|
8
|
-
it
|
10
|
+
it "is not accessible if token is expired" do
|
9
11
|
allow(subject).to receive(:expired?).and_return(true)
|
10
12
|
should_not be_accessible
|
11
13
|
end
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
|
-
shared_examples
|
17
|
+
shared_examples "a revocable token" do
|
16
18
|
describe :accessible? do
|
17
19
|
before { subject.save! }
|
18
20
|
|
19
|
-
it
|
21
|
+
it "is accessible if token is not revoked" do
|
20
22
|
expect(subject).to be_accessible
|
21
23
|
end
|
22
24
|
|
23
|
-
it
|
25
|
+
it "is not accessible if token is revoked" do
|
24
26
|
subject.revoke
|
25
27
|
expect(subject).not_to be_accessible
|
26
28
|
end
|
27
29
|
end
|
28
30
|
end
|
29
31
|
|
30
|
-
shared_examples
|
32
|
+
shared_examples "a unique token" do
|
31
33
|
describe :token do
|
32
|
-
it
|
34
|
+
it "is generated before validation" do
|
33
35
|
expect { subject.valid? }.to change { subject.token }.from(nil)
|
34
36
|
end
|
35
37
|
|
36
|
-
it
|
38
|
+
it "is not valid if token exists" do
|
37
39
|
token1 = FactoryBot.create factory_name
|
38
40
|
token2 = FactoryBot.create factory_name
|
39
41
|
token2.token = token1.token
|
40
42
|
expect(token2).not_to be_valid
|
41
43
|
end
|
42
44
|
|
43
|
-
it
|
45
|
+
it "expects database to throw an error when tokens are the same" do
|
44
46
|
token1 = FactoryBot.create factory_name
|
45
47
|
token2 = FactoryBot.create factory_name
|
46
48
|
token2.token = token1.token
|
@@ -1,12 +1,14 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
describe RedirectUriValidator do
|
4
6
|
subject do
|
5
7
|
FactoryBot.create(:application)
|
6
8
|
end
|
7
9
|
|
8
|
-
it
|
9
|
-
subject.redirect_uri =
|
10
|
+
it "is valid when the uri is a uri" do
|
11
|
+
subject.redirect_uri = "https://example.com/callback"
|
10
12
|
expect(subject).to be_valid
|
11
13
|
end
|
12
14
|
|
@@ -15,115 +17,142 @@ describe RedirectUriValidator do
|
|
15
17
|
# the system browser.
|
16
18
|
#
|
17
19
|
# @see https://www.oauth.com/oauth2-servers/redirect-uris/redirect-uris-native-apps/
|
18
|
-
it
|
19
|
-
subject.redirect_uri =
|
20
|
+
it "is valid when the uri is custom native URI" do
|
21
|
+
subject.redirect_uri = "myapp://callback"
|
20
22
|
expect(subject).to be_valid
|
21
23
|
end
|
22
24
|
|
23
|
-
it
|
24
|
-
subject.redirect_uri =
|
25
|
+
it "is valid when the uri has a query parameter" do
|
26
|
+
subject.redirect_uri = "https://example.com/abcd?xyz=123"
|
25
27
|
expect(subject).to be_valid
|
26
28
|
end
|
27
29
|
|
28
|
-
it
|
29
|
-
subject.redirect_uri =
|
30
|
+
it "accepts native redirect uri" do
|
31
|
+
subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
|
30
32
|
expect(subject).to be_valid
|
31
33
|
end
|
32
34
|
|
33
|
-
it
|
35
|
+
it "rejects if test uri is disabled" do
|
34
36
|
allow(RedirectUriValidator).to receive(:native_redirect_uri).and_return(nil)
|
35
|
-
subject.redirect_uri =
|
37
|
+
subject.redirect_uri = "urn:some:test"
|
36
38
|
expect(subject).not_to be_valid
|
37
39
|
end
|
38
40
|
|
39
|
-
it
|
40
|
-
subject.redirect_uri =
|
41
|
+
it "is invalid when the uri is not a uri" do
|
42
|
+
subject.redirect_uri = "]"
|
41
43
|
expect(subject).not_to be_valid
|
42
|
-
expect(subject.errors[:redirect_uri].first).to eq(
|
44
|
+
expect(subject.errors[:redirect_uri].first).to eq("must be a valid URI.")
|
43
45
|
end
|
44
46
|
|
45
|
-
it
|
46
|
-
subject.redirect_uri =
|
47
|
+
it "is invalid when the uri is relative" do
|
48
|
+
subject.redirect_uri = "/abcd"
|
47
49
|
expect(subject).not_to be_valid
|
48
|
-
expect(subject.errors[:redirect_uri].first).to eq(
|
50
|
+
expect(subject.errors[:redirect_uri].first).to eq("must be an absolute URI.")
|
49
51
|
end
|
50
52
|
|
51
|
-
it
|
52
|
-
subject.redirect_uri =
|
53
|
+
it "is invalid when the uri has a fragment" do
|
54
|
+
subject.redirect_uri = "https://example.com/abcd#xyz"
|
53
55
|
expect(subject).not_to be_valid
|
54
|
-
expect(subject.errors[:redirect_uri].first).to eq(
|
56
|
+
expect(subject.errors[:redirect_uri].first).to eq("cannot contain a fragment.")
|
55
57
|
end
|
56
58
|
|
57
|
-
context
|
58
|
-
it
|
59
|
-
subject.redirect_uri =
|
59
|
+
context "force secured uri" do
|
60
|
+
it "accepts an valid uri" do
|
61
|
+
subject.redirect_uri = "https://example.com/callback"
|
60
62
|
expect(subject).to be_valid
|
61
63
|
end
|
62
64
|
|
63
|
-
it
|
64
|
-
subject.redirect_uri =
|
65
|
+
it "accepts native redirect uri" do
|
66
|
+
subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
|
65
67
|
expect(subject).to be_valid
|
66
68
|
end
|
67
69
|
|
68
|
-
it
|
69
|
-
subject.redirect_uri =
|
70
|
+
it "accepts app redirect uri" do
|
71
|
+
subject.redirect_uri = "some-awesome-app://oauth/callback"
|
70
72
|
expect(subject).to be_valid
|
71
73
|
end
|
72
74
|
|
73
|
-
it
|
74
|
-
subject.redirect_uri =
|
75
|
+
it "accepts a non secured protocol when disabled" do
|
76
|
+
subject.redirect_uri = "http://example.com/callback"
|
75
77
|
allow(Doorkeeper.configuration).to receive(
|
76
78
|
:force_ssl_in_redirect_uri
|
77
79
|
).and_return(false)
|
78
80
|
expect(subject).to be_valid
|
79
81
|
end
|
80
82
|
|
81
|
-
it
|
83
|
+
it "accepts a non secured protocol when conditional option defined" do
|
82
84
|
Doorkeeper.configure do
|
83
85
|
orm DOORKEEPER_ORM
|
84
|
-
force_ssl_in_redirect_uri { |uri| uri.host !=
|
86
|
+
force_ssl_in_redirect_uri { |uri| uri.host != "localhost" }
|
85
87
|
end
|
86
88
|
|
87
|
-
application = FactoryBot.build(:application, redirect_uri:
|
89
|
+
application = FactoryBot.build(:application, redirect_uri: "http://localhost/callback")
|
88
90
|
expect(application).to be_valid
|
89
91
|
|
90
|
-
application = FactoryBot.build(:application, redirect_uri:
|
92
|
+
application = FactoryBot.build(:application, redirect_uri: "https://test.com/callback")
|
91
93
|
expect(application).to be_valid
|
92
94
|
|
93
|
-
application = FactoryBot.build(:application, redirect_uri:
|
95
|
+
application = FactoryBot.build(:application, redirect_uri: "http://localhost2/callback")
|
94
96
|
expect(application).not_to be_valid
|
95
97
|
|
96
|
-
application = FactoryBot.build(:application, redirect_uri:
|
98
|
+
application = FactoryBot.build(:application, redirect_uri: "https://test.com/callback")
|
97
99
|
expect(application).to be_valid
|
98
100
|
end
|
99
101
|
|
100
|
-
it
|
101
|
-
subject.redirect_uri =
|
102
|
+
it "forbids redirect uri if required" do
|
103
|
+
subject.redirect_uri = "javascript://document.cookie"
|
102
104
|
|
103
105
|
Doorkeeper.configure do
|
104
106
|
orm DOORKEEPER_ORM
|
105
|
-
forbid_redirect_uri { |uri| uri.scheme ==
|
107
|
+
forbid_redirect_uri { |uri| uri.scheme == "javascript" }
|
106
108
|
end
|
107
109
|
|
108
110
|
expect(subject).to be_invalid
|
109
|
-
expect(subject.errors[:redirect_uri].first).to eq(
|
111
|
+
expect(subject.errors[:redirect_uri].first).to eq("is forbidden by the server.")
|
110
112
|
|
111
|
-
subject.redirect_uri =
|
113
|
+
subject.redirect_uri = "https://localhost/callback"
|
112
114
|
expect(subject).to be_valid
|
113
115
|
end
|
114
116
|
|
115
|
-
it
|
116
|
-
subject.redirect_uri =
|
117
|
+
it "invalidates the uri when the uri does not use a secure protocol" do
|
118
|
+
subject.redirect_uri = "http://example.com/callback"
|
117
119
|
expect(subject).not_to be_valid
|
118
120
|
error = subject.errors[:redirect_uri].first
|
119
|
-
expect(error).to eq(
|
121
|
+
expect(error).to eq("must be an HTTPS/SSL URI.")
|
120
122
|
end
|
121
123
|
end
|
122
124
|
|
123
|
-
context
|
124
|
-
it
|
125
|
+
context "multiple redirect uri" do
|
126
|
+
it "invalidates the second uri when the first uri is native uri" do
|
125
127
|
subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob\nexample.com/callback"
|
126
128
|
expect(subject).to be_invalid
|
127
129
|
end
|
128
130
|
end
|
131
|
+
|
132
|
+
context "blank redirect URI" do
|
133
|
+
it "forbids blank redirect uri by default" do
|
134
|
+
subject.redirect_uri = ""
|
135
|
+
|
136
|
+
expect(subject).to be_invalid
|
137
|
+
expect(subject.errors[:redirect_uri]).not_to be_blank
|
138
|
+
end
|
139
|
+
|
140
|
+
it "forbids blank redirect uri by custom condition" do
|
141
|
+
Doorkeeper.configure do
|
142
|
+
orm DOORKEEPER_ORM
|
143
|
+
allow_blank_redirect_uri do |_grant_flows, application|
|
144
|
+
application.name == "admin app"
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
subject.name = "test app"
|
149
|
+
subject.redirect_uri = ""
|
150
|
+
|
151
|
+
expect(subject).to be_invalid
|
152
|
+
expect(subject.errors[:redirect_uri]).not_to be_blank
|
153
|
+
|
154
|
+
subject.name = "admin app"
|
155
|
+
expect(subject).to be_valid
|
156
|
+
end
|
157
|
+
end
|
129
158
|
end
|