doorkeeper 4.2.5 → 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/.github/ISSUE_TEMPLATE.md +25 -0
- data/.github/PULL_REQUEST_TEMPLATE.md +17 -0
- data/.gitignore +2 -1
- data/.gitlab-ci.yml +16 -0
- 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 +115 -0
- data/README.md +175 -39
- data/RELEASING.md +5 -12
- data/Rakefile +6 -0
- data/SECURITY.md +15 -0
- data/UPGRADE.md +2 -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 +19 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +24 -17
- 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 +19 -6
- data/doorkeeper.gemspec +20 -20
- 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 +17 -0
- data/lib/doorkeeper/config.rb +123 -71
- 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 +67 -23
- data/lib/doorkeeper/models/access_token_mixin.rb +54 -55
- 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 +46 -20
- data/lib/doorkeeper/oauth/authorization_code_request.rb +33 -3
- data/lib/doorkeeper/oauth/base_request.rb +23 -7
- data/lib/doorkeeper/oauth/client/credentials.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +2 -4
- 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.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 +45 -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/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 +1 -13
- data/lib/doorkeeper/request/refresh_token.rb +0 -2
- data/lib/doorkeeper/request/token.rb +0 -2
- data/lib/doorkeeper/request.rb +29 -30
- data/lib/doorkeeper/validations.rb +3 -2
- data/lib/doorkeeper/version.rb +14 -1
- data/lib/doorkeeper.rb +21 -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 +104 -12
- 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 +304 -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 +201 -17
- 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 +23 -2
- 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 +199 -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 +43 -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 +45 -2
- data/spec/models/doorkeeper/access_token_spec.rb +132 -64
- data/spec/models/doorkeeper/application_spec.rb +114 -23
- data/spec/requests/applications/applications_request_spec.rb +139 -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 +199 -2
- 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 +18 -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 +75 -33
- data/spec/controllers/application_metal_controller.rb +0 -10
- data/spec/support/dependencies/factory_girl.rb +0 -2
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
feature 'Implicit Grant Flow (feature spec)' do
|
|
4
4
|
background do
|
|
@@ -17,6 +17,29 @@ feature 'Implicit Grant Flow (feature spec)' do
|
|
|
17
17
|
|
|
18
18
|
i_should_be_on_client_callback @client
|
|
19
19
|
end
|
|
20
|
+
|
|
21
|
+
context 'when application scopes are present and no scope is passed' do
|
|
22
|
+
background do
|
|
23
|
+
@client.update_attributes(scopes: 'public write read')
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
scenario 'access token has no scopes' do
|
|
27
|
+
default_scopes_exist :admin
|
|
28
|
+
visit authorization_endpoint_url(client: @client, response_type: 'token')
|
|
29
|
+
click_on 'Authorize'
|
|
30
|
+
access_token_should_exist_for @client, @resource_owner
|
|
31
|
+
token = Doorkeeper::AccessToken.first
|
|
32
|
+
expect(token.scopes).to be_empty
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
scenario 'access token has scopes which are common in application scopees and default scopes' do
|
|
36
|
+
default_scopes_exist :public, :write
|
|
37
|
+
visit authorization_endpoint_url(client: @client, response_type: 'token')
|
|
38
|
+
click_on 'Authorize'
|
|
39
|
+
access_token_should_exist_for @client, @resource_owner
|
|
40
|
+
access_token_should_have_scopes :public, :write
|
|
41
|
+
end
|
|
42
|
+
end
|
|
20
43
|
end
|
|
21
44
|
|
|
22
45
|
describe 'Implicit Grant Flow (request spec)' do
|
|
@@ -34,11 +57,13 @@ describe 'Implicit Grant Flow (request spec)' do
|
|
|
34
57
|
token = client_is_authorized(@client, @resource_owner)
|
|
35
58
|
|
|
36
59
|
post "/oauth/authorize",
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
60
|
+
params: {
|
|
61
|
+
client_id: @client.uid,
|
|
62
|
+
state: '',
|
|
63
|
+
redirect_uri: @client.redirect_uri,
|
|
64
|
+
response_type: 'token',
|
|
65
|
+
commit: 'Authorize'
|
|
66
|
+
}
|
|
42
67
|
|
|
43
68
|
expect(response.location).not_to include(token.token)
|
|
44
69
|
end
|
|
@@ -49,11 +74,13 @@ describe 'Implicit Grant Flow (request spec)' do
|
|
|
49
74
|
token = client_is_authorized(@client, @resource_owner)
|
|
50
75
|
|
|
51
76
|
post "/oauth/authorize",
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
77
|
+
params: {
|
|
78
|
+
client_id: @client.uid,
|
|
79
|
+
state: '',
|
|
80
|
+
redirect_uri: @client.redirect_uri,
|
|
81
|
+
response_type: 'token',
|
|
82
|
+
commit: 'Authorize'
|
|
83
|
+
}
|
|
57
84
|
|
|
58
85
|
expect(response.location).to include(token.token)
|
|
59
86
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe 'Resource Owner Password Credentials Flow not set up' do
|
|
4
4
|
before do
|
|
@@ -7,49 +7,92 @@ describe 'Resource Owner Password Credentials Flow not set up' do
|
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
context 'with valid user credentials' do
|
|
10
|
-
it '
|
|
10
|
+
it 'does not issue new token' do
|
|
11
11
|
expect do
|
|
12
12
|
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
13
|
-
end.to_not
|
|
13
|
+
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
describe 'Resource Owner Password Credentials Flow' do
|
|
19
|
+
let(:client_attributes) { {} }
|
|
20
|
+
|
|
19
21
|
before do
|
|
20
22
|
config_is_set(:grant_flows, ["password"])
|
|
21
23
|
config_is_set(:resource_owner_from_credentials) { User.authenticate! params[:username], params[:password] }
|
|
22
|
-
client_exists
|
|
24
|
+
client_exists(client_attributes)
|
|
23
25
|
create_resource_owner
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
context 'with valid user credentials' do
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
context "with non-confidential/public client" do
|
|
30
|
+
let(:client_attributes) { { confidential: false } }
|
|
31
|
+
|
|
32
|
+
context "when client_secret absent" do
|
|
33
|
+
it "should issue new token" do
|
|
34
|
+
expect do
|
|
35
|
+
post password_token_endpoint_url(client_id: @client.uid, resource_owner: @resource_owner)
|
|
36
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
37
|
+
|
|
38
|
+
token = Doorkeeper::AccessToken.first
|
|
39
|
+
|
|
40
|
+
expect(token.application_id).to eq @client.id
|
|
41
|
+
should_have_json 'access_token', token.token
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
context "when client_secret present" do
|
|
46
|
+
it "should issue new token" do
|
|
47
|
+
expect do
|
|
48
|
+
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
49
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
50
|
+
|
|
51
|
+
token = Doorkeeper::AccessToken.first
|
|
52
|
+
|
|
53
|
+
expect(token.application_id).to eq @client.id
|
|
54
|
+
should_have_json 'access_token', token.token
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
context "when client_secret incorrect" do
|
|
58
|
+
it "should not issue new token" do
|
|
59
|
+
expect do
|
|
60
|
+
post password_token_endpoint_url(client_id: @client.uid, client_secret: 'foobar', resource_owner: @resource_owner)
|
|
61
|
+
end.not_to(change { Doorkeeper::AccessToken.count })
|
|
62
|
+
|
|
63
|
+
expect(response).not_to be_ok
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
31
68
|
|
|
32
|
-
|
|
69
|
+
context "with confidential/private client" do
|
|
70
|
+
it "should issue new token" do
|
|
71
|
+
expect do
|
|
72
|
+
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
73
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
33
74
|
|
|
34
|
-
|
|
35
|
-
should_have_json 'access_token', token.token
|
|
36
|
-
end
|
|
75
|
+
token = Doorkeeper::AccessToken.first
|
|
37
76
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
77
|
+
expect(token.application_id).to eq @client.id
|
|
78
|
+
should_have_json 'access_token', token.token
|
|
79
|
+
end
|
|
42
80
|
|
|
43
|
-
|
|
81
|
+
context "when client_secret absent" do
|
|
82
|
+
it "should not issue new token" do
|
|
83
|
+
expect do
|
|
84
|
+
post password_token_endpoint_url(client_id: @client.uid, resource_owner: @resource_owner)
|
|
85
|
+
end.not_to(change { Doorkeeper::AccessToken.count })
|
|
44
86
|
|
|
45
|
-
|
|
46
|
-
|
|
87
|
+
expect(response).not_to be_ok
|
|
88
|
+
end
|
|
89
|
+
end
|
|
47
90
|
end
|
|
48
91
|
|
|
49
92
|
it 'should issue new token without client credentials' do
|
|
50
93
|
expect do
|
|
51
94
|
post password_token_endpoint_url(resource_owner: @resource_owner)
|
|
52
|
-
end.to
|
|
95
|
+
end.to(change { Doorkeeper::AccessToken.count }.by(1))
|
|
53
96
|
|
|
54
97
|
token = Doorkeeper::AccessToken.first
|
|
55
98
|
|
|
@@ -77,6 +120,99 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
77
120
|
expect(Doorkeeper::AccessToken.count).to be(1)
|
|
78
121
|
should_have_json 'access_token', Doorkeeper::AccessToken.first.token
|
|
79
122
|
end
|
|
123
|
+
|
|
124
|
+
context 'with valid, default scope' do
|
|
125
|
+
before do
|
|
126
|
+
default_scopes_exist :public
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it 'should issue new token' do
|
|
130
|
+
expect do
|
|
131
|
+
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner, scope: 'public')
|
|
132
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
133
|
+
|
|
134
|
+
token = Doorkeeper::AccessToken.first
|
|
135
|
+
|
|
136
|
+
expect(token.application_id).to eq @client.id
|
|
137
|
+
should_have_json 'access_token', token.token
|
|
138
|
+
should_have_json 'scope', 'public'
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context 'when application scopes are present and differs from configured default scopes and no scope is passed' do
|
|
144
|
+
before do
|
|
145
|
+
default_scopes_exist :public
|
|
146
|
+
@client.update_attributes(scopes: 'abc')
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it 'issues new token without any scope' do
|
|
150
|
+
expect do
|
|
151
|
+
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
152
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
153
|
+
|
|
154
|
+
token = Doorkeeper::AccessToken.first
|
|
155
|
+
|
|
156
|
+
expect(token.application_id).to eq @client.id
|
|
157
|
+
expect(token.scopes).to be_empty
|
|
158
|
+
should_have_json 'access_token', token.token
|
|
159
|
+
should_not_have_json 'scope'
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
context 'when application scopes contain some of the default scopes and no scope is passed' do
|
|
164
|
+
before do
|
|
165
|
+
@client.update_attributes(scopes: 'read write public')
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
it 'issues new token with one default scope that are present in application scopes' do
|
|
169
|
+
default_scopes_exist :public, :admin
|
|
170
|
+
|
|
171
|
+
expect do
|
|
172
|
+
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
173
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
174
|
+
|
|
175
|
+
token = Doorkeeper::AccessToken.first
|
|
176
|
+
|
|
177
|
+
expect(token.application_id).to eq @client.id
|
|
178
|
+
should_have_json 'access_token', token.token
|
|
179
|
+
should_have_json 'scope', 'public'
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'issues new token with multiple default scopes that are present in application scopes' do
|
|
183
|
+
default_scopes_exist :public, :read, :update
|
|
184
|
+
|
|
185
|
+
expect do
|
|
186
|
+
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
187
|
+
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
188
|
+
|
|
189
|
+
token = Doorkeeper::AccessToken.first
|
|
190
|
+
|
|
191
|
+
expect(token.application_id).to eq @client.id
|
|
192
|
+
should_have_json 'access_token', token.token
|
|
193
|
+
should_have_json 'scope', 'public read'
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
context 'with invalid scopes' do
|
|
198
|
+
subject do
|
|
199
|
+
post password_token_endpoint_url(client: @client,
|
|
200
|
+
resource_owner: @resource_owner,
|
|
201
|
+
scope: 'random')
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
it 'should not issue new token' do
|
|
205
|
+
expect { subject }.to_not(change { Doorkeeper::AccessToken.count })
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
it 'should return invalid_scope error' do
|
|
209
|
+
subject
|
|
210
|
+
should_have_json 'error', 'invalid_scope'
|
|
211
|
+
should_have_json 'error_description', translated_error_message(:invalid_scope)
|
|
212
|
+
should_not_have_json 'access_token'
|
|
213
|
+
|
|
214
|
+
expect(response.status).to eq(401)
|
|
215
|
+
end
|
|
80
216
|
end
|
|
81
217
|
|
|
82
218
|
context 'with invalid user credentials' do
|
|
@@ -85,13 +221,13 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
85
221
|
post password_token_endpoint_url(client: @client,
|
|
86
222
|
resource_owner_username: @resource_owner.name,
|
|
87
223
|
resource_owner_password: 'wrongpassword')
|
|
88
|
-
end.to_not
|
|
224
|
+
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
89
225
|
end
|
|
90
226
|
|
|
91
227
|
it 'should not issue new token without credentials' do
|
|
92
228
|
expect do
|
|
93
229
|
post password_token_endpoint_url(client: @client)
|
|
94
|
-
end.to_not
|
|
230
|
+
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
95
231
|
end
|
|
96
232
|
end
|
|
97
233
|
|
|
@@ -101,7 +237,7 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
101
237
|
post password_token_endpoint_url(client_id: @client.uid,
|
|
102
238
|
client_secret: 'bad_secret',
|
|
103
239
|
resource_owner: @resource_owner)
|
|
104
|
-
end.to_not
|
|
240
|
+
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
105
241
|
end
|
|
106
242
|
end
|
|
107
243
|
|
|
@@ -109,7 +245,7 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
109
245
|
it 'should not issue new token with bad client id' do
|
|
110
246
|
expect do
|
|
111
247
|
post password_token_endpoint_url(client_id: 'bad_id', resource_owner: @resource_owner)
|
|
112
|
-
end.to_not
|
|
248
|
+
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
113
249
|
end
|
|
114
250
|
end
|
|
115
251
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe 'Refresh Token Flow' do
|
|
4
4
|
before do
|
|
@@ -14,7 +14,7 @@ describe 'Refresh Token Flow' do
|
|
|
14
14
|
authorization_code_exists application: @client
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
it 'client gets the refresh token and
|
|
17
|
+
it 'client gets the refresh token and refreshes it' do
|
|
18
18
|
post token_endpoint_url(code: @authorization.token, client: @client)
|
|
19
19
|
|
|
20
20
|
token = Doorkeeper::AccessToken.first
|
|
@@ -37,7 +37,7 @@ describe 'Refresh Token Flow' do
|
|
|
37
37
|
|
|
38
38
|
context 'refreshing the token' do
|
|
39
39
|
before do
|
|
40
|
-
@token =
|
|
40
|
+
@token = FactoryBot.create(
|
|
41
41
|
:access_token,
|
|
42
42
|
application: @client,
|
|
43
43
|
resource_owner_id: 1,
|
|
@@ -101,14 +101,14 @@ describe 'Refresh Token Flow' do
|
|
|
101
101
|
should_have_json 'error', 'invalid_grant'
|
|
102
102
|
end
|
|
103
103
|
|
|
104
|
-
it 'client gets an error for revoked
|
|
104
|
+
it 'client gets an error for revoked access token' do
|
|
105
105
|
@token.revoke
|
|
106
106
|
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
|
|
107
107
|
should_not_have_json 'refresh_token'
|
|
108
108
|
should_have_json 'error', 'invalid_grant'
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
-
it 'second of simultaneous client requests get an error for revoked
|
|
111
|
+
it 'second of simultaneous client requests get an error for revoked access token' do
|
|
112
112
|
allow_any_instance_of(Doorkeeper::AccessToken).to receive(:revoked?).and_return(false, true)
|
|
113
113
|
post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
|
|
114
114
|
|
|
@@ -130,7 +130,7 @@ describe 'Refresh Token Flow' do
|
|
|
130
130
|
)
|
|
131
131
|
last_token.update_attribute :created_at, 5.seconds.ago
|
|
132
132
|
|
|
133
|
-
@token =
|
|
133
|
+
@token = FactoryBot.create(
|
|
134
134
|
:access_token,
|
|
135
135
|
application: @client,
|
|
136
136
|
resource_owner_id: @resource_owner.id,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe 'Revoke Token Flow' do
|
|
4
4
|
before do
|
|
@@ -6,10 +6,10 @@ describe 'Revoke Token Flow' do
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
context 'with default parameters' do
|
|
9
|
-
let(:client_application) {
|
|
9
|
+
let(:client_application) { FactoryBot.create :application }
|
|
10
10
|
let(:resource_owner) { User.create!(name: 'John', password: 'sekret') }
|
|
11
11
|
let(:access_token) do
|
|
12
|
-
|
|
12
|
+
FactoryBot.create(:access_token,
|
|
13
13
|
application: client_application,
|
|
14
14
|
resource_owner_id: resource_owner.id,
|
|
15
15
|
use_refresh_token: true)
|
|
@@ -24,31 +24,31 @@ describe 'Revoke Token Flow' do
|
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
it 'should revoke the access token provided' do
|
|
27
|
-
post revocation_token_endpoint_url, { token: access_token.token }, headers
|
|
27
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
28
28
|
|
|
29
29
|
access_token.reload
|
|
30
30
|
|
|
31
|
-
expect(response).to
|
|
31
|
+
expect(response).to be_successful
|
|
32
32
|
expect(access_token.revoked?).to be_truthy
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
it 'should revoke the refresh token provided' do
|
|
36
|
-
post revocation_token_endpoint_url, { token: access_token.refresh_token }, headers
|
|
36
|
+
post revocation_token_endpoint_url, params: { token: access_token.refresh_token }, headers: headers
|
|
37
37
|
|
|
38
38
|
access_token.reload
|
|
39
39
|
|
|
40
|
-
expect(response).to
|
|
40
|
+
expect(response).to be_successful
|
|
41
41
|
expect(access_token.revoked?).to be_truthy
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
context 'with invalid token to revoke' do
|
|
45
45
|
it 'should not revoke any tokens and respond successfully' do
|
|
46
46
|
num_prev_revoked_tokens = Doorkeeper::AccessToken.where(revoked_at: nil).count
|
|
47
|
-
post revocation_token_endpoint_url, { token: 'I_AM_AN_INVALID_TOKEN' }, headers
|
|
47
|
+
post revocation_token_endpoint_url, params: { token: 'I_AM_AN_INVALID_TOKEN' }, headers: headers
|
|
48
48
|
|
|
49
49
|
# The authorization server responds with HTTP status code 200 even if
|
|
50
50
|
# token is invalid
|
|
51
|
-
expect(response).to
|
|
51
|
+
expect(response).to be_successful
|
|
52
52
|
expect(Doorkeeper::AccessToken.where(revoked_at: nil).count).to eq(num_prev_revoked_tokens)
|
|
53
53
|
end
|
|
54
54
|
end
|
|
@@ -60,28 +60,28 @@ describe 'Revoke Token Flow' do
|
|
|
60
60
|
{ 'HTTP_AUTHORIZATION' => "Basic #{credentials}" }
|
|
61
61
|
end
|
|
62
62
|
it 'should not revoke any tokens and respond successfully' do
|
|
63
|
-
post revocation_token_endpoint_url, { token: access_token.token }, headers
|
|
63
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
64
64
|
|
|
65
65
|
access_token.reload
|
|
66
66
|
|
|
67
|
-
expect(response).to
|
|
67
|
+
expect(response).to be_successful
|
|
68
68
|
expect(access_token.revoked?).to be_falsey
|
|
69
69
|
end
|
|
70
70
|
end
|
|
71
71
|
|
|
72
72
|
context 'with no credentials and a valid token' do
|
|
73
73
|
it 'should not revoke any tokens and respond successfully' do
|
|
74
|
-
post revocation_token_endpoint_url, { token: access_token.token }
|
|
74
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
75
75
|
|
|
76
76
|
access_token.reload
|
|
77
77
|
|
|
78
|
-
expect(response).to
|
|
78
|
+
expect(response).to be_successful
|
|
79
79
|
expect(access_token.revoked?).to be_falsey
|
|
80
80
|
end
|
|
81
81
|
end
|
|
82
82
|
|
|
83
83
|
context 'with valid token for another client application' do
|
|
84
|
-
let(:other_client_application) {
|
|
84
|
+
let(:other_client_application) { FactoryBot.create :application }
|
|
85
85
|
let(:headers) do
|
|
86
86
|
client_id = other_client_application.uid
|
|
87
87
|
client_secret = other_client_application.secret
|
|
@@ -90,11 +90,11 @@ describe 'Revoke Token Flow' do
|
|
|
90
90
|
end
|
|
91
91
|
|
|
92
92
|
it 'should not revoke the token as its unauthorized' do
|
|
93
|
-
post revocation_token_endpoint_url, { token: access_token.token }, headers
|
|
93
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
|
|
94
94
|
|
|
95
95
|
access_token.reload
|
|
96
96
|
|
|
97
|
-
expect(response).to
|
|
97
|
+
expect(response).to be_successful
|
|
98
98
|
expect(access_token.revoked?).to be_falsey
|
|
99
99
|
end
|
|
100
100
|
end
|
|
@@ -102,53 +102,53 @@ describe 'Revoke Token Flow' do
|
|
|
102
102
|
|
|
103
103
|
context 'with public OAuth 2.0 client/application' do
|
|
104
104
|
let(:access_token) do
|
|
105
|
-
|
|
105
|
+
FactoryBot.create(:access_token,
|
|
106
106
|
application: nil,
|
|
107
107
|
resource_owner_id: resource_owner.id,
|
|
108
108
|
use_refresh_token: true)
|
|
109
109
|
end
|
|
110
110
|
|
|
111
111
|
it 'should revoke the access token provided' do
|
|
112
|
-
post revocation_token_endpoint_url, { token: access_token.token }
|
|
112
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
113
113
|
|
|
114
114
|
access_token.reload
|
|
115
115
|
|
|
116
|
-
expect(response).to
|
|
116
|
+
expect(response).to be_successful
|
|
117
117
|
expect(access_token.revoked?).to be_truthy
|
|
118
118
|
end
|
|
119
119
|
|
|
120
120
|
it 'should revoke the refresh token provided' do
|
|
121
|
-
post revocation_token_endpoint_url, { token: access_token.refresh_token }
|
|
121
|
+
post revocation_token_endpoint_url, params: { token: access_token.refresh_token }
|
|
122
122
|
|
|
123
123
|
access_token.reload
|
|
124
124
|
|
|
125
|
-
expect(response).to
|
|
125
|
+
expect(response).to be_successful
|
|
126
126
|
expect(access_token.revoked?).to be_truthy
|
|
127
127
|
end
|
|
128
128
|
|
|
129
129
|
context 'with a valid token issued for a confidential client' do
|
|
130
130
|
let(:access_token) do
|
|
131
|
-
|
|
131
|
+
FactoryBot.create(:access_token,
|
|
132
132
|
application: client_application,
|
|
133
133
|
resource_owner_id: resource_owner.id,
|
|
134
134
|
use_refresh_token: true)
|
|
135
135
|
end
|
|
136
136
|
|
|
137
137
|
it 'should not revoke the access token provided' do
|
|
138
|
-
post revocation_token_endpoint_url, { token: access_token.token }
|
|
138
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
139
139
|
|
|
140
140
|
access_token.reload
|
|
141
141
|
|
|
142
|
-
expect(response).to
|
|
142
|
+
expect(response).to be_successful
|
|
143
143
|
expect(access_token.revoked?).to be_falsey
|
|
144
144
|
end
|
|
145
145
|
|
|
146
146
|
it 'should not revoke the refresh token provided' do
|
|
147
|
-
post revocation_token_endpoint_url, { token: access_token.token }
|
|
147
|
+
post revocation_token_endpoint_url, params: { token: access_token.token }
|
|
148
148
|
|
|
149
149
|
access_token.reload
|
|
150
150
|
|
|
151
|
-
expect(response).to
|
|
151
|
+
expect(response).to be_successful
|
|
152
152
|
expect(access_token.revoked?).to be_falsey
|
|
153
153
|
end
|
|
154
154
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
feature 'Skip authorization form' do
|
|
4
4
|
background do
|
|
@@ -15,13 +15,24 @@ feature 'Skip authorization form' do
|
|
|
15
15
|
end
|
|
16
16
|
|
|
17
17
|
scenario 'skips the authorization and return a new grant code' do
|
|
18
|
-
client_is_authorized(@client, @resource_owner, scopes:
|
|
19
|
-
visit authorization_endpoint_url(client: @client)
|
|
18
|
+
client_is_authorized(@client, @resource_owner, scopes: "public")
|
|
19
|
+
visit authorization_endpoint_url(client: @client, scope: "public")
|
|
20
|
+
|
|
21
|
+
i_should_not_see "Authorize"
|
|
22
|
+
client_should_be_authorized @client
|
|
23
|
+
i_should_be_on_client_callback @client
|
|
24
|
+
url_should_have_param "code", Doorkeeper::AccessGrant.first.token
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
scenario "skips the authorization if other scopes are not requested" do
|
|
28
|
+
client_exists scopes: "public read write"
|
|
29
|
+
client_is_authorized(@client, @resource_owner, scopes: "public")
|
|
30
|
+
visit authorization_endpoint_url(client: @client, scope: "public")
|
|
20
31
|
|
|
21
|
-
i_should_not_see
|
|
32
|
+
i_should_not_see "Authorize"
|
|
22
33
|
client_should_be_authorized @client
|
|
23
34
|
i_should_be_on_client_callback @client
|
|
24
|
-
url_should_have_param
|
|
35
|
+
url_should_have_param "code", Doorkeeper::AccessGrant.first.token
|
|
25
36
|
end
|
|
26
37
|
|
|
27
38
|
scenario 'does not skip authorization when scopes differ (new request has fewer scopes)' do
|
|
@@ -43,12 +54,6 @@ feature 'Skip authorization form' do
|
|
|
43
54
|
access_grant_should_have_scopes :public
|
|
44
55
|
end
|
|
45
56
|
|
|
46
|
-
scenario 'doesn not skip authorization when scopes are greater' do
|
|
47
|
-
client_is_authorized(@client, @resource_owner, scopes: 'public')
|
|
48
|
-
visit authorization_endpoint_url(client: @client, scope: 'public write')
|
|
49
|
-
i_should_see 'Authorize'
|
|
50
|
-
end
|
|
51
|
-
|
|
52
57
|
scenario 'creates grant with new scope when scopes are greater' do
|
|
53
58
|
client_is_authorized(@client, @resource_owner, scopes: 'public')
|
|
54
59
|
visit authorization_endpoint_url(client: @client, scope: 'public write')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe 'ActionController::Metal API' do
|
|
4
4
|
before do
|
|
5
|
-
@client =
|
|
5
|
+
@client = FactoryBot.create(:application)
|
|
6
6
|
@resource = User.create!(name: 'Joe', password: 'sekret')
|
|
7
7
|
@token = client_is_authorized(@client, @resource)
|
|
8
8
|
end
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
feature 'Private API' do
|
|
4
4
|
background do
|
|
5
|
-
@client =
|
|
5
|
+
@client = FactoryBot.create(:application)
|
|
6
6
|
@resource = User.create!(name: 'Joe', password: 'sekret')
|
|
7
7
|
@token = client_is_authorized(@client, @resource)
|
|
8
8
|
end
|