doorkeeper 4.4.3 → 5.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.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 +61 -8
- 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 +10 -1
- 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 +75 -39
- 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 +39 -22
- 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/password_access_token_request.rb +7 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +41 -11
- 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 +14 -6
- 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 +5 -25
- 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 +277 -47
- 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 +10 -5
- 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 +80 -31
- 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 +9 -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 -7
- 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 +33 -4
- 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 -47
- 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 +197 -1
- 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/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
- 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
@@ -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
|
@@ -58,7 +61,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
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
|
@@ -164,38 +273,6 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
164
273
|
it 'should not issue a token' do
|
165
274
|
expect(Doorkeeper::AccessToken.count).to be 0
|
166
275
|
end
|
167
|
-
|
168
|
-
context 'with opt_out_native_route_change' do
|
169
|
-
around(:each) do |example|
|
170
|
-
Doorkeeper.configure do
|
171
|
-
orm DOORKEEPER_ORM
|
172
|
-
opt_out_native_route_change
|
173
|
-
end
|
174
|
-
|
175
|
-
Rails.application.reload_routes!
|
176
|
-
|
177
|
-
example.run
|
178
|
-
|
179
|
-
Doorkeeper.configure do
|
180
|
-
orm DOORKEEPER_ORM
|
181
|
-
end
|
182
|
-
|
183
|
-
Rails.application.reload_routes!
|
184
|
-
end
|
185
|
-
|
186
|
-
it 'should redirect immediately' do
|
187
|
-
expect(response).to be_redirect
|
188
|
-
expect(response.location).to match(/oauth\/authorize\/#{Doorkeeper::AccessGrant.first.token}/)
|
189
|
-
end
|
190
|
-
|
191
|
-
it 'should issue a grant' do
|
192
|
-
expect(Doorkeeper::AccessGrant.count).to be 1
|
193
|
-
end
|
194
|
-
|
195
|
-
it 'should not issue a token' do
|
196
|
-
expect(Doorkeeper::AccessToken.count).to be 0
|
197
|
-
end
|
198
|
-
end
|
199
276
|
end
|
200
277
|
|
201
278
|
describe 'GET #new with skip_authorization true' do
|
@@ -203,7 +280,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
203
280
|
allow(Doorkeeper.configuration).to receive(:skip_authorization).and_return(proc do
|
204
281
|
true
|
205
282
|
end)
|
206
|
-
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 }
|
207
284
|
end
|
208
285
|
|
209
286
|
it 'should redirect immediately' do
|
@@ -220,7 +297,7 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
220
297
|
end
|
221
298
|
|
222
299
|
it 'includes token expiration in fragment' do
|
223
|
-
expect(response.query_params['expires_in'].to_i).to eq(
|
300
|
+
expect(response.query_params['expires_in'].to_i).to eq(1234)
|
224
301
|
end
|
225
302
|
|
226
303
|
it 'issues the token for the current client' do
|
@@ -232,10 +309,72 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
232
309
|
end
|
233
310
|
end
|
234
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
|
+
|
235
374
|
describe 'GET #new with errors' do
|
236
375
|
before do
|
237
376
|
default_scopes_exist :public
|
238
|
-
get :new, an_invalid: 'request'
|
377
|
+
get :new, params: { an_invalid: 'request' }
|
239
378
|
end
|
240
379
|
|
241
380
|
it 'does not redirect' do
|
@@ -247,4 +386,95 @@ describe Doorkeeper::AuthorizationsController, 'implicit grant flow' do
|
|
247
386
|
expect(Doorkeeper::AccessToken.count).to eq 0
|
248
387
|
end
|
249
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
|
250
480
|
end
|