doorkeeper 4.4.0 → 5.0.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 +4 -4
- data/.gitignore +1 -0
- data/.gitlab-ci.yml +16 -0
- data/.travis.yml +2 -0
- data/Appraisals +2 -2
- data/Gemfile +1 -1
- data/NEWS.md +67 -1
- data/README.md +92 -9
- data/Rakefile +6 -0
- data/UPGRADE.md +2 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +4 -3
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +42 -22
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +19 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +2 -6
- data/app/helpers/doorkeeper/dashboard_helper.rb +7 -7
- data/app/validators/redirect_uri_validator.rb +3 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +25 -24
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +17 -7
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +6 -6
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +12 -3
- data/doorkeeper.gemspec +18 -20
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/gemfiles/rails_master.gemfile +4 -1
- data/lib/doorkeeper/config.rb +77 -27
- data/lib/doorkeeper/engine.rb +4 -0
- data/lib/doorkeeper/errors.rb +2 -5
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +7 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +71 -0
- data/lib/doorkeeper/models/access_token_mixin.rb +40 -23
- 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 +36 -14
- data/lib/doorkeeper/oauth/authorization_code_request.rb +27 -2
- data/lib/doorkeeper/oauth/base_request.rb +20 -9
- data/lib/doorkeeper/oauth/client/credentials.rb +1 -1
- data/lib/doorkeeper/oauth/client.rb +0 -2
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +2 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -3
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -6
- data/lib/doorkeeper/oauth/client_credentials_request.rb +0 -4
- data/lib/doorkeeper/oauth/error_response.rb +11 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -1
- data/lib/doorkeeper/oauth/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/token.rb +5 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +2 -2
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/application.rb +22 -14
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +2 -0
- data/lib/doorkeeper/rails/helpers.rb +2 -4
- data/lib/doorkeeper/rails/routes.rb +13 -1
- 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/authorization_code.rb +0 -2
- data/lib/doorkeeper/request/client_credentials.rb +0 -2
- data/lib/doorkeeper/request/code.rb +0 -2
- data/lib/doorkeeper/request/password.rb +0 -2
- data/lib/doorkeeper/request/refresh_token.rb +0 -2
- data/lib/doorkeeper/request/token.rb +0 -2
- data/lib/doorkeeper/request.rb +28 -35
- data/lib/doorkeeper/version.rb +4 -24
- data/lib/doorkeeper.rb +19 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
- 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 +23 -18
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +76 -11
- 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 +126 -13
- data/spec/controllers/authorizations_controller_spec.rb +279 -17
- data/spec/controllers/protected_resources_controller_spec.rb +16 -16
- data/spec/controllers/token_info_controller_spec.rb +4 -12
- data/spec/controllers/tokens_controller_spec.rb +13 -15
- 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 +11 -1
- data/spec/dummy/config/initializers/new_framework_defaults.rb +4 -0
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/{20180210183654_add_confidential_to_application.rb → 20180210183654_add_confidential_to_applications.rb} +1 -1
- data/spec/dummy/db/schema.rb +36 -36
- data/spec/generators/application_owner_generator_spec.rb +1 -1
- 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 +1 -1
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +1 -1
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +88 -14
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +0 -2
- 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 +24 -2
- data/spec/lib/oauth/base_request_spec.rb +40 -2
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +1 -3
- data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
- 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 +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +4 -2
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +0 -2
- 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 +5 -2
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
- data/spec/lib/oauth/password_access_token_request_spec.rb +37 -2
- data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
- data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
- data/spec/lib/oauth/scopes_spec.rb +0 -3
- data/spec/lib/oauth/token_request_spec.rb +4 -5
- 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 +1 -1
- data/spec/models/doorkeeper/access_grant_spec.rb +44 -1
- data/spec/models/doorkeeper/access_token_spec.rb +66 -22
- data/spec/models/doorkeeper/application_spec.rb +14 -30
- data/spec/requests/applications/applications_request_spec.rb +134 -1
- 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 +7 -5
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_spec.rb +198 -2
- data/spec/requests/flows/client_credentials_spec.rb +46 -6
- data/spec/requests/flows/implicit_grant_errors_spec.rb +1 -1
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +56 -2
- data/spec/requests/flows/refresh_token_spec.rb +2 -2
- data/spec/requests/flows/revoke_token_spec.rb +11 -11
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +1 -1
- data/spec/routing/custom_controller_routes_spec.rb +59 -7
- data/spec/routing/default_routes_spec.rb +2 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -74
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/request_spec_helper.rb +10 -2
- data/spec/support/helpers/url_helper.rb +7 -3
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/validators/redirect_uri_validator_spec.rb +7 -1
- data/spec/version/version_spec.rb +3 -3
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +37 -33
- data/lib/generators/doorkeeper/add_client_confidentiality_generator.rb +0 -31
- data/lib/generators/doorkeeper/templates/add_confidential_to_application_migration.rb.erb +0 -11
- data/spec/controllers/application_metal_controller.rb +0 -10
- /data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
|
@@ -1,7 +1,99 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
describe ApplicationsController do
|
|
5
|
+
context 'JSON API' do
|
|
6
|
+
render_views
|
|
7
|
+
|
|
8
|
+
before do
|
|
9
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
10
|
+
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(->(*) { true })
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'creates an application' do
|
|
14
|
+
expect do
|
|
15
|
+
post :create, params: {
|
|
16
|
+
doorkeeper_application: {
|
|
17
|
+
name: 'Example',
|
|
18
|
+
redirect_uri: 'https://example.com'
|
|
19
|
+
}, format: :json
|
|
20
|
+
}
|
|
21
|
+
end.to change { Doorkeeper::Application.count }
|
|
22
|
+
|
|
23
|
+
expect(response).to be_successful
|
|
24
|
+
|
|
25
|
+
expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
|
|
26
|
+
|
|
27
|
+
expect(json_response['name']).to eq('Example')
|
|
28
|
+
expect(json_response['redirect_uri']).to eq('https://example.com')
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it 'returns validation errors on wrong create params' do
|
|
32
|
+
expect do
|
|
33
|
+
post :create, params: {
|
|
34
|
+
doorkeeper_application: {
|
|
35
|
+
name: 'Example'
|
|
36
|
+
}, format: :json
|
|
37
|
+
}
|
|
38
|
+
end.not_to change { Doorkeeper::Application.count }
|
|
39
|
+
|
|
40
|
+
expect(response).to have_http_status(422)
|
|
41
|
+
|
|
42
|
+
expect(json_response).to include('errors')
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'returns application info' do
|
|
46
|
+
application = FactoryBot.create(:application, name: 'Change me')
|
|
47
|
+
|
|
48
|
+
get :show, params: { id: application.id, format: :json }
|
|
49
|
+
|
|
50
|
+
expect(response).to be_successful
|
|
51
|
+
|
|
52
|
+
expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it 'updates application' do
|
|
56
|
+
application = FactoryBot.create(:application, name: 'Change me')
|
|
57
|
+
|
|
58
|
+
put :update, params: {
|
|
59
|
+
id: application.id,
|
|
60
|
+
doorkeeper_application: {
|
|
61
|
+
name: 'Example App',
|
|
62
|
+
redirect_uri: 'https://example.com'
|
|
63
|
+
}, format: :json
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
expect(application.reload.name).to eq 'Example App'
|
|
67
|
+
|
|
68
|
+
expect(json_response).to include('id', 'name', 'uid', 'secret', 'redirect_uri', 'scopes')
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it 'returns validation errors on wrong update params' do
|
|
72
|
+
application = FactoryBot.create(:application, name: 'Change me')
|
|
73
|
+
|
|
74
|
+
put :update, params: {
|
|
75
|
+
id: application.id,
|
|
76
|
+
doorkeeper_application: {
|
|
77
|
+
name: 'Example App',
|
|
78
|
+
redirect_uri: 'localhost:3000'
|
|
79
|
+
}, format: :json
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
expect(response).to have_http_status(422)
|
|
83
|
+
|
|
84
|
+
expect(json_response).to include('errors')
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it 'destroys an application' do
|
|
88
|
+
application = FactoryBot.create(:application)
|
|
89
|
+
|
|
90
|
+
delete :destroy, params: { id: application.id, format: :json }
|
|
91
|
+
|
|
92
|
+
expect(response).to have_http_status(204)
|
|
93
|
+
expect(Application.count).to be_zero
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
|
|
5
97
|
context 'when admin is not authenticated' do
|
|
6
98
|
before do
|
|
7
99
|
allow(Doorkeeper.configuration).to receive(:authenticate_admin).and_return(proc do
|
|
@@ -16,9 +108,13 @@ module Doorkeeper
|
|
|
16
108
|
|
|
17
109
|
it 'does not create application' do
|
|
18
110
|
expect do
|
|
19
|
-
post :create,
|
|
20
|
-
|
|
21
|
-
|
|
111
|
+
post :create,
|
|
112
|
+
params: {
|
|
113
|
+
doorkeeper_application: {
|
|
114
|
+
name: 'Example',
|
|
115
|
+
redirect_uri: 'https://example.com'
|
|
116
|
+
}
|
|
117
|
+
}
|
|
22
118
|
end.not_to change { Doorkeeper::Application.count }
|
|
23
119
|
end
|
|
24
120
|
end
|
|
@@ -34,34 +130,51 @@ module Doorkeeper
|
|
|
34
130
|
first_application = FactoryBot.create(:application)
|
|
35
131
|
second_application = FactoryBot.create(:application)
|
|
36
132
|
expect(Doorkeeper::Application).to receive(:ordered_by).and_call_original
|
|
133
|
+
|
|
37
134
|
get :index
|
|
135
|
+
|
|
38
136
|
expect(response.body).to have_selector("tbody tr:first-child#application_#{first_application.id}")
|
|
39
137
|
expect(response.body).to have_selector("tbody tr:last-child#application_#{second_application.id}")
|
|
40
138
|
end
|
|
41
139
|
|
|
42
140
|
it 'creates application' do
|
|
43
141
|
expect do
|
|
44
|
-
post :create,
|
|
45
|
-
|
|
46
|
-
|
|
142
|
+
post :create,
|
|
143
|
+
params: {
|
|
144
|
+
doorkeeper_application: {
|
|
145
|
+
name: 'Example',
|
|
146
|
+
redirect_uri: 'https://example.com'
|
|
147
|
+
}
|
|
148
|
+
}
|
|
47
149
|
end.to change { Doorkeeper::Application.count }.by(1)
|
|
150
|
+
|
|
48
151
|
expect(response).to be_redirect
|
|
49
152
|
end
|
|
50
153
|
|
|
51
154
|
it 'does not allow mass assignment of uid or secret' do
|
|
52
155
|
application = FactoryBot.create(:application)
|
|
53
|
-
put :update,
|
|
54
|
-
|
|
55
|
-
|
|
156
|
+
put :update,
|
|
157
|
+
params: {
|
|
158
|
+
id: application.id,
|
|
159
|
+
doorkeeper_application: {
|
|
160
|
+
uid: '1A2B3C4D',
|
|
161
|
+
secret: '1A2B3C4D'
|
|
162
|
+
}
|
|
163
|
+
}
|
|
56
164
|
|
|
57
165
|
expect(application.reload.uid).not_to eq '1A2B3C4D'
|
|
58
166
|
end
|
|
59
167
|
|
|
60
168
|
it 'updates application' do
|
|
61
169
|
application = FactoryBot.create(:application)
|
|
62
|
-
put :update,
|
|
63
|
-
|
|
64
|
-
|
|
170
|
+
put :update,
|
|
171
|
+
params: {
|
|
172
|
+
id: application.id, doorkeeper_application: {
|
|
173
|
+
name: 'Example',
|
|
174
|
+
redirect_uri: 'https://example.com'
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
65
178
|
expect(application.reload.name).to eq 'Example'
|
|
66
179
|
end
|
|
67
180
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
4
4
|
include AuthorizationRequestHelper
|
|
@@ -6,7 +6,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
6
6
|
if Rails::VERSION::MAJOR >= 5
|
|
7
7
|
class ActionDispatch::TestResponse
|
|
8
8
|
def query_params
|
|
9
|
-
@
|
|
9
|
+
@query_params ||= begin
|
|
10
10
|
fragment = URI.parse(location).fragment
|
|
11
11
|
Rack::Utils.parse_query(fragment)
|
|
12
12
|
end
|
|
@@ -15,7 +15,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
15
15
|
else
|
|
16
16
|
class ActionController::TestResponse
|
|
17
17
|
def query_params
|
|
18
|
-
@
|
|
18
|
+
@query_params ||= begin
|
|
19
19
|
fragment = URI.parse(location).fragment
|
|
20
20
|
Rack::Utils.parse_query(fragment)
|
|
21
21
|
end
|
|
@@ -34,11 +34,14 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
34
34
|
before do
|
|
35
35
|
allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["implicit"])
|
|
36
36
|
allow(controller).to receive(:current_resource_owner).and_return(user)
|
|
37
|
+
allow(Doorkeeper.configuration).to receive(:custom_access_token_expires_in).and_return(proc { |context|
|
|
38
|
+
context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
|
|
39
|
+
})
|
|
37
40
|
end
|
|
38
41
|
|
|
39
42
|
describe 'POST #create' do
|
|
40
43
|
before do
|
|
41
|
-
post :create, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
|
|
44
|
+
post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
|
|
42
45
|
end
|
|
43
46
|
|
|
44
47
|
it 'redirects after authorization' do
|
|
@@ -54,11 +57,11 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
54
57
|
end
|
|
55
58
|
|
|
56
59
|
it 'includes token type in fragment' do
|
|
57
|
-
expect(response.query_params['token_type']).to eq('
|
|
60
|
+
expect(response.query_params['token_type']).to eq('Bearer')
|
|
58
61
|
end
|
|
59
62
|
|
|
60
63
|
it 'includes token expiration in fragment' do
|
|
61
|
-
expect(response.query_params['expires_in'].to_i).to eq(
|
|
64
|
+
expect(response.query_params['expires_in'].to_i).to eq(1234)
|
|
62
65
|
end
|
|
63
66
|
|
|
64
67
|
it 'issues the token for the current client' do
|
|
@@ -70,10 +73,48 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
70
73
|
end
|
|
71
74
|
end
|
|
72
75
|
|
|
76
|
+
describe "POST #create in API mode" do
|
|
77
|
+
before do
|
|
78
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
79
|
+
post :create, params: { client_id: client.uid, response_type: "token", redirect_uri: client.redirect_uri }
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
|
83
|
+
let(:redirect_uri) { response_json_body["redirect_uri"] }
|
|
84
|
+
|
|
85
|
+
it "renders success after authorization" do
|
|
86
|
+
expect(response).to be_successful
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "renders correct redirect uri" do
|
|
90
|
+
expect(redirect_uri).to match(/^#{client.redirect_uri}/)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "includes access token in fragment" do
|
|
94
|
+
expect(redirect_uri.match(/access_token=([a-f0-9]+)&?/)[1]).to eq(Doorkeeper::AccessToken.first.token)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "includes token type in fragment" do
|
|
98
|
+
expect(redirect_uri.match(/token_type=(\w+)&?/)[1]).to eq "Bearer"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "includes token expiration in fragment" do
|
|
102
|
+
expect(redirect_uri.match(/expires_in=(\d+)&?/)[1].to_i).to eq 1234
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "issues the token for the current client" do
|
|
106
|
+
expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "issues the token for the current resource owner" do
|
|
110
|
+
expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
73
114
|
describe 'POST #create with errors' do
|
|
74
115
|
before do
|
|
75
116
|
default_scopes_exist :public
|
|
76
|
-
post :create, client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri
|
|
117
|
+
post :create, params: { client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri }
|
|
77
118
|
end
|
|
78
119
|
|
|
79
120
|
it 'redirects after authorization' do
|
|
@@ -81,7 +122,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
81
122
|
end
|
|
82
123
|
|
|
83
124
|
it 'redirects to client redirect uri' do
|
|
84
|
-
expect(response.location).to match(
|
|
125
|
+
expect(response.location).to match(/^#{client.redirect_uri}/)
|
|
85
126
|
end
|
|
86
127
|
|
|
87
128
|
it 'does not include access token in fragment' do
|
|
@@ -101,12 +142,47 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
101
142
|
end
|
|
102
143
|
end
|
|
103
144
|
|
|
145
|
+
describe 'POST #create in API mode with errors' do
|
|
146
|
+
before do
|
|
147
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
148
|
+
default_scopes_exist :public
|
|
149
|
+
post :create, params: { client_id: client.uid, response_type: 'token', scope: 'invalid', redirect_uri: client.redirect_uri }
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
|
153
|
+
let(:redirect_uri) { response_json_body['redirect_uri'] }
|
|
154
|
+
|
|
155
|
+
it 'renders 400 error' do
|
|
156
|
+
expect(response.status).to eq 401
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it 'includes correct redirect URI' do
|
|
160
|
+
expect(redirect_uri).to match(/^#{client.redirect_uri}/)
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
it 'does not include access token in fragment' do
|
|
164
|
+
expect(redirect_uri.match(/access_token=([a-f0-9]+)&?/)).to be_nil
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
it 'includes error in redirect uri' do
|
|
168
|
+
expect(redirect_uri.match(/error=([a-z_]+)&?/)[1]).to eq 'invalid_scope'
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
it 'includes error description in redirect uri' do
|
|
172
|
+
expect(redirect_uri.match(/error_description=(.+)&?/)[1]).to_not be_nil
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it 'does not issue any access token' do
|
|
176
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
|
177
|
+
end
|
|
178
|
+
end
|
|
179
|
+
|
|
104
180
|
describe 'POST #create with application already authorized' do
|
|
105
181
|
before do
|
|
106
182
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
|
107
183
|
|
|
108
184
|
access_token.save!
|
|
109
|
-
post :create, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
|
|
185
|
+
post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
|
|
110
186
|
end
|
|
111
187
|
|
|
112
188
|
it 'returns the existing access token in a fragment' do
|
|
@@ -118,13 +194,47 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
118
194
|
end
|
|
119
195
|
end
|
|
120
196
|
|
|
197
|
+
describe 'POST #create with callbacks' do
|
|
198
|
+
after do
|
|
199
|
+
client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
describe 'when successful' do
|
|
203
|
+
after do
|
|
204
|
+
post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it 'should call :before_successful_authorization callback' do
|
|
208
|
+
expect(Doorkeeper.configuration).to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
it 'should call :after_successful_authorization callback' do
|
|
212
|
+
expect(Doorkeeper.configuration).to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
describe 'with errors' do
|
|
217
|
+
after do
|
|
218
|
+
post :create, params: { client_id: client.uid, response_type: 'token', redirect_uri: 'bad_uri' }
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
it 'should not call :before_successful_authorization callback' do
|
|
222
|
+
expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
it 'should not call :after_successful_authorization callback' do
|
|
226
|
+
expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|
|
230
|
+
|
|
121
231
|
describe 'GET #new token request with native url and skip_authorization true' do
|
|
122
232
|
before do
|
|
123
233
|
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
|
|
124
234
|
true
|
|
125
235
|
end)
|
|
126
236
|
client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
|
|
127
|
-
get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
|
|
237
|
+
get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
|
|
128
238
|
end
|
|
129
239
|
|
|
130
240
|
it 'should redirect immediately' do
|
|
@@ -143,13 +253,12 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
143
253
|
|
|
144
254
|
describe 'GET #new code request with native url and skip_authorization true' do
|
|
145
255
|
before do
|
|
146
|
-
allow(Doorkeeper.configuration).to receive(:grant_flows).
|
|
147
|
-
and_return(%w[authorization_code])
|
|
256
|
+
allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(%w[authorization_code])
|
|
148
257
|
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
|
|
149
258
|
true
|
|
150
259
|
end)
|
|
151
260
|
client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
|
|
152
|
-
get :new, client_id: client.uid, response_type: 'code', redirect_uri: client.redirect_uri
|
|
261
|
+
get :new, params: { client_id: client.uid, response_type: 'code', redirect_uri: client.redirect_uri }
|
|
153
262
|
end
|
|
154
263
|
|
|
155
264
|
it 'should redirect immediately' do
|
|
@@ -171,7 +280,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
171
280
|
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
|
|
172
281
|
true
|
|
173
282
|
end)
|
|
174
|
-
get :new, client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri
|
|
283
|
+
get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
|
|
175
284
|
end
|
|
176
285
|
|
|
177
286
|
it 'should redirect immediately' do
|
|
@@ -184,11 +293,11 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
184
293
|
end
|
|
185
294
|
|
|
186
295
|
it 'includes token type in fragment' do
|
|
187
|
-
expect(response.query_params['token_type']).to eq('
|
|
296
|
+
expect(response.query_params['token_type']).to eq('Bearer')
|
|
188
297
|
end
|
|
189
298
|
|
|
190
299
|
it 'includes token expiration in fragment' do
|
|
191
|
-
expect(response.query_params['expires_in'].to_i).to eq(
|
|
300
|
+
expect(response.query_params['expires_in'].to_i).to eq(1234)
|
|
192
301
|
end
|
|
193
302
|
|
|
194
303
|
it 'issues the token for the current client' do
|
|
@@ -200,10 +309,72 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
200
309
|
end
|
|
201
310
|
end
|
|
202
311
|
|
|
312
|
+
describe 'GET #new in API mode' do
|
|
313
|
+
before do
|
|
314
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
315
|
+
get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
it 'should render success' do
|
|
319
|
+
expect(response).to be_successful
|
|
320
|
+
end
|
|
321
|
+
|
|
322
|
+
it "sets status to pre-authorization" do
|
|
323
|
+
expect(json_response["status"]).to eq(I18n.t('doorkeeper.pre_authorization.status'))
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
it "sets correct values" do
|
|
327
|
+
expect(json_response['client_id']).to eq(client.uid)
|
|
328
|
+
expect(json_response['redirect_uri']).to eq(client.redirect_uri)
|
|
329
|
+
expect(json_response['state']).to be_nil
|
|
330
|
+
expect(json_response['response_type']).to eq('token')
|
|
331
|
+
expect(json_response['scope']).to eq('')
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
describe 'GET #new in API mode with skip_authorization true' do
|
|
336
|
+
before do
|
|
337
|
+
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { true })
|
|
338
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
339
|
+
|
|
340
|
+
get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
it 'should render success' do
|
|
344
|
+
expect(response).to be_successful
|
|
345
|
+
end
|
|
346
|
+
|
|
347
|
+
it 'should issue a token' do
|
|
348
|
+
expect(Doorkeeper::AccessToken.count).to be 1
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it "sets status to redirect" do
|
|
352
|
+
expect(JSON.parse(response.body)["status"]).to eq("redirect")
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
it "sets redirect_uri to correct value" do
|
|
356
|
+
redirect_uri = JSON.parse(response.body)["redirect_uri"]
|
|
357
|
+
expect(redirect_uri).to_not be_nil
|
|
358
|
+
expect(redirect_uri.match(/token_type=(\w+)&?/)[1]).to eq "Bearer"
|
|
359
|
+
expect(redirect_uri.match(/expires_in=(\d+)&?/)[1].to_i).to eq 1234
|
|
360
|
+
expect(
|
|
361
|
+
redirect_uri.match(/access_token=([a-f0-9]+)&?/)[1]
|
|
362
|
+
).to eq Doorkeeper::AccessToken.first.token
|
|
363
|
+
end
|
|
364
|
+
|
|
365
|
+
it "issues the token for the current client" do
|
|
366
|
+
expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
|
|
367
|
+
end
|
|
368
|
+
|
|
369
|
+
it "issues the token for the current resource owner" do
|
|
370
|
+
expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
|
|
371
|
+
end
|
|
372
|
+
end
|
|
373
|
+
|
|
203
374
|
describe 'GET #new with errors' do
|
|
204
375
|
before do
|
|
205
376
|
default_scopes_exist :public
|
|
206
|
-
get :new, an_invalid: 'request'
|
|
377
|
+
get :new, params: { an_invalid: 'request' }
|
|
207
378
|
end
|
|
208
379
|
|
|
209
380
|
it 'does not redirect' do
|
|
@@ -215,4 +386,95 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
|
215
386
|
expect(Doorkeeper::AccessToken.count).to eq 0
|
|
216
387
|
end
|
|
217
388
|
end
|
|
389
|
+
|
|
390
|
+
describe 'GET #new in API mode with errors' do
|
|
391
|
+
let(:response_json_body) { JSON.parse(response.body) }
|
|
392
|
+
|
|
393
|
+
before do
|
|
394
|
+
default_scopes_exist :public
|
|
395
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
396
|
+
get :new, params: { an_invalid: 'request' }
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
it 'should render bad request' do
|
|
400
|
+
expect(response).to have_http_status(:bad_request)
|
|
401
|
+
end
|
|
402
|
+
|
|
403
|
+
it 'includes error in body' do
|
|
404
|
+
expect(response_json_body['error']).to eq('unsupported_response_type')
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
it 'includes error description in body' do
|
|
408
|
+
expect(response_json_body['error_description']).to eq(translated_error_message(:unsupported_response_type))
|
|
409
|
+
end
|
|
410
|
+
|
|
411
|
+
it 'does not issue any token' do
|
|
412
|
+
expect(Doorkeeper::AccessGrant.count).to eq 0
|
|
413
|
+
expect(Doorkeeper::AccessToken.count).to eq 0
|
|
414
|
+
end
|
|
415
|
+
end
|
|
416
|
+
|
|
417
|
+
describe 'GET #new with callbacks' do
|
|
418
|
+
after do
|
|
419
|
+
client.update_attribute :redirect_uri, 'urn:ietf:wg:oauth:2.0:oob'
|
|
420
|
+
get :new, params: { client_id: client.uid, response_type: 'token', redirect_uri: client.redirect_uri }
|
|
421
|
+
end
|
|
422
|
+
|
|
423
|
+
describe 'when authorizing' do
|
|
424
|
+
before do
|
|
425
|
+
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { true })
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
it 'should call :before_successful_authorization callback' do
|
|
429
|
+
expect(Doorkeeper.configuration).to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
|
|
430
|
+
end
|
|
431
|
+
|
|
432
|
+
it 'should call :after_successful_authorization callback' do
|
|
433
|
+
expect(Doorkeeper.configuration).to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
|
|
434
|
+
end
|
|
435
|
+
end
|
|
436
|
+
|
|
437
|
+
describe 'when not authorizing' do
|
|
438
|
+
before do
|
|
439
|
+
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { false })
|
|
440
|
+
end
|
|
441
|
+
|
|
442
|
+
it 'should not call :before_successful_authorization callback' do
|
|
443
|
+
expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
|
|
444
|
+
end
|
|
445
|
+
|
|
446
|
+
it 'should not call :after_successful_authorization callback' do
|
|
447
|
+
expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
|
|
448
|
+
end
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
describe 'when not authorizing in api mode' do
|
|
452
|
+
before do
|
|
453
|
+
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc { false })
|
|
454
|
+
allow(Doorkeeper.configuration).to receive(:api_only).and_return(true)
|
|
455
|
+
end
|
|
456
|
+
|
|
457
|
+
it 'should not call :before_successful_authorization callback' do
|
|
458
|
+
expect(Doorkeeper.configuration).not_to receive(:before_successful_authorization)
|
|
459
|
+
end
|
|
460
|
+
|
|
461
|
+
it 'should not call :after_successful_authorization callback' do
|
|
462
|
+
expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
|
|
463
|
+
end
|
|
464
|
+
end
|
|
465
|
+
end
|
|
466
|
+
|
|
467
|
+
describe 'authorize response memoization' do
|
|
468
|
+
it 'memoizes the result of the authorization' do
|
|
469
|
+
strategy = double(:strategy, authorize: true)
|
|
470
|
+
expect(strategy).to receive(:authorize).once
|
|
471
|
+
allow(controller).to receive(:strategy) { strategy }
|
|
472
|
+
allow(controller).to receive(:create) do
|
|
473
|
+
2.times { controller.send :authorize_response }
|
|
474
|
+
controller.render json: {}, status: :ok
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
post :create
|
|
478
|
+
end
|
|
479
|
+
end
|
|
218
480
|
end
|