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,12 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
describe Doorkeeper::TokensController do
|
|
4
|
-
describe
|
|
6
|
+
describe "when authorization has succeeded" do
|
|
5
7
|
let(:token) { double(:token, authorize: true) }
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
skip 'verify need of these specs'
|
|
9
|
+
it "returns the authorization" do
|
|
10
|
+
skip "verify need of these specs"
|
|
10
11
|
|
|
11
12
|
expect(token).to receive(:authorization)
|
|
12
13
|
|
|
@@ -14,28 +15,28 @@ describe Doorkeeper::TokensController do
|
|
|
14
15
|
end
|
|
15
16
|
end
|
|
16
17
|
|
|
17
|
-
describe
|
|
18
|
-
it
|
|
18
|
+
describe "when authorization has failed" do
|
|
19
|
+
it "returns the error response" do
|
|
19
20
|
token = double(:token, authorize: false)
|
|
20
21
|
allow(controller).to receive(:token) { token }
|
|
21
22
|
|
|
22
23
|
post :create
|
|
23
24
|
|
|
24
|
-
expect(response.status).to eq
|
|
25
|
-
expect(response.headers[
|
|
25
|
+
expect(response.status).to eq 400
|
|
26
|
+
expect(response.headers["WWW-Authenticate"]).to match(/Bearer/)
|
|
26
27
|
end
|
|
27
28
|
end
|
|
28
29
|
|
|
29
|
-
describe
|
|
30
|
-
it
|
|
30
|
+
describe "when there is a failure due to a custom error" do
|
|
31
|
+
it "returns the error response with a custom message" do
|
|
31
32
|
# I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
|
|
32
33
|
custom_message = "my_message"
|
|
33
|
-
allow(I18n).to receive(:translate)
|
|
34
|
-
with(
|
|
34
|
+
allow(I18n).to receive(:translate)
|
|
35
|
+
.with(
|
|
35
36
|
custom_message,
|
|
36
37
|
hash_including(scope: %i[doorkeeper errors messages])
|
|
37
|
-
)
|
|
38
|
-
and_return(
|
|
38
|
+
)
|
|
39
|
+
.and_return("Authorization custom message")
|
|
39
40
|
|
|
40
41
|
doorkeeper_error = Doorkeeper::Errors::DoorkeeperError.new(custom_message)
|
|
41
42
|
|
|
@@ -47,41 +48,37 @@ describe Doorkeeper::TokensController do
|
|
|
47
48
|
post :create
|
|
48
49
|
|
|
49
50
|
expected_response_body = {
|
|
50
|
-
"error"
|
|
51
|
-
"error_description" => "Authorization custom message"
|
|
51
|
+
"error" => custom_message,
|
|
52
|
+
"error_description" => "Authorization custom message",
|
|
52
53
|
}
|
|
53
|
-
expect(response.status).to eq
|
|
54
|
-
expect(response.headers[
|
|
54
|
+
expect(response.status).to eq 400
|
|
55
|
+
expect(response.headers["WWW-Authenticate"]).to match(/Bearer/)
|
|
55
56
|
expect(JSON.parse(response.body)).to eq expected_response_body
|
|
56
57
|
end
|
|
57
58
|
end
|
|
58
59
|
|
|
59
60
|
# http://tools.ietf.org/html/rfc7009#section-2.2
|
|
60
|
-
describe
|
|
61
|
+
describe "revoking tokens" do
|
|
61
62
|
let(:client) { FactoryBot.create(:application) }
|
|
62
63
|
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
63
64
|
|
|
64
|
-
|
|
65
|
-
allow(controller).to receive(:token) { access_token }
|
|
66
|
-
end
|
|
67
|
-
|
|
68
|
-
context 'when associated app is public' do
|
|
65
|
+
context "when associated app is public" do
|
|
69
66
|
let(:client) { FactoryBot.create(:application, confidential: false) }
|
|
70
67
|
|
|
71
|
-
it
|
|
72
|
-
post :revoke
|
|
68
|
+
it "returns 200" do
|
|
69
|
+
post :revoke, params: { token: access_token.token }
|
|
73
70
|
|
|
74
71
|
expect(response.status).to eq 200
|
|
75
72
|
end
|
|
76
73
|
|
|
77
|
-
it
|
|
78
|
-
post :revoke
|
|
74
|
+
it "revokes the access token" do
|
|
75
|
+
post :revoke, params: { token: access_token.token }
|
|
79
76
|
|
|
80
77
|
expect(access_token.reload).to have_attributes(revoked?: true)
|
|
81
78
|
end
|
|
82
79
|
end
|
|
83
80
|
|
|
84
|
-
context
|
|
81
|
+
context "when associated app is confidential" do
|
|
85
82
|
let(:client) { FactoryBot.create(:application, confidential: true) }
|
|
86
83
|
let(:oauth_client) { Doorkeeper::OAuth::Client.new(client) }
|
|
87
84
|
|
|
@@ -89,30 +86,30 @@ describe Doorkeeper::TokensController do
|
|
|
89
86
|
allow_any_instance_of(Doorkeeper::Server).to receive(:client) { oauth_client }
|
|
90
87
|
end
|
|
91
88
|
|
|
92
|
-
it
|
|
93
|
-
post :revoke
|
|
89
|
+
it "returns 200" do
|
|
90
|
+
post :revoke, params: { token: access_token.token }
|
|
94
91
|
|
|
95
92
|
expect(response.status).to eq 200
|
|
96
93
|
end
|
|
97
94
|
|
|
98
|
-
it
|
|
99
|
-
post :revoke
|
|
95
|
+
it "revokes the access token" do
|
|
96
|
+
post :revoke, params: { token: access_token.token }
|
|
100
97
|
|
|
101
98
|
expect(access_token.reload).to have_attributes(revoked?: true)
|
|
102
99
|
end
|
|
103
100
|
|
|
104
|
-
context
|
|
101
|
+
context "when authorization fails" do
|
|
105
102
|
let(:some_other_client) { FactoryBot.create(:application, confidential: true) }
|
|
106
103
|
let(:oauth_client) { Doorkeeper::OAuth::Client.new(some_other_client) }
|
|
107
104
|
|
|
108
|
-
it
|
|
109
|
-
post :revoke
|
|
105
|
+
it "returns 200" do
|
|
106
|
+
post :revoke, params: { token: access_token.token }
|
|
110
107
|
|
|
111
108
|
expect(response.status).to eq 200
|
|
112
109
|
end
|
|
113
110
|
|
|
114
|
-
it
|
|
115
|
-
post :revoke
|
|
111
|
+
it "does not revoke the access token" do
|
|
112
|
+
post :revoke, params: { token: access_token.token }
|
|
116
113
|
|
|
117
114
|
expect(access_token.reload).to have_attributes(revoked?: false)
|
|
118
115
|
end
|
|
@@ -120,7 +117,7 @@ describe Doorkeeper::TokensController do
|
|
|
120
117
|
end
|
|
121
118
|
end
|
|
122
119
|
|
|
123
|
-
describe
|
|
120
|
+
describe "authorize response memoization" do
|
|
124
121
|
it "memoizes the result of the authorization" do
|
|
125
122
|
strategy = double(:strategy, authorize: true)
|
|
126
123
|
expect(strategy).to receive(:authorize).once
|
|
@@ -134,138 +131,199 @@ describe Doorkeeper::TokensController do
|
|
|
134
131
|
end
|
|
135
132
|
end
|
|
136
133
|
|
|
137
|
-
describe
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
134
|
+
describe "when requested token introspection" do
|
|
135
|
+
let(:client) { FactoryBot.create(:application) }
|
|
136
|
+
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
137
|
+
let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
|
|
141
138
|
|
|
142
|
-
|
|
143
|
-
|
|
139
|
+
context "authorized using valid Bearer token" do
|
|
140
|
+
it "responds with full token introspection" do
|
|
141
|
+
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
|
144
142
|
|
|
145
|
-
post :introspect, params: { token:
|
|
143
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
146
144
|
|
|
147
|
-
should_have_json
|
|
148
|
-
expect(json_response).to include(
|
|
145
|
+
should_have_json "active", true
|
|
146
|
+
expect(json_response).to include("client_id", "token_type", "exp", "iat")
|
|
149
147
|
end
|
|
150
148
|
end
|
|
151
149
|
|
|
152
|
-
context
|
|
153
|
-
|
|
154
|
-
|
|
150
|
+
context "authorized using valid Client Authentication" do
|
|
151
|
+
it "responds with full token introspection" do
|
|
152
|
+
request.headers["Authorization"] = basic_auth_header_for_client(client)
|
|
155
153
|
|
|
156
|
-
|
|
157
|
-
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
154
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
158
155
|
|
|
159
|
-
|
|
156
|
+
should_have_json "active", true
|
|
157
|
+
expect(json_response).to include("client_id", "token_type", "exp", "iat")
|
|
158
|
+
should_have_json "client_id", client.uid
|
|
159
|
+
end
|
|
160
|
+
end
|
|
160
161
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
162
|
+
context "using custom introspection response" do
|
|
163
|
+
before do
|
|
164
|
+
Doorkeeper.configure do
|
|
165
|
+
orm DOORKEEPER_ORM
|
|
166
|
+
custom_introspection_response do |_token, _context|
|
|
167
|
+
{
|
|
168
|
+
sub: "Z5O3upPC88QrAjx00dis",
|
|
169
|
+
aud: "https://protected.example.net/resource",
|
|
170
|
+
}
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "responds with full token introspection" do
|
|
176
|
+
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
|
177
|
+
|
|
178
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
179
|
+
|
|
180
|
+
expect(json_response).to include("client_id", "token_type", "exp", "iat", "sub", "aud")
|
|
181
|
+
should_have_json "sub", "Z5O3upPC88QrAjx00dis"
|
|
182
|
+
should_have_json "aud", "https://protected.example.net/resource"
|
|
164
183
|
end
|
|
165
184
|
end
|
|
166
185
|
|
|
167
|
-
context
|
|
168
|
-
let(:
|
|
169
|
-
let(:access_token) { FactoryBot.create(:access_token, application: nil) }
|
|
186
|
+
context "public access token" do
|
|
187
|
+
let(:token_for_introspection) { FactoryBot.create(:access_token, application: nil) }
|
|
170
188
|
|
|
171
|
-
it
|
|
172
|
-
request.headers[
|
|
189
|
+
it "responds with full token introspection" do
|
|
190
|
+
request.headers["Authorization"] = basic_auth_header_for_client(client)
|
|
173
191
|
|
|
174
|
-
post :introspect, params: { token:
|
|
192
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
175
193
|
|
|
176
|
-
should_have_json
|
|
177
|
-
expect(json_response).to include(
|
|
178
|
-
should_have_json
|
|
194
|
+
should_have_json "active", true
|
|
195
|
+
expect(json_response).to include("client_id", "token_type", "exp", "iat")
|
|
196
|
+
should_have_json "client_id", nil
|
|
179
197
|
end
|
|
180
198
|
end
|
|
181
199
|
|
|
182
|
-
context
|
|
183
|
-
let(:client) { FactoryBot.create(:application) }
|
|
200
|
+
context "token was issued to a different client than is making this request" do
|
|
184
201
|
let(:different_client) { FactoryBot.create(:application) }
|
|
185
|
-
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
186
202
|
|
|
187
|
-
it
|
|
188
|
-
request.headers[
|
|
203
|
+
it "responds with only active state" do
|
|
204
|
+
request.headers["Authorization"] = basic_auth_header_for_client(different_client)
|
|
189
205
|
|
|
190
|
-
post :introspect, params: { token:
|
|
206
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
191
207
|
|
|
192
208
|
expect(response).to be_successful
|
|
193
209
|
|
|
194
|
-
should_have_json
|
|
195
|
-
expect(json_response).not_to include(
|
|
210
|
+
should_have_json "active", false
|
|
211
|
+
expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
context "authorized using invalid Bearer token" do
|
|
216
|
+
let(:access_token) do
|
|
217
|
+
FactoryBot.create(:access_token, application: client, revoked_at: 1.day.ago)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
it "responds with invalid token error" do
|
|
221
|
+
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
|
222
|
+
|
|
223
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
224
|
+
|
|
225
|
+
response_status_should_be 401
|
|
226
|
+
|
|
227
|
+
should_not_have_json "active"
|
|
228
|
+
should_have_json "error", "invalid_token"
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context "authorized using the Bearer token that need to be introspected" do
|
|
233
|
+
it "responds with invalid token error" do
|
|
234
|
+
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
|
235
|
+
|
|
236
|
+
post :introspect, params: { token: access_token.token }
|
|
237
|
+
|
|
238
|
+
response_status_should_be 401
|
|
239
|
+
|
|
240
|
+
should_not_have_json "active"
|
|
241
|
+
should_have_json "error", "invalid_token"
|
|
196
242
|
end
|
|
197
243
|
end
|
|
198
244
|
|
|
199
|
-
context
|
|
200
|
-
let(:client) { double(uid:
|
|
245
|
+
context "using invalid credentials to authorize" do
|
|
246
|
+
let(:client) { double(uid: "123123", secret: "666999") }
|
|
201
247
|
let(:access_token) { FactoryBot.create(:access_token) }
|
|
202
248
|
|
|
203
|
-
it
|
|
204
|
-
request.headers[
|
|
249
|
+
it "responds with invalid_client error" do
|
|
250
|
+
request.headers["Authorization"] = basic_auth_header_for_client(client)
|
|
205
251
|
|
|
206
252
|
post :introspect, params: { token: access_token.token }
|
|
207
253
|
|
|
208
254
|
expect(response).not_to be_successful
|
|
209
255
|
response_status_should_be 401
|
|
210
256
|
|
|
211
|
-
should_not_have_json
|
|
212
|
-
should_have_json
|
|
257
|
+
should_not_have_json "active"
|
|
258
|
+
should_have_json "error", "invalid_client"
|
|
213
259
|
end
|
|
214
260
|
end
|
|
215
261
|
|
|
216
|
-
context
|
|
217
|
-
|
|
218
|
-
|
|
262
|
+
context "using wrong token value" do
|
|
263
|
+
context "authorized using client credentials" do
|
|
264
|
+
it "responds with only active state" do
|
|
265
|
+
request.headers["Authorization"] = basic_auth_header_for_client(client)
|
|
219
266
|
|
|
220
|
-
|
|
221
|
-
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
267
|
+
post :introspect, params: { token: SecureRandom.hex(16) }
|
|
222
268
|
|
|
223
|
-
|
|
269
|
+
should_have_json "active", false
|
|
270
|
+
expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
context "authorized using valid Bearer token" do
|
|
275
|
+
it "responds with only active state" do
|
|
276
|
+
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
|
277
|
+
|
|
278
|
+
post :introspect, params: { token: SecureRandom.hex(16) }
|
|
224
279
|
|
|
225
|
-
|
|
226
|
-
|
|
280
|
+
should_have_json "active", false
|
|
281
|
+
expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
|
|
282
|
+
end
|
|
227
283
|
end
|
|
228
284
|
end
|
|
229
285
|
|
|
230
|
-
context
|
|
231
|
-
let(:
|
|
232
|
-
|
|
286
|
+
context "when requested access token expired" do
|
|
287
|
+
let(:token_for_introspection) do
|
|
288
|
+
FactoryBot.create(:access_token, application: client, created_at: 1.year.ago)
|
|
289
|
+
end
|
|
233
290
|
|
|
234
|
-
it
|
|
235
|
-
request.headers[
|
|
291
|
+
it "responds with only active state" do
|
|
292
|
+
request.headers["Authorization"] = basic_auth_header_for_client(client)
|
|
236
293
|
|
|
237
|
-
post :introspect, params: { token:
|
|
294
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
238
295
|
|
|
239
|
-
should_have_json
|
|
240
|
-
expect(json_response).not_to include(
|
|
296
|
+
should_have_json "active", false
|
|
297
|
+
expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
|
|
241
298
|
end
|
|
242
299
|
end
|
|
243
300
|
|
|
244
|
-
context
|
|
245
|
-
let(:
|
|
246
|
-
|
|
301
|
+
context "when requested Access Token revoked" do
|
|
302
|
+
let(:token_for_introspection) do
|
|
303
|
+
FactoryBot.create(:access_token, application: client, revoked_at: 1.year.ago)
|
|
304
|
+
end
|
|
247
305
|
|
|
248
|
-
it
|
|
249
|
-
request.headers[
|
|
306
|
+
it "responds with only active state" do
|
|
307
|
+
request.headers["Authorization"] = basic_auth_header_for_client(client)
|
|
250
308
|
|
|
251
|
-
post :introspect, params: { token:
|
|
309
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
252
310
|
|
|
253
|
-
should_have_json
|
|
254
|
-
expect(json_response).not_to include(
|
|
311
|
+
should_have_json "active", false
|
|
312
|
+
expect(json_response).not_to include("client_id", "token_type", "exp", "iat")
|
|
255
313
|
end
|
|
256
314
|
end
|
|
257
315
|
|
|
258
|
-
context
|
|
259
|
-
let(:
|
|
316
|
+
context "unauthorized (no bearer token or client credentials)" do
|
|
317
|
+
let(:token_for_introspection) { FactoryBot.create(:access_token) }
|
|
260
318
|
|
|
261
|
-
it
|
|
262
|
-
post :introspect, params: { token:
|
|
319
|
+
it "responds with invalid_request error" do
|
|
320
|
+
post :introspect, params: { token: token_for_introspection.token }
|
|
263
321
|
|
|
264
322
|
expect(response).not_to be_successful
|
|
265
|
-
response_status_should_be
|
|
323
|
+
response_status_should_be 400
|
|
266
324
|
|
|
267
|
-
should_not_have_json
|
|
268
|
-
should_have_json
|
|
325
|
+
should_not_have_json "active"
|
|
326
|
+
should_have_json "error", "invalid_request"
|
|
269
327
|
end
|
|
270
328
|
end
|
|
271
329
|
end
|
data/spec/dummy/Rakefile
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env rake
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
2
4
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
|
3
5
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
|
4
6
|
|
|
5
|
-
require File.expand_path(
|
|
7
|
+
require File.expand_path("config/application", __dir__)
|
|
6
8
|
|
|
7
9
|
Dummy::Application.load_tasks
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
class CustomAuthorizationsController < ::ApplicationController
|
|
2
|
-
%w
|
|
4
|
+
%w[index show new create edit update destroy].each do |action|
|
|
3
5
|
define_method action do
|
|
4
6
|
render nothing: true
|
|
5
7
|
end
|
|
@@ -1,12 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
class FullProtectedResourcesController < ApplicationController
|
|
2
4
|
before_action -> { doorkeeper_authorize! :write, :admin }, only: :show
|
|
3
5
|
before_action :doorkeeper_authorize!, only: :index
|
|
4
6
|
|
|
5
7
|
def index
|
|
6
|
-
render plain:
|
|
8
|
+
render plain: "index"
|
|
7
9
|
end
|
|
8
10
|
|
|
9
11
|
def show
|
|
10
|
-
render plain:
|
|
12
|
+
render plain: "show"
|
|
11
13
|
end
|
|
12
14
|
end
|
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
class HomeController < ApplicationController
|
|
2
|
-
def index
|
|
3
|
-
end
|
|
4
|
+
def index; end
|
|
4
5
|
|
|
5
6
|
def sign_in
|
|
6
7
|
session[:user_id] = if Rails.env.development?
|
|
7
|
-
User.first || User.create!(name:
|
|
8
|
+
User.first || User.create!(name: "Joe", password: "sekret")
|
|
8
9
|
else
|
|
9
10
|
User.first
|
|
10
11
|
end
|
|
11
|
-
redirect_to
|
|
12
|
+
redirect_to "/"
|
|
12
13
|
end
|
|
13
14
|
|
|
14
15
|
def callback
|
|
15
|
-
render plain:
|
|
16
|
+
render plain: "ok"
|
|
16
17
|
end
|
|
17
18
|
end
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
class SemiProtectedResourcesController < ApplicationController
|
|
2
4
|
before_action :doorkeeper_authorize!, only: :index
|
|
3
5
|
|
|
4
6
|
def index
|
|
5
|
-
render plain:
|
|
7
|
+
render plain: "protected index"
|
|
6
8
|
end
|
|
7
9
|
|
|
8
10
|
def show
|
|
9
|
-
render plain:
|
|
11
|
+
render plain: "non protected show"
|
|
10
12
|
end
|
|
11
13
|
end
|
|
@@ -1,6 +1,17 @@
|
|
|
1
|
-
require File.expand_path('
|
|
1
|
+
require File.expand_path('boot', __dir__)
|
|
2
2
|
|
|
3
|
-
require
|
|
3
|
+
require "rails"
|
|
4
|
+
|
|
5
|
+
%w[
|
|
6
|
+
action_controller/railtie
|
|
7
|
+
action_view/railtie
|
|
8
|
+
sprockets/railtie
|
|
9
|
+
].each do |railtie|
|
|
10
|
+
begin
|
|
11
|
+
require railtie
|
|
12
|
+
rescue LoadError
|
|
13
|
+
end
|
|
14
|
+
end
|
|
4
15
|
|
|
5
16
|
Bundler.require(*Rails.groups)
|
|
6
17
|
|
|
@@ -16,6 +27,19 @@ require "#{orm}/railtie"
|
|
|
16
27
|
|
|
17
28
|
module Dummy
|
|
18
29
|
class Application < Rails::Application
|
|
30
|
+
if Rails.gem_version < Gem::Version.new('5.1')
|
|
31
|
+
config.action_controller.per_form_csrf_tokens = true
|
|
32
|
+
config.action_controller.forgery_protection_origin_check = true
|
|
33
|
+
|
|
34
|
+
ActiveSupport.to_time_preserves_timezone = true
|
|
35
|
+
|
|
36
|
+
config.active_record.belongs_to_required_by_default = true
|
|
37
|
+
|
|
38
|
+
config.ssl_options = { hsts: { subdomains: true } }
|
|
39
|
+
else
|
|
40
|
+
config.load_defaults "#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}"
|
|
41
|
+
end
|
|
42
|
+
|
|
19
43
|
# Settings in config/environments/* take precedence over those specified here.
|
|
20
44
|
# Application configuration should go into files in config/initializers
|
|
21
45
|
# -- all .rb files in that directory are automatically loaded.
|
data/spec/dummy/config/boot.rb
CHANGED
|
@@ -2,8 +2,6 @@ require 'rubygems'
|
|
|
2
2
|
require 'bundler/setup'
|
|
3
3
|
|
|
4
4
|
orm = ENV['BUNDLE_GEMFILE'].match(/Gemfile\.(.+)\.rb/)
|
|
5
|
-
unless defined?(DOORKEEPER_ORM)
|
|
6
|
-
DOORKEEPER_ORM = (orm && orm[1]) || :active_record
|
|
7
|
-
end
|
|
5
|
+
DOORKEEPER_ORM = (orm && orm[1]) || :active_record unless defined?(DOORKEEPER_ORM)
|
|
8
6
|
|
|
9
|
-
$LOAD_PATH.unshift File.expand_path('
|
|
7
|
+
$LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
Dummy::Application.configure do
|
|
2
4
|
# Settings specified here will take precedence over those in config/application.rb
|
|
3
5
|
|
|
@@ -8,7 +10,7 @@ Dummy::Application.configure do
|
|
|
8
10
|
config.cache_classes = true
|
|
9
11
|
|
|
10
12
|
config.assets.enabled = true
|
|
11
|
-
config.assets.version =
|
|
13
|
+
config.assets.version = "1.0"
|
|
12
14
|
config.assets.digest = false
|
|
13
15
|
|
|
14
16
|
# Do not eager load code on boot. This avoids loading your whole application
|
|
@@ -24,7 +26,7 @@ Dummy::Application.configure do
|
|
|
24
26
|
config.action_dispatch.show_exceptions = false
|
|
25
27
|
|
|
26
28
|
# Disable request forgery protection in test environment
|
|
27
|
-
config.action_controller.allow_forgery_protection
|
|
29
|
+
config.action_controller.allow_forgery_protection = false
|
|
28
30
|
|
|
29
31
|
# Tell Action Mailer not to deliver emails to the real world.
|
|
30
32
|
# The :test delivery method accumulates sent emails in the
|