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,62 +1,64 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
class Doorkeeper::OAuth::Client
|
|
4
6
|
describe Credentials do
|
|
5
|
-
let(:client_id) {
|
|
6
|
-
let(:client_secret) {
|
|
7
|
+
let(:client_id) { "some-uid" }
|
|
8
|
+
let(:client_secret) { "some-secret" }
|
|
7
9
|
|
|
8
|
-
it
|
|
10
|
+
it "is blank when the uid in credentials is blank" do
|
|
9
11
|
expect(Credentials.new(nil, nil)).to be_blank
|
|
10
|
-
expect(Credentials.new(nil,
|
|
11
|
-
expect(Credentials.new(
|
|
12
|
-
expect(Credentials.new(
|
|
12
|
+
expect(Credentials.new(nil, "something")).to be_blank
|
|
13
|
+
expect(Credentials.new("something", nil)).to be_present
|
|
14
|
+
expect(Credentials.new("something", "something")).to be_present
|
|
13
15
|
end
|
|
14
16
|
|
|
15
17
|
describe :from_request do
|
|
16
18
|
let(:request) { double.as_null_object }
|
|
17
19
|
|
|
18
20
|
let(:method) do
|
|
19
|
-
->(_request) { [
|
|
21
|
+
->(_request) { %w[uid secret] }
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
it
|
|
24
|
+
it "accepts anything that responds to #call" do
|
|
23
25
|
expect(method).to receive(:call).with(request)
|
|
24
26
|
Credentials.from_request request, method
|
|
25
27
|
end
|
|
26
28
|
|
|
27
|
-
it
|
|
29
|
+
it "delegates methods received as symbols to Credentials class" do
|
|
28
30
|
expect(Credentials).to receive(:from_params).with(request)
|
|
29
31
|
Credentials.from_request request, :from_params
|
|
30
32
|
end
|
|
31
33
|
|
|
32
|
-
it
|
|
34
|
+
it "stops at the first credentials found" do
|
|
33
35
|
not_called_method = double
|
|
34
36
|
expect(not_called_method).not_to receive(:call)
|
|
35
37
|
Credentials.from_request request, ->(_) {}, method, not_called_method
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
it
|
|
40
|
+
it "returns new Credentials" do
|
|
39
41
|
credentials = Credentials.from_request request, method
|
|
40
42
|
expect(credentials).to be_a(Credentials)
|
|
41
43
|
end
|
|
42
44
|
|
|
43
|
-
it
|
|
45
|
+
it "returns uid and secret from extractor method" do
|
|
44
46
|
credentials = Credentials.from_request request, method
|
|
45
|
-
expect(credentials.uid).to eq(
|
|
46
|
-
expect(credentials.secret).to eq(
|
|
47
|
+
expect(credentials.uid).to eq("uid")
|
|
48
|
+
expect(credentials.secret).to eq("secret")
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
|
|
50
52
|
describe :from_params do
|
|
51
|
-
it
|
|
53
|
+
it "returns credentials from parameters when Authorization header is not available" do
|
|
52
54
|
request = double parameters: { client_id: client_id, client_secret: client_secret }
|
|
53
55
|
uid, secret = Credentials.from_params(request)
|
|
54
56
|
|
|
55
|
-
expect(uid).to eq(
|
|
56
|
-
expect(secret).to eq(
|
|
57
|
+
expect(uid).to eq("some-uid")
|
|
58
|
+
expect(secret).to eq("some-secret")
|
|
57
59
|
end
|
|
58
60
|
|
|
59
|
-
it
|
|
61
|
+
it "is blank when there are no credentials" do
|
|
60
62
|
request = double parameters: {}
|
|
61
63
|
uid, secret = Credentials.from_params(request)
|
|
62
64
|
|
|
@@ -68,16 +70,16 @@ class Doorkeeper::OAuth::Client
|
|
|
68
70
|
describe :from_basic do
|
|
69
71
|
let(:credentials) { Base64.encode64("#{client_id}:#{client_secret}") }
|
|
70
72
|
|
|
71
|
-
it
|
|
73
|
+
it "decodes the credentials" do
|
|
72
74
|
request = double authorization: "Basic #{credentials}"
|
|
73
75
|
uid, secret = Credentials.from_basic(request)
|
|
74
76
|
|
|
75
|
-
expect(uid).to eq(
|
|
76
|
-
expect(secret).to eq(
|
|
77
|
+
expect(uid).to eq("some-uid")
|
|
78
|
+
expect(secret).to eq("some-secret")
|
|
77
79
|
end
|
|
78
80
|
|
|
79
|
-
it
|
|
80
|
-
request = double authorization:
|
|
81
|
+
it "is blank if Authorization is not Basic" do
|
|
82
|
+
request = double authorization: credentials.to_s
|
|
81
83
|
uid, secret = Credentials.from_basic(request)
|
|
82
84
|
|
|
83
85
|
expect(uid).to be_blank
|
|
@@ -1,29 +1,75 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
4
6
|
describe Creator do
|
|
5
7
|
let(:client) { FactoryBot.create :application }
|
|
6
|
-
let(:scopes) { Doorkeeper::OAuth::Scopes.from_string(
|
|
8
|
+
let(:scopes) { Doorkeeper::OAuth::Scopes.from_string("public") }
|
|
7
9
|
|
|
8
10
|
before do
|
|
9
11
|
default_scopes_exist :public
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
it
|
|
14
|
+
it "creates a new token" do
|
|
13
15
|
expect do
|
|
14
16
|
subject.call(client, scopes)
|
|
15
17
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
16
18
|
end
|
|
17
19
|
|
|
18
20
|
context "when reuse_access_token is true" do
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
21
|
+
context "when expiration is disabled" do
|
|
22
|
+
it "returns the existing valid token" do
|
|
23
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
|
24
|
+
existing_token = subject.call(client, scopes)
|
|
22
25
|
|
|
23
|
-
|
|
26
|
+
result = subject.call(client, scopes)
|
|
27
|
+
|
|
28
|
+
expect(Doorkeeper::AccessToken.count).to eq(1)
|
|
29
|
+
expect(result).to eq(existing_token)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "when existing token has not crossed token_reuse_limit" do
|
|
34
|
+
it "returns the existing valid token" do
|
|
35
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
|
36
|
+
allow(Doorkeeper.configuration).to receive(:token_reuse_limit).and_return(50)
|
|
37
|
+
existing_token = subject.call(client, scopes, expires_in: 1000)
|
|
38
|
+
|
|
39
|
+
allow_any_instance_of(Doorkeeper::AccessToken).to receive(:expires_in_seconds).and_return(600)
|
|
40
|
+
result = subject.call(client, scopes, expires_in: 1000)
|
|
41
|
+
|
|
42
|
+
expect(Doorkeeper::AccessToken.count).to eq(1)
|
|
43
|
+
expect(result).to eq(existing_token)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
context "when existing token has crossed token_reuse_limit" do
|
|
48
|
+
it "returns a new token" do
|
|
49
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
|
50
|
+
allow(Doorkeeper.configuration).to receive(:token_reuse_limit).and_return(50)
|
|
51
|
+
existing_token = subject.call(client, scopes, expires_in: 1000)
|
|
52
|
+
|
|
53
|
+
allow_any_instance_of(Doorkeeper::AccessToken).to receive(:expires_in_seconds).and_return(400)
|
|
54
|
+
result = subject.call(client, scopes, expires_in: 1000)
|
|
55
|
+
|
|
56
|
+
expect(Doorkeeper::AccessToken.count).to eq(2)
|
|
57
|
+
expect(result).not_to eq(existing_token)
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
context "when existing token has been expired" do
|
|
62
|
+
it "returns a new token" do
|
|
63
|
+
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
|
64
|
+
allow(Doorkeeper.configuration).to receive(:token_reuse_limit).and_return(50)
|
|
65
|
+
existing_token = subject.call(client, scopes, expires_in: 1000)
|
|
66
|
+
|
|
67
|
+
allow_any_instance_of(Doorkeeper::AccessToken).to receive(:expired?).and_return(true)
|
|
68
|
+
result = subject.call(client, scopes, expires_in: 1000)
|
|
24
69
|
|
|
25
|
-
|
|
26
|
-
|
|
70
|
+
expect(Doorkeeper::AccessToken.count).to eq(2)
|
|
71
|
+
expect(result).not_to eq(existing_token)
|
|
72
|
+
end
|
|
27
73
|
end
|
|
28
74
|
end
|
|
29
75
|
|
|
@@ -39,7 +85,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
|
39
85
|
end
|
|
40
86
|
end
|
|
41
87
|
|
|
42
|
-
it
|
|
88
|
+
it "returns false if creation fails" do
|
|
43
89
|
expect(Doorkeeper::AccessToken).to receive(:find_or_create_for).and_return(false)
|
|
44
90
|
created = subject.call(client, scopes)
|
|
45
91
|
expect(created).to be_falsey
|
|
@@ -1,31 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
4
6
|
describe Issuer do
|
|
5
|
-
let(:creator) { double :
|
|
7
|
+
let(:creator) { double :access_token_creator }
|
|
6
8
|
let(:server) do
|
|
7
9
|
double(
|
|
8
10
|
:server,
|
|
9
|
-
access_token_expires_in: 100
|
|
10
|
-
custom_access_token_expires_in: ->(_context) { nil }
|
|
11
|
+
access_token_expires_in: 100
|
|
11
12
|
)
|
|
12
13
|
end
|
|
13
14
|
let(:validation) { double :validation, valid?: true }
|
|
14
15
|
|
|
16
|
+
before do
|
|
17
|
+
allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(false)
|
|
18
|
+
end
|
|
19
|
+
|
|
15
20
|
subject { Issuer.new(server, validation) }
|
|
16
21
|
|
|
17
22
|
describe :create do
|
|
18
|
-
let(:client) { double :client, id:
|
|
19
|
-
let(:scopes) {
|
|
23
|
+
let(:client) { double :client, id: "some-id" }
|
|
24
|
+
let(:scopes) { "some scope" }
|
|
20
25
|
|
|
21
|
-
it
|
|
22
|
-
expect(creator).to receive(:call).and_return(
|
|
26
|
+
it "creates and sets the token" do
|
|
27
|
+
expect(creator).to receive(:call).and_return("token")
|
|
23
28
|
subject.create client, scopes, creator
|
|
24
29
|
|
|
25
|
-
expect(subject.token).to eq(
|
|
30
|
+
expect(subject.token).to eq("token")
|
|
26
31
|
end
|
|
27
32
|
|
|
28
|
-
it
|
|
33
|
+
it "creates with correct token parameters" do
|
|
29
34
|
expect(creator).to receive(:call).with(
|
|
30
35
|
client,
|
|
31
36
|
scopes,
|
|
@@ -36,34 +41,34 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
|
36
41
|
subject.create client, scopes, creator
|
|
37
42
|
end
|
|
38
43
|
|
|
39
|
-
it
|
|
44
|
+
it "has error set to :server_error if creator fails" do
|
|
40
45
|
expect(creator).to receive(:call).and_return(false)
|
|
41
46
|
subject.create client, scopes, creator
|
|
42
47
|
|
|
43
48
|
expect(subject.error).to eq(:server_error)
|
|
44
49
|
end
|
|
45
50
|
|
|
46
|
-
context
|
|
51
|
+
context "when validation fails" do
|
|
47
52
|
before do
|
|
48
53
|
allow(validation).to receive(:valid?).and_return(false)
|
|
49
54
|
allow(validation).to receive(:error).and_return(:validation_error)
|
|
50
55
|
expect(creator).not_to receive(:create)
|
|
51
56
|
end
|
|
52
57
|
|
|
53
|
-
it
|
|
58
|
+
it "has error set from validation" do
|
|
54
59
|
subject.create client, scopes, creator
|
|
55
60
|
expect(subject.error).to eq(:validation_error)
|
|
56
61
|
end
|
|
57
62
|
|
|
58
|
-
it
|
|
63
|
+
it "returns false" do
|
|
59
64
|
expect(subject.create(client, scopes, creator)).to be_falsey
|
|
60
65
|
end
|
|
61
66
|
end
|
|
62
67
|
|
|
63
|
-
context
|
|
68
|
+
context "with custom expirations" do
|
|
64
69
|
let(:custom_ttl_grant) { 1234 }
|
|
65
70
|
let(:custom_ttl_scope) { 1235 }
|
|
66
|
-
let(:custom_scope) {
|
|
71
|
+
let(:custom_scope) { "special" }
|
|
67
72
|
let(:server) do
|
|
68
73
|
double(
|
|
69
74
|
:server,
|
|
@@ -73,14 +78,16 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
|
73
78
|
custom_ttl_scope
|
|
74
79
|
elsif context.grant_type == Doorkeeper::OAuth::CLIENT_CREDENTIALS
|
|
75
80
|
custom_ttl_grant
|
|
76
|
-
else
|
|
77
|
-
nil
|
|
78
81
|
end
|
|
79
82
|
}
|
|
80
83
|
)
|
|
81
84
|
end
|
|
82
85
|
|
|
83
|
-
|
|
86
|
+
before do
|
|
87
|
+
allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "respects grant based rules" do
|
|
84
91
|
expect(creator).to receive(:call).with(
|
|
85
92
|
client,
|
|
86
93
|
scopes,
|
|
@@ -90,7 +97,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
|
90
97
|
subject.create client, scopes, creator
|
|
91
98
|
end
|
|
92
99
|
|
|
93
|
-
it
|
|
100
|
+
it "respects scope based rules" do
|
|
94
101
|
expect(creator).to receive(:call).with(
|
|
95
102
|
client,
|
|
96
103
|
custom_scope,
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
4
6
|
describe Validation do
|
|
@@ -9,41 +11,45 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
|
9
11
|
|
|
10
12
|
subject { Validation.new(server, request) }
|
|
11
13
|
|
|
12
|
-
it
|
|
14
|
+
it "is valid with valid request" do
|
|
13
15
|
expect(subject).to be_valid
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
it
|
|
18
|
+
it "is invalid when client is not present" do
|
|
17
19
|
allow(request).to receive(:client).and_return(nil)
|
|
18
20
|
expect(subject).not_to be_valid
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
context
|
|
22
|
-
it
|
|
23
|
-
server_scopes = Doorkeeper::OAuth::Scopes.from_string
|
|
23
|
+
context "with scopes" do
|
|
24
|
+
it "is invalid when scopes are not included in the server" do
|
|
25
|
+
server_scopes = Doorkeeper::OAuth::Scopes.from_string "email"
|
|
26
|
+
allow(request).to receive(:grant_type).and_return(Doorkeeper::OAuth::CLIENT_CREDENTIALS)
|
|
24
27
|
allow(server).to receive(:scopes).and_return(server_scopes)
|
|
25
28
|
allow(request).to receive(:scopes).and_return(
|
|
26
|
-
Doorkeeper::OAuth::Scopes.from_string
|
|
29
|
+
Doorkeeper::OAuth::Scopes.from_string("invalid")
|
|
30
|
+
)
|
|
27
31
|
expect(subject).not_to be_valid
|
|
28
32
|
end
|
|
29
33
|
|
|
30
|
-
context
|
|
31
|
-
it
|
|
32
|
-
application_scopes = Doorkeeper::OAuth::Scopes.from_string
|
|
33
|
-
server_scopes = Doorkeeper::OAuth::Scopes.from_string
|
|
34
|
+
context "with application scopes" do
|
|
35
|
+
it "is valid when scopes are included in the application" do
|
|
36
|
+
application_scopes = Doorkeeper::OAuth::Scopes.from_string "app"
|
|
37
|
+
server_scopes = Doorkeeper::OAuth::Scopes.from_string "email app"
|
|
34
38
|
allow(application).to receive(:scopes).and_return(application_scopes)
|
|
35
39
|
allow(server).to receive(:scopes).and_return(server_scopes)
|
|
40
|
+
allow(request).to receive(:grant_type).and_return(Doorkeeper::OAuth::CLIENT_CREDENTIALS)
|
|
36
41
|
allow(request).to receive(:scopes).and_return(application_scopes)
|
|
37
42
|
expect(subject).to be_valid
|
|
38
43
|
end
|
|
39
44
|
|
|
40
|
-
it
|
|
41
|
-
application_scopes = Doorkeeper::OAuth::Scopes.from_string
|
|
42
|
-
server_scopes = Doorkeeper::OAuth::Scopes.from_string
|
|
45
|
+
it "is invalid when scopes are not included in the application" do
|
|
46
|
+
application_scopes = Doorkeeper::OAuth::Scopes.from_string "app"
|
|
47
|
+
server_scopes = Doorkeeper::OAuth::Scopes.from_string "email app"
|
|
43
48
|
allow(application).to receive(:scopes).and_return(application_scopes)
|
|
49
|
+
allow(request).to receive(:grant_type).and_return(Doorkeeper::OAuth::CLIENT_CREDENTIALS)
|
|
44
50
|
allow(server).to receive(:scopes).and_return(server_scopes)
|
|
45
51
|
allow(request).to receive(:scopes).and_return(
|
|
46
|
-
Doorkeeper::OAuth::Scopes.from_string(
|
|
52
|
+
Doorkeeper::OAuth::Scopes.from_string("email")
|
|
47
53
|
)
|
|
48
54
|
expect(subject).not_to be_valid
|
|
49
55
|
end
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper::OAuth
|
|
4
6
|
describe ClientCredentialsRequest do
|
|
5
7
|
let(:server) { Doorkeeper.configuration }
|
|
6
8
|
|
|
7
|
-
context
|
|
9
|
+
context "with a valid request" do
|
|
8
10
|
let(:client) { FactoryBot.create :application }
|
|
9
11
|
|
|
10
|
-
it
|
|
12
|
+
it "issues an access token" do
|
|
11
13
|
request = ClientCredentialsRequest.new(server, client, {})
|
|
12
14
|
expect do
|
|
13
15
|
request.authorize
|
|
@@ -15,12 +17,12 @@ module Doorkeeper::OAuth
|
|
|
15
17
|
end
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
describe
|
|
19
|
-
it
|
|
20
|
+
describe "with an invalid request" do
|
|
21
|
+
it "does not issue an access token" do
|
|
20
22
|
request = ClientCredentialsRequest.new(server, nil, {})
|
|
21
23
|
expect do
|
|
22
24
|
request.authorize
|
|
23
|
-
end.to_not
|
|
25
|
+
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
24
26
|
end
|
|
25
27
|
end
|
|
26
28
|
end
|
|
@@ -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 ClientCredentialsRequest do
|
|
@@ -10,71 +12,75 @@ module Doorkeeper::OAuth
|
|
|
10
12
|
)
|
|
11
13
|
end
|
|
12
14
|
|
|
13
|
-
let(:application) { FactoryBot.create(:application, scopes:
|
|
15
|
+
let(:application) { FactoryBot.create(:application, scopes: "") }
|
|
14
16
|
let(:client) { double :client, application: application }
|
|
15
17
|
let(:token_creator) { double :issuer, create: true, token: double }
|
|
16
18
|
|
|
19
|
+
before do
|
|
20
|
+
allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
|
|
21
|
+
end
|
|
22
|
+
|
|
17
23
|
subject { ClientCredentialsRequest.new(server, client) }
|
|
18
24
|
|
|
19
25
|
before do
|
|
20
26
|
subject.issuer = token_creator
|
|
21
27
|
end
|
|
22
28
|
|
|
23
|
-
it
|
|
29
|
+
it "issues an access token for the current client" do
|
|
24
30
|
expect(token_creator).to receive(:create).with(client, nil)
|
|
25
31
|
subject.authorize
|
|
26
32
|
end
|
|
27
33
|
|
|
28
|
-
it
|
|
34
|
+
it "has successful response when issue was created" do
|
|
29
35
|
subject.authorize
|
|
30
36
|
expect(subject.response).to be_a(TokenResponse)
|
|
31
37
|
end
|
|
32
38
|
|
|
33
|
-
context
|
|
39
|
+
context "if issue was not created" do
|
|
34
40
|
before do
|
|
35
41
|
subject.issuer = double create: false, error: :invalid
|
|
36
42
|
end
|
|
37
43
|
|
|
38
|
-
it
|
|
44
|
+
it "has an error response" do
|
|
39
45
|
subject.authorize
|
|
40
46
|
expect(subject.response).to be_a(Doorkeeper::OAuth::ErrorResponse)
|
|
41
47
|
end
|
|
42
48
|
|
|
43
|
-
it
|
|
49
|
+
it "delegates the error to issuer" do
|
|
44
50
|
subject.authorize
|
|
45
51
|
expect(subject.error).to eq(:invalid)
|
|
46
52
|
end
|
|
47
53
|
end
|
|
48
54
|
|
|
49
|
-
context
|
|
50
|
-
let(:default_scopes) { Doorkeeper::OAuth::Scopes.from_string(
|
|
55
|
+
context "with scopes" do
|
|
56
|
+
let(:default_scopes) { Doorkeeper::OAuth::Scopes.from_string("public email") }
|
|
51
57
|
|
|
52
58
|
before do
|
|
53
59
|
allow(server).to receive(:default_scopes).and_return(default_scopes)
|
|
54
60
|
end
|
|
55
61
|
|
|
56
|
-
it
|
|
62
|
+
it "issues an access token with default scopes if none was requested" do
|
|
57
63
|
expect(token_creator).to receive(:create).with(client, default_scopes)
|
|
58
64
|
subject.authorize
|
|
59
65
|
end
|
|
60
66
|
|
|
61
|
-
it
|
|
62
|
-
subject = ClientCredentialsRequest.new(server, client, scope:
|
|
67
|
+
it "issues an access token with requested scopes" do
|
|
68
|
+
subject = ClientCredentialsRequest.new(server, client, scope: "email")
|
|
63
69
|
subject.issuer = token_creator
|
|
64
|
-
expect(token_creator).to receive(:create).with(client, Doorkeeper::OAuth::Scopes.from_string(
|
|
70
|
+
expect(token_creator).to receive(:create).with(client, Doorkeeper::OAuth::Scopes.from_string("email"))
|
|
65
71
|
subject.authorize
|
|
66
72
|
end
|
|
67
73
|
end
|
|
68
74
|
|
|
69
|
-
context
|
|
75
|
+
context "with restricted client" do
|
|
70
76
|
let(:default_scopes) do
|
|
71
|
-
Doorkeeper::OAuth::Scopes.from_string(
|
|
77
|
+
Doorkeeper::OAuth::Scopes.from_string("public email")
|
|
72
78
|
end
|
|
73
79
|
let(:server_scopes) do
|
|
74
|
-
Doorkeeper::OAuth::Scopes.from_string(
|
|
80
|
+
Doorkeeper::OAuth::Scopes.from_string("public email phone")
|
|
75
81
|
end
|
|
76
82
|
let(:client_scopes) do
|
|
77
|
-
Doorkeeper::OAuth::Scopes.from_string(
|
|
83
|
+
Doorkeeper::OAuth::Scopes.from_string("public phone")
|
|
78
84
|
end
|
|
79
85
|
|
|
80
86
|
before do
|
|
@@ -85,18 +91,18 @@ module Doorkeeper::OAuth
|
|
|
85
91
|
allow(client).to receive(:id).and_return(nil)
|
|
86
92
|
end
|
|
87
93
|
|
|
88
|
-
it
|
|
94
|
+
it "delegates the error to issuer if no scope was requested" do
|
|
89
95
|
subject = ClientCredentialsRequest.new(server, client)
|
|
90
96
|
subject.authorize
|
|
91
97
|
expect(subject.response).to be_a(Doorkeeper::OAuth::ErrorResponse)
|
|
92
98
|
expect(subject.error).to eq(:invalid_scope)
|
|
93
99
|
end
|
|
94
100
|
|
|
95
|
-
it
|
|
96
|
-
subject = ClientCredentialsRequest.new(server, client, scope:
|
|
101
|
+
it "issues an access token with requested scopes" do
|
|
102
|
+
subject = ClientCredentialsRequest.new(server, client, scope: "phone")
|
|
97
103
|
subject.authorize
|
|
98
104
|
expect(subject.response).to be_a(Doorkeeper::OAuth::TokenResponse)
|
|
99
|
-
expect(subject.response.token.scopes_string).to eq(
|
|
105
|
+
expect(subject.response.token.scopes_string).to eq("phone")
|
|
100
106
|
end
|
|
101
107
|
end
|
|
102
108
|
end
|
|
@@ -1,34 +1,36 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
module Doorkeeper::OAuth
|
|
4
6
|
describe Client do
|
|
5
7
|
describe :find do
|
|
6
8
|
let(:method) { double }
|
|
7
9
|
|
|
8
|
-
it
|
|
10
|
+
it "finds the client via uid" do
|
|
9
11
|
client = double
|
|
10
|
-
expect(method).to receive(:call).with(
|
|
11
|
-
expect(Client.find(
|
|
12
|
+
expect(method).to receive(:call).with("uid").and_return(client)
|
|
13
|
+
expect(Client.find("uid", method)).to be_a(Client)
|
|
12
14
|
end
|
|
13
15
|
|
|
14
|
-
it
|
|
15
|
-
expect(method).to receive(:call).with(
|
|
16
|
-
expect(Client.find(
|
|
16
|
+
it "returns nil if client was not found" do
|
|
17
|
+
expect(method).to receive(:call).with("uid").and_return(nil)
|
|
18
|
+
expect(Client.find("uid", method)).to be_nil
|
|
17
19
|
end
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
describe :authenticate do
|
|
21
|
-
it
|
|
22
|
-
credentials = Client::Credentials.new(
|
|
23
|
+
it "returns the authenticated client via credentials" do
|
|
24
|
+
credentials = Client::Credentials.new("some-uid", "some-secret")
|
|
23
25
|
authenticator = double
|
|
24
|
-
expect(authenticator).to receive(:call).with(
|
|
26
|
+
expect(authenticator).to receive(:call).with("some-uid", "some-secret").and_return(double)
|
|
25
27
|
expect(Client.authenticate(credentials, authenticator)).to be_a(Client)
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
it
|
|
29
|
-
credentials = Client::Credentials.new(
|
|
30
|
+
it "returns nil if client was not authenticated" do
|
|
31
|
+
credentials = Client::Credentials.new("some-uid", "some-secret")
|
|
30
32
|
authenticator = double
|
|
31
|
-
expect(authenticator).to receive(:call).with(
|
|
33
|
+
expect(authenticator).to receive(:call).with("some-uid", "some-secret").and_return(nil)
|
|
32
34
|
expect(Client.authenticate(credentials, authenticator)).to be_nil
|
|
33
35
|
end
|
|
34
36
|
end
|
|
@@ -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 CodeRequest do
|
|
@@ -6,13 +8,13 @@ module Doorkeeper::OAuth
|
|
|
6
8
|
double(
|
|
7
9
|
:pre_auth,
|
|
8
10
|
client: double(:application, id: 9990),
|
|
9
|
-
redirect_uri:
|
|
11
|
+
redirect_uri: "http://tst.com/cb",
|
|
10
12
|
scopes: nil,
|
|
11
13
|
state: nil,
|
|
12
14
|
error: nil,
|
|
13
15
|
authorizable?: true,
|
|
14
16
|
code_challenge: nil,
|
|
15
|
-
code_challenge_method: nil
|
|
17
|
+
code_challenge_method: nil
|
|
16
18
|
)
|
|
17
19
|
end
|
|
18
20
|
|
|
@@ -22,22 +24,22 @@ module Doorkeeper::OAuth
|
|
|
22
24
|
CodeRequest.new(pre_auth, owner)
|
|
23
25
|
end
|
|
24
26
|
|
|
25
|
-
it
|
|
27
|
+
it "creates an access grant" do
|
|
26
28
|
expect do
|
|
27
29
|
subject.authorize
|
|
28
30
|
end.to change { Doorkeeper::AccessGrant.count }.by(1)
|
|
29
31
|
end
|
|
30
32
|
|
|
31
|
-
it
|
|
33
|
+
it "returns a code response" do
|
|
32
34
|
expect(subject.authorize).to be_a(CodeResponse)
|
|
33
35
|
end
|
|
34
36
|
|
|
35
|
-
it
|
|
37
|
+
it "does not create grant when not authorizable" do
|
|
36
38
|
allow(pre_auth).to receive(:authorizable?).and_return(false)
|
|
37
|
-
expect { subject.authorize }.not_to
|
|
39
|
+
expect { subject.authorize }.not_to(change { Doorkeeper::AccessGrant.count })
|
|
38
40
|
end
|
|
39
41
|
|
|
40
|
-
it
|
|
42
|
+
it "returns a error response" do
|
|
41
43
|
allow(pre_auth).to receive(:authorizable?).and_return(false)
|
|
42
44
|
expect(subject.authorize).to be_a(ErrorResponse)
|
|
43
45
|
end
|