doorkeeper 4.2.5 → 5.0.0.rc1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +2 -1
- data/.hound.yml +2 -13
- data/.rubocop.yml +17 -0
- data/.travis.yml +19 -4
- data/Appraisals +8 -4
- data/CODE_OF_CONDUCT.md +46 -0
- data/Gemfile +1 -1
- data/NEWS.md +81 -0
- data/README.md +169 -34
- data/RELEASING.md +5 -12
- data/Rakefile +6 -0
- data/SECURITY.md +15 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +2 -5
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +47 -13
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +15 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +15 -7
- data/app/helpers/doorkeeper/dashboard_helper.rb +8 -6
- data/app/validators/redirect_uri_validator.rb +13 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +31 -19
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +18 -6
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +8 -5
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +5 -1
- data/app/views/doorkeeper/authorized_applications/index.html.erb +0 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +18 -6
- data/doorkeeper.gemspec +6 -6
- data/gemfiles/rails_4_2.gemfile +6 -4
- data/gemfiles/rails_5_0.gemfile +4 -4
- data/gemfiles/rails_5_1.gemfile +6 -7
- data/gemfiles/rails_5_2.gemfile +12 -0
- data/gemfiles/rails_master.gemfile +14 -0
- data/lib/doorkeeper/config.rb +107 -68
- data/lib/doorkeeper/engine.rb +7 -3
- data/lib/doorkeeper/errors.rb +20 -5
- data/lib/doorkeeper/grape/helpers.rb +14 -9
- data/lib/doorkeeper/helpers/controller.rb +16 -22
- data/lib/doorkeeper/models/access_grant_mixin.rb +52 -23
- data/lib/doorkeeper/models/access_token_mixin.rb +51 -52
- data/lib/doorkeeper/models/application_mixin.rb +16 -30
- data/lib/doorkeeper/models/concerns/expirable.rb +7 -5
- data/lib/doorkeeper/models/concerns/orderable.rb +13 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +41 -20
- data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
- data/lib/doorkeeper/oauth/base_request.rb +22 -7
- data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +2 -2
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -2
- data/lib/doorkeeper/oauth/error.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +11 -4
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +15 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +3 -4
- data/lib/doorkeeper/oauth/password_access_token_request.rb +8 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +7 -1
- data/lib/doorkeeper/oauth/scopes.rb +19 -9
- data/lib/doorkeeper/oauth/token.rb +6 -3
- data/lib/doorkeeper/oauth/token_introspection.rb +128 -0
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -0
- data/lib/doorkeeper/orm/active_record/access_token.rb +21 -20
- data/lib/doorkeeper/orm/active_record/application.rb +34 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +21 -8
- data/lib/doorkeeper/rails/helpers.rb +7 -10
- data/lib/doorkeeper/rails/routes.rb +21 -7
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +6 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request/password.rb +1 -11
- data/lib/doorkeeper/request.rb +29 -23
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +14 -1
- data/lib/doorkeeper.rb +6 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +26 -12
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -9
- data/lib/generators/doorkeeper/migration_generator.rb +26 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +31 -20
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/{add_owner_to_application_migration.rb → add_owner_to_application_migration.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/{add_previous_refresh_token_to_access_tokens.rb → add_previous_refresh_token_to_access_tokens.rb.erb} +1 -1
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +88 -10
- data/lib/generators/doorkeeper/templates/{migration.rb → migration.rb.erb} +2 -1
- data/lib/generators/doorkeeper/views_generator.rb +3 -1
- data/spec/controllers/application_metal_controller_spec.rb +50 -0
- data/spec/controllers/applications_controller_spec.rb +141 -17
- data/spec/controllers/authorizations_controller_spec.rb +277 -27
- data/spec/controllers/protected_resources_controller_spec.rb +44 -35
- data/spec/controllers/token_info_controller_spec.rb +17 -21
- data/spec/controllers/tokens_controller_spec.rb +142 -10
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/config/environments/test.rb +4 -5
- data/spec/dummy/config/initializers/doorkeeper.rb +18 -1
- data/spec/dummy/config/initializers/{active_record_belongs_to_required_by_default.rb → new_framework_defaults.rb} +5 -1
- data/spec/dummy/config/initializers/secret_token.rb +0 -1
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
- data/spec/dummy/db/schema.rb +38 -37
- data/spec/factories.rb +1 -1
- data/spec/generators/application_owner_generator_spec.rb +25 -6
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/migration_generator_spec.rb +25 -4
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +57 -0
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +135 -0
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +2 -2
- data/spec/lib/config_spec.rb +170 -22
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -4
- data/spec/lib/models/revocable_spec.rb +2 -4
- data/spec/lib/models/scopes_spec.rb +0 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
- data/spec/lib/oauth/authorization_code_request_spec.rb +63 -13
- data/spec/lib/oauth/base_request_spec.rb +19 -10
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +5 -5
- data/spec/lib/oauth/client_credentials/creator_spec.rb +6 -2
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
- data/spec/lib/oauth/client_credentials_integration_spec.rb +2 -2
- data/spec/lib/oauth/client_credentials_request_spec.rb +4 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +5 -5
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +1 -3
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -3
- data/spec/lib/oauth/invalid_token_response_spec.rb +2 -5
- data/spec/lib/oauth/password_access_token_request_spec.rb +46 -5
- data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
- data/spec/lib/oauth/refresh_token_request_spec.rb +30 -14
- data/spec/lib/oauth/scopes_spec.rb +28 -4
- data/spec/lib/oauth/token_request_spec.rb +10 -13
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +37 -14
- data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +10 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +2 -2
- data/spec/models/doorkeeper/access_token_spec.rb +118 -60
- data/spec/models/doorkeeper/application_spec.rb +101 -23
- data/spec/requests/applications/applications_request_spec.rb +94 -6
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +1 -1
- data/spec/requests/endpoints/token_spec.rb +15 -6
- data/spec/requests/flows/authorization_code_errors_spec.rb +12 -2
- data/spec/requests/flows/authorization_code_spec.rb +198 -1
- data/spec/requests/flows/client_credentials_spec.rb +73 -5
- data/spec/requests/flows/implicit_grant_errors_spec.rb +3 -3
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +160 -24
- data/spec/requests/flows/refresh_token_spec.rb +6 -6
- data/spec/requests/flows/revoke_token_spec.rb +26 -26
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +2 -2
- data/spec/requests/protected_resources/private_api_spec.rb +2 -2
- data/spec/routing/custom_controller_routes_spec.rb +63 -7
- data/spec/routing/default_routes_spec.rb +6 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -64
- data/spec/support/dependencies/factory_bot.rb +2 -0
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/access_token_request_helper.rb +1 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/model_helper.rb +9 -4
- data/spec/support/helpers/request_spec_helper.rb +10 -6
- data/spec/support/helpers/url_helper.rb +15 -10
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/support/shared/controllers_shared_context.rb +2 -6
- data/spec/support/shared/models_shared_examples.rb +4 -4
- data/spec/validators/redirect_uri_validator_spec.rb +58 -7
- data/spec/version/version_spec.rb +15 -0
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +74 -34
- data/spec/controllers/application_metal_controller.rb +0 -10
- data/spec/support/dependencies/factory_girl.rb +0 -2
|
@@ -1,36 +1,27 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Doorkeeper::TokenInfoController do
|
|
4
|
-
describe 'when requesting
|
|
5
|
-
let(:doorkeeper_token) {
|
|
6
|
-
|
|
7
|
-
before(:each) do
|
|
8
|
-
allow(controller).to receive(:doorkeeper_token) { doorkeeper_token }
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
def do_get
|
|
12
|
-
get :show
|
|
13
|
-
end
|
|
4
|
+
describe 'when requesting token info with valid token' do
|
|
5
|
+
let(:doorkeeper_token) { FactoryBot.create(:access_token) }
|
|
14
6
|
|
|
15
7
|
describe 'successful request' do
|
|
8
|
+
it 'responds with token info' do
|
|
9
|
+
get :show, params: { access_token: doorkeeper_token.token }
|
|
16
10
|
|
|
17
|
-
it 'responds with tokeninfo' do
|
|
18
|
-
do_get
|
|
19
11
|
expect(response.body).to eq(doorkeeper_token.to_json)
|
|
20
12
|
end
|
|
21
13
|
|
|
22
14
|
it 'responds with a 200 status' do
|
|
23
|
-
|
|
15
|
+
get :show, params: { access_token: doorkeeper_token.token }
|
|
16
|
+
|
|
24
17
|
expect(response.status).to eq 200
|
|
25
18
|
end
|
|
26
19
|
end
|
|
27
20
|
|
|
28
21
|
describe 'invalid token response' do
|
|
29
|
-
before(:each) do
|
|
30
|
-
allow(controller).to receive(:doorkeeper_token).and_return(nil)
|
|
31
|
-
end
|
|
32
22
|
it 'responds with 401 when doorkeeper_token is not valid' do
|
|
33
|
-
|
|
23
|
+
get :show
|
|
24
|
+
|
|
34
25
|
expect(response.status).to eq 401
|
|
35
26
|
expect(response.headers['WWW-Authenticate']).to match(/^Bearer/)
|
|
36
27
|
end
|
|
@@ -38,14 +29,19 @@ describe Doorkeeper::TokenInfoController do
|
|
|
38
29
|
it 'responds with 401 when doorkeeper_token is invalid, expired or revoked' do
|
|
39
30
|
allow(controller).to receive(:doorkeeper_token).and_return(doorkeeper_token)
|
|
40
31
|
allow(doorkeeper_token).to receive(:accessible?).and_return(false)
|
|
41
|
-
|
|
32
|
+
|
|
33
|
+
get :show
|
|
34
|
+
|
|
42
35
|
expect(response.status).to eq 401
|
|
43
36
|
expect(response.headers['WWW-Authenticate']).to match(/^Bearer/)
|
|
44
37
|
end
|
|
45
38
|
|
|
46
39
|
it 'responds body message for error' do
|
|
47
|
-
|
|
48
|
-
|
|
40
|
+
get :show
|
|
41
|
+
|
|
42
|
+
expect(response.body).to eq(
|
|
43
|
+
Doorkeeper::OAuth::ErrorResponse.new(name: :invalid_request, status: :unauthorized).body.to_json
|
|
44
|
+
)
|
|
49
45
|
end
|
|
50
46
|
end
|
|
51
47
|
end
|
|
@@ -1,14 +1,9 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Doorkeeper::TokensController do
|
|
4
4
|
describe 'when authorization has succeeded' do
|
|
5
|
-
let :token
|
|
6
|
-
double(:token, authorize: true)
|
|
7
|
-
end
|
|
5
|
+
let(:token) { double(:token, authorize: true) }
|
|
8
6
|
|
|
9
|
-
before do
|
|
10
|
-
allow(controller).to receive(:token) { token }
|
|
11
|
-
end
|
|
12
7
|
|
|
13
8
|
it 'returns the authorization' do
|
|
14
9
|
skip 'verify need of these specs'
|
|
@@ -38,7 +33,7 @@ describe Doorkeeper::TokensController do
|
|
|
38
33
|
allow(I18n).to receive(:translate).
|
|
39
34
|
with(
|
|
40
35
|
custom_message,
|
|
41
|
-
hash_including(scope: [
|
|
36
|
+
hash_including(scope: %i[doorkeeper errors messages]),
|
|
42
37
|
).
|
|
43
38
|
and_return('Authorization custom message')
|
|
44
39
|
|
|
@@ -57,7 +52,7 @@ describe Doorkeeper::TokensController do
|
|
|
57
52
|
}
|
|
58
53
|
expect(response.status).to eq 401
|
|
59
54
|
expect(response.headers['WWW-Authenticate']).to match(/Bearer/)
|
|
60
|
-
expect(JSON.
|
|
55
|
+
expect(JSON.parse(response.body)).to eq expected_response_body
|
|
61
56
|
end
|
|
62
57
|
end
|
|
63
58
|
|
|
@@ -79,10 +74,147 @@ describe Doorkeeper::TokensController do
|
|
|
79
74
|
expect(strategy).to receive(:authorize).once
|
|
80
75
|
allow(controller).to receive(:strategy) { strategy }
|
|
81
76
|
allow(controller).to receive(:create) do
|
|
82
|
-
controller.send :authorize_response
|
|
77
|
+
2.times { controller.send :authorize_response }
|
|
78
|
+
controller.render json: {}, status: :ok
|
|
83
79
|
end
|
|
84
80
|
|
|
85
81
|
post :create
|
|
86
82
|
end
|
|
87
83
|
end
|
|
84
|
+
|
|
85
|
+
describe 'when requested token introspection' do
|
|
86
|
+
context 'authorized using Bearer token' do
|
|
87
|
+
let(:client) { FactoryBot.create(:application) }
|
|
88
|
+
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
89
|
+
|
|
90
|
+
it 'responds with full token introspection' do
|
|
91
|
+
request.headers['Authorization'] = "Bearer #{access_token.token}"
|
|
92
|
+
|
|
93
|
+
post :introspect, params: { token: access_token.token }
|
|
94
|
+
|
|
95
|
+
should_have_json 'active', true
|
|
96
|
+
expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
context 'authorized using Client Authentication' do
|
|
101
|
+
let(:client) { FactoryBot.create(:application) }
|
|
102
|
+
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
103
|
+
|
|
104
|
+
it 'responds with full token introspection' do
|
|
105
|
+
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
106
|
+
|
|
107
|
+
post :introspect, params: { token: access_token.token }
|
|
108
|
+
|
|
109
|
+
should_have_json 'active', true
|
|
110
|
+
expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
|
|
111
|
+
should_have_json 'client_id', client.uid
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
context 'public access token' do
|
|
116
|
+
let(:client) { FactoryBot.create(:application) }
|
|
117
|
+
let(:access_token) { FactoryBot.create(:access_token, application: nil) }
|
|
118
|
+
|
|
119
|
+
it 'responds with full token introspection' do
|
|
120
|
+
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
121
|
+
|
|
122
|
+
post :introspect, params: { token: access_token.token }
|
|
123
|
+
|
|
124
|
+
should_have_json 'active', true
|
|
125
|
+
expect(json_response).to include('client_id', 'token_type', 'exp', 'iat')
|
|
126
|
+
should_have_json 'client_id', nil
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
context 'token was issued to a different client than is making this request' do
|
|
131
|
+
let(:client) { FactoryBot.create(:application) }
|
|
132
|
+
let(:different_client) { FactoryBot.create(:application) }
|
|
133
|
+
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
134
|
+
|
|
135
|
+
it 'responds with only active state' do
|
|
136
|
+
request.headers['Authorization'] = basic_auth_header_for_client(different_client)
|
|
137
|
+
|
|
138
|
+
post :introspect, params: { token: access_token.token }
|
|
139
|
+
|
|
140
|
+
expect(response).to be_successful
|
|
141
|
+
|
|
142
|
+
should_have_json 'active', false
|
|
143
|
+
expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
context 'using invalid credentials to authorize' do
|
|
148
|
+
let(:client) { double(uid: '123123', secret: '666999') }
|
|
149
|
+
let(:access_token) { FactoryBot.create(:access_token) }
|
|
150
|
+
|
|
151
|
+
it 'responds with invalid_client error' do
|
|
152
|
+
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
153
|
+
|
|
154
|
+
post :introspect, params: { token: access_token.token }
|
|
155
|
+
|
|
156
|
+
expect(response).not_to be_successful
|
|
157
|
+
response_status_should_be 401
|
|
158
|
+
|
|
159
|
+
should_not_have_json 'active'
|
|
160
|
+
should_have_json 'error', 'invalid_client'
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
context 'using wrong token value' do
|
|
165
|
+
let(:client) { FactoryBot.create(:application) }
|
|
166
|
+
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
|
167
|
+
|
|
168
|
+
it 'responds with only active state' do
|
|
169
|
+
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
170
|
+
|
|
171
|
+
post :introspect, params: { token: SecureRandom.hex(16) }
|
|
172
|
+
|
|
173
|
+
should_have_json 'active', false
|
|
174
|
+
expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
|
|
175
|
+
end
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
context 'when requested Access Token expired' do
|
|
179
|
+
let(:client) { FactoryBot.create(:application) }
|
|
180
|
+
let(:access_token) { FactoryBot.create(:access_token, application: client, created_at: 1.year.ago) }
|
|
181
|
+
|
|
182
|
+
it 'responds with only active state' do
|
|
183
|
+
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
184
|
+
|
|
185
|
+
post :introspect, params: { token: access_token.token }
|
|
186
|
+
|
|
187
|
+
should_have_json 'active', false
|
|
188
|
+
expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
context 'when requested Access Token revoked' do
|
|
193
|
+
let(:client) { FactoryBot.create(:application) }
|
|
194
|
+
let(:access_token) { FactoryBot.create(:access_token, application: client, revoked_at: 1.year.ago) }
|
|
195
|
+
|
|
196
|
+
it 'responds with only active state' do
|
|
197
|
+
request.headers['Authorization'] = basic_auth_header_for_client(client)
|
|
198
|
+
|
|
199
|
+
post :introspect, params: { token: access_token.token }
|
|
200
|
+
|
|
201
|
+
should_have_json 'active', false
|
|
202
|
+
expect(json_response).not_to include('client_id', 'token_type', 'exp', 'iat')
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
context 'unauthorized (no bearer token or client credentials)' do
|
|
207
|
+
let(:access_token) { FactoryBot.create(:access_token) }
|
|
208
|
+
|
|
209
|
+
it 'responds with invalid_request error' do
|
|
210
|
+
post :introspect, params: { token: access_token.token }
|
|
211
|
+
|
|
212
|
+
expect(response).not_to be_successful
|
|
213
|
+
response_status_should_be 401
|
|
214
|
+
|
|
215
|
+
should_not_have_json 'active'
|
|
216
|
+
should_have_json 'error', 'invalid_request'
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
88
220
|
end
|
|
@@ -7,6 +7,10 @@ Dummy::Application.configure do
|
|
|
7
7
|
# and recreated between test runs. Don't rely on the data there!
|
|
8
8
|
config.cache_classes = true
|
|
9
9
|
|
|
10
|
+
config.assets.enabled = true
|
|
11
|
+
config.assets.version = '1.0'
|
|
12
|
+
config.assets.digest = false
|
|
13
|
+
|
|
10
14
|
# Do not eager load code on boot. This avoids loading your whole application
|
|
11
15
|
# just for the purpose of running a single test. If you are using a tool that
|
|
12
16
|
# preloads Rails for running tests, you may have to set it to true.
|
|
@@ -36,9 +40,4 @@ Dummy::Application.configure do
|
|
|
36
40
|
config.active_support.deprecation = :stderr
|
|
37
41
|
|
|
38
42
|
config.eager_load = true
|
|
39
|
-
|
|
40
|
-
if DOORKEEPER_ORM == :active_record
|
|
41
|
-
config.active_record.table_name_prefix = TABLE_NAME_PREFIX.to_s
|
|
42
|
-
config.active_record.table_name_suffix = TABLE_NAME_SUFFIX.to_s
|
|
43
|
-
end
|
|
44
43
|
end
|
|
@@ -29,6 +29,12 @@ Doorkeeper.configure do
|
|
|
29
29
|
# Issue access tokens with refresh token (disabled by default)
|
|
30
30
|
use_refresh_token
|
|
31
31
|
|
|
32
|
+
# Forbids creating/updating applications with arbitrary scopes that are
|
|
33
|
+
# not in configuration, i.e. `default_scopes` or `optional_scopes`.
|
|
34
|
+
# (disabled by default)
|
|
35
|
+
#
|
|
36
|
+
# enforce_configured_scopes
|
|
37
|
+
|
|
32
38
|
# Provide support for an owner to be assigned to each registered application (disabled by default)
|
|
33
39
|
# Optional parameter confirmation: true (default false) if you want to enforce ownership of
|
|
34
40
|
# a registered application
|
|
@@ -82,7 +88,18 @@ Doorkeeper.configure do
|
|
|
82
88
|
# http://tools.ietf.org/html/rfc6819#section-4.4.2
|
|
83
89
|
# http://tools.ietf.org/html/rfc6819#section-4.4.3
|
|
84
90
|
#
|
|
85
|
-
# grant_flows %w
|
|
91
|
+
# grant_flows %w[authorization_code client_credentials]
|
|
92
|
+
|
|
93
|
+
# Hook into the strategies' request & response life-cycle in case your
|
|
94
|
+
# application needs advanced customization or logging:
|
|
95
|
+
#
|
|
96
|
+
# before_successful_strategy_response do |request|
|
|
97
|
+
# puts "BEFORE HOOK FIRED! #{request}"
|
|
98
|
+
# end
|
|
99
|
+
#
|
|
100
|
+
# after_successful_strategy_response do |request, response|
|
|
101
|
+
# puts "AFTER HOOK FIRED! #{request}, #{response}"
|
|
102
|
+
# end
|
|
86
103
|
|
|
87
104
|
# Under some circumstances you might want to have applications auto-approved,
|
|
88
105
|
# so that the user skips the authorization step.
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
# Require `belongs_to` associations by default. This is a new Rails 5.0
|
|
2
2
|
# default, so it is introduced as a configuration option to ensure that apps
|
|
3
3
|
# made on earlier versions of Rails are not affected when upgrading.
|
|
4
|
-
if Rails
|
|
4
|
+
if Rails::VERSION::MAJOR >= 5
|
|
5
5
|
Rails.application.config.active_record.belongs_to_required_by_default = true
|
|
6
|
+
|
|
7
|
+
if Rails::VERSION::MINOR >= 2
|
|
8
|
+
Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true
|
|
9
|
+
end
|
|
6
10
|
end
|
|
@@ -5,5 +5,4 @@
|
|
|
5
5
|
# Make sure the secret is at least 30 characters and all random,
|
|
6
6
|
# no regular words or you'll be exposed to dictionary attacks.
|
|
7
7
|
Dummy::Application.config.secret_key_base =
|
|
8
|
-
Dummy::Application.config.secret_token =
|
|
9
8
|
'c00157b5a1bb6181792f0f4a8a080485de7bab9987e6cf159dc74c4f0573345c1bfa713b5d756e1491fc0b098567e8a619e2f8d268eda86a20a720d05d633780'
|
data/spec/dummy/config/routes.rb
CHANGED
|
@@ -1,52 +1,13 @@
|
|
|
1
1
|
Rails.application.routes.draw do
|
|
2
2
|
use_doorkeeper
|
|
3
|
-
use_doorkeeper scope: 'scope'
|
|
4
3
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
controllers authorizations: 'custom_authorizations',
|
|
8
|
-
tokens: 'custom_authorizations',
|
|
9
|
-
applications: 'custom_authorizations',
|
|
10
|
-
token_info: 'custom_authorizations'
|
|
11
|
-
|
|
12
|
-
as authorizations: 'custom_auth',
|
|
13
|
-
tokens: 'custom_token',
|
|
14
|
-
token_info: 'custom_token_info'
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
scope 'space' do
|
|
19
|
-
use_doorkeeper do
|
|
20
|
-
controllers authorizations: 'custom_authorizations',
|
|
21
|
-
tokens: 'custom_authorizations',
|
|
22
|
-
applications: 'custom_authorizations',
|
|
23
|
-
token_info: 'custom_authorizations'
|
|
24
|
-
|
|
25
|
-
as authorizations: 'custom_auth',
|
|
26
|
-
tokens: 'custom_token',
|
|
27
|
-
token_info: 'custom_token_info'
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
scope 'outer_space' do
|
|
32
|
-
use_doorkeeper do
|
|
33
|
-
controllers authorizations: 'custom_authorizations',
|
|
34
|
-
tokens: 'custom_authorizations',
|
|
35
|
-
token_info: 'custom_authorizations'
|
|
36
|
-
|
|
37
|
-
as authorizations: 'custom_auth',
|
|
38
|
-
tokens: 'custom_token',
|
|
39
|
-
token_info: 'custom_token_info'
|
|
40
|
-
|
|
41
|
-
skip_controllers :tokens, :applications, :token_info
|
|
42
|
-
end
|
|
43
|
-
end
|
|
4
|
+
resources :semi_protected_resources
|
|
5
|
+
resources :full_protected_resources
|
|
44
6
|
|
|
45
7
|
get 'metal.json' => 'metal#index'
|
|
46
8
|
|
|
47
9
|
get '/callback', to: 'home#callback'
|
|
48
10
|
get '/sign_in', to: 'home#sign_in'
|
|
49
|
-
|
|
50
|
-
resources :full_protected_resources
|
|
11
|
+
|
|
51
12
|
root to: 'home#index'
|
|
52
13
|
end
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddOwnerToApplication < ActiveRecord::Migration[4.2]
|
|
2
4
|
def change
|
|
3
5
|
add_column :oauth_applications, :owner_id, :integer, null: true
|
|
4
6
|
add_column :oauth_applications, :owner_type, :string, null: true
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
class AddConfidentialToApplications < ActiveRecord::Migration[5.1]
|
|
4
|
+
def change
|
|
5
|
+
add_column(
|
|
6
|
+
:oauth_applications,
|
|
7
|
+
:confidential,
|
|
8
|
+
:boolean,
|
|
9
|
+
null: false,
|
|
10
|
+
default: true # maintaining backwards compatibility: require secrets
|
|
11
|
+
)
|
|
12
|
+
end
|
|
13
|
+
end
|
data/spec/dummy/db/schema.rb
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
# encoding: UTF-8
|
|
2
1
|
# This file is auto-generated from the current state of the database. Instead
|
|
3
2
|
# of editing this file, please use the migrations feature of Active Record to
|
|
4
3
|
# incrementally modify your database, and then regenerate this schema definition.
|
|
@@ -11,57 +10,59 @@
|
|
|
11
10
|
#
|
|
12
11
|
# It's strongly recommended that you check this file into your version control system.
|
|
13
12
|
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
|
13
|
+
ActiveRecord::Schema.define(version: 20180210183654) do
|
|
15
14
|
|
|
16
15
|
create_table "oauth_access_grants", force: :cascade do |t|
|
|
17
|
-
t.integer
|
|
18
|
-
t.integer
|
|
19
|
-
t.string
|
|
20
|
-
t.integer
|
|
21
|
-
t.text
|
|
22
|
-
t.datetime "created_at",
|
|
16
|
+
t.integer "resource_owner_id", null: false
|
|
17
|
+
t.integer "application_id", null: false
|
|
18
|
+
t.string "token", null: false
|
|
19
|
+
t.integer "expires_in", null: false
|
|
20
|
+
t.text "redirect_uri", null: false
|
|
21
|
+
t.datetime "created_at", null: false
|
|
23
22
|
t.datetime "revoked_at"
|
|
24
|
-
t.string
|
|
23
|
+
t.string "scopes"
|
|
24
|
+
unless ENV['WITHOUT_PKCE']
|
|
25
|
+
t.string "code_challenge"
|
|
26
|
+
t.string "code_challenge_method"
|
|
27
|
+
end
|
|
28
|
+
t.index ["token"], name: "index_oauth_access_grants_on_token", unique: true
|
|
25
29
|
end
|
|
26
30
|
|
|
27
|
-
add_index "oauth_access_grants", ["token"], name: "index_oauth_access_grants_on_token", unique: true
|
|
28
|
-
|
|
29
31
|
create_table "oauth_access_tokens", force: :cascade do |t|
|
|
30
|
-
t.integer
|
|
31
|
-
t.integer
|
|
32
|
-
t.string
|
|
33
|
-
t.string
|
|
34
|
-
t.integer
|
|
32
|
+
t.integer "resource_owner_id"
|
|
33
|
+
t.integer "application_id"
|
|
34
|
+
t.string "token", null: false
|
|
35
|
+
t.string "refresh_token"
|
|
36
|
+
t.integer "expires_in"
|
|
35
37
|
t.datetime "revoked_at"
|
|
36
|
-
t.datetime "created_at",
|
|
37
|
-
t.string
|
|
38
|
-
t.string
|
|
38
|
+
t.datetime "created_at", null: false
|
|
39
|
+
t.string "scopes"
|
|
40
|
+
t.string "previous_refresh_token", default: "", null: false
|
|
41
|
+
t.index ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
|
|
42
|
+
t.index ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
|
|
43
|
+
t.index ["token"], name: "index_oauth_access_tokens_on_token", unique: true
|
|
39
44
|
end
|
|
40
45
|
|
|
41
|
-
add_index "oauth_access_tokens", ["refresh_token"], name: "index_oauth_access_tokens_on_refresh_token", unique: true
|
|
42
|
-
add_index "oauth_access_tokens", ["resource_owner_id"], name: "index_oauth_access_tokens_on_resource_owner_id"
|
|
43
|
-
add_index "oauth_access_tokens", ["token"], name: "index_oauth_access_tokens_on_token", unique: true
|
|
44
|
-
|
|
45
46
|
create_table "oauth_applications", force: :cascade do |t|
|
|
46
|
-
t.string
|
|
47
|
-
t.string
|
|
48
|
-
t.string
|
|
49
|
-
t.text
|
|
50
|
-
t.string
|
|
51
|
-
t.datetime "created_at"
|
|
52
|
-
t.datetime "updated_at"
|
|
53
|
-
t.integer
|
|
54
|
-
t.string
|
|
47
|
+
t.string "name", null: false
|
|
48
|
+
t.string "uid", null: false
|
|
49
|
+
t.string "secret", null: false
|
|
50
|
+
t.text "redirect_uri", null: false
|
|
51
|
+
t.string "scopes", default: "", null: false
|
|
52
|
+
t.datetime "created_at", null: false
|
|
53
|
+
t.datetime "updated_at", null: false
|
|
54
|
+
t.integer "owner_id"
|
|
55
|
+
t.string "owner_type"
|
|
56
|
+
t.boolean "confidential", default: true, null: false
|
|
57
|
+
t.index ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type"
|
|
58
|
+
t.index ["uid"], name: "index_oauth_applications_on_uid", unique: true
|
|
55
59
|
end
|
|
56
60
|
|
|
57
|
-
add_index "oauth_applications", ["owner_id", "owner_type"], name: "index_oauth_applications_on_owner_id_and_owner_type"
|
|
58
|
-
add_index "oauth_applications", ["uid"], name: "index_oauth_applications_on_uid", unique: true
|
|
59
|
-
|
|
60
61
|
create_table "users", force: :cascade do |t|
|
|
61
|
-
t.string
|
|
62
|
+
t.string "name"
|
|
62
63
|
t.datetime "created_at"
|
|
63
64
|
t.datetime "updated_at"
|
|
64
|
-
t.string
|
|
65
|
+
t.string "password"
|
|
65
66
|
end
|
|
66
67
|
|
|
67
68
|
end
|
data/spec/factories.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
require 'generators/doorkeeper/application_owner_generator'
|
|
3
3
|
|
|
4
4
|
describe 'Doorkeeper::ApplicationOwnerGenerator' do
|
|
@@ -10,13 +10,32 @@ describe 'Doorkeeper::ApplicationOwnerGenerator' do
|
|
|
10
10
|
describe 'after running the generator' do
|
|
11
11
|
before :each do
|
|
12
12
|
prepare_destination
|
|
13
|
-
FileUtils.mkdir(::File.expand_path('config', Pathname(destination_root)))
|
|
14
|
-
FileUtils.copy_file(::File.expand_path('../templates/routes.rb', __FILE__), ::File.expand_path('config/routes.rb', Pathname.new(destination_root)))
|
|
15
|
-
run_generator
|
|
16
13
|
end
|
|
17
14
|
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
context 'pre Rails 5.0.0' do
|
|
16
|
+
it 'creates a migration with no version specifier' do
|
|
17
|
+
stub_const("ActiveRecord::VERSION::MAJOR", 4)
|
|
18
|
+
stub_const("ActiveRecord::VERSION::MINOR", 2)
|
|
19
|
+
|
|
20
|
+
run_generator
|
|
21
|
+
|
|
22
|
+
assert_migration 'db/migrate/add_owner_to_application.rb' do |migration|
|
|
23
|
+
assert migration.include?("ActiveRecord::Migration\n")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
context 'post Rails 5.0.0' do
|
|
29
|
+
it 'creates a migration with a version specifier' do
|
|
30
|
+
stub_const("ActiveRecord::VERSION::MAJOR", 5)
|
|
31
|
+
stub_const("ActiveRecord::VERSION::MINOR", 0)
|
|
32
|
+
|
|
33
|
+
run_generator
|
|
34
|
+
|
|
35
|
+
assert_migration 'db/migrate/add_owner_to_application.rb' do |migration|
|
|
36
|
+
assert migration.include?("ActiveRecord::Migration[5.0]\n")
|
|
37
|
+
end
|
|
38
|
+
end
|
|
20
39
|
end
|
|
21
40
|
end
|
|
22
41
|
end
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
require 'generators/doorkeeper/confidential_applications_generator'
|
|
5
|
+
|
|
6
|
+
describe 'Doorkeeper::ConfidentialApplicationsGenerator' do
|
|
7
|
+
include GeneratorSpec::TestCase
|
|
8
|
+
|
|
9
|
+
tests Doorkeeper::ConfidentialApplicationsGenerator
|
|
10
|
+
destination ::File.expand_path('../tmp/dummy', __FILE__)
|
|
11
|
+
|
|
12
|
+
describe 'after running the generator' do
|
|
13
|
+
before :each do
|
|
14
|
+
prepare_destination
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
context 'pre Rails 5.0.0' do
|
|
18
|
+
it 'creates a migration with no version specifier' do
|
|
19
|
+
stub_const("ActiveRecord::VERSION::MAJOR", 4)
|
|
20
|
+
stub_const("ActiveRecord::VERSION::MINOR", 2)
|
|
21
|
+
|
|
22
|
+
run_generator
|
|
23
|
+
|
|
24
|
+
assert_migration 'db/migrate/add_confidential_to_applications.rb' do |migration|
|
|
25
|
+
assert migration.include?("ActiveRecord::Migration\n")
|
|
26
|
+
assert migration.include?(':confidential')
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'post Rails 5.0.0' do
|
|
32
|
+
it 'creates a migration with a version specifier' do
|
|
33
|
+
stub_const("ActiveRecord::VERSION::MAJOR", 5)
|
|
34
|
+
stub_const("ActiveRecord::VERSION::MINOR", 0)
|
|
35
|
+
|
|
36
|
+
run_generator
|
|
37
|
+
|
|
38
|
+
assert_migration 'db/migrate/add_confidential_to_applications.rb' do |migration|
|
|
39
|
+
assert migration.include?("ActiveRecord::Migration[5.0]\n")
|
|
40
|
+
assert migration.include?(':confidential')
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|