doorkeeper 5.0.3 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.hound.yml +2 -1
- data/.rubocop.yml +37 -4
- data/.travis.yml +11 -21
- data/Appraisals +29 -7
- data/Dangerfile +5 -2
- data/Gemfile +19 -5
- data/NEWS.md +81 -21
- data/README.md +75 -485
- data/Rakefile +10 -8
- data/app/controllers/doorkeeper/application_controller.rb +1 -2
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -13
- data/app/controllers/doorkeeper/applications_controller.rb +20 -8
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/token_info_controller.rb +2 -2
- data/app/controllers/doorkeeper/tokens_controller.rb +11 -11
- data/app/helpers/doorkeeper/dashboard_helper.rb +1 -1
- data/app/validators/redirect_uri_validator.rb +5 -2
- data/app/views/doorkeeper/applications/_form.html.erb +6 -0
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
- data/bin/console +16 -0
- data/config/locales/en.yml +1 -0
- data/doorkeeper.gemspec +24 -21
- data/gemfiles/rails_5_0.gemfile +9 -4
- data/gemfiles/rails_5_1.gemfile +9 -4
- data/gemfiles/rails_5_2.gemfile +10 -5
- data/gemfiles/rails_6_0.gemfile +17 -0
- data/gemfiles/rails_master.gemfile +9 -9
- data/lib/doorkeeper/config/option.rb +64 -0
- data/lib/doorkeeper/config.rb +191 -75
- data/lib/doorkeeper/engine.rb +1 -1
- data/lib/doorkeeper/grape/authorization_decorator.rb +4 -4
- data/lib/doorkeeper/grape/helpers.rb +3 -3
- data/lib/doorkeeper/helpers/controller.rb +3 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +20 -3
- data/lib/doorkeeper/models/access_token_mixin.rb +63 -19
- data/lib/doorkeeper/models/application_mixin.rb +43 -1
- data/lib/doorkeeper/models/concerns/expirable.rb +4 -2
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +108 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +2 -2
- data/lib/doorkeeper/oauth/authorization/token.rb +12 -7
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +6 -4
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +5 -4
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +10 -6
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +13 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +37 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -1
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +11 -5
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
- data/lib/doorkeeper/oauth/scopes.rb +5 -3
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +74 -8
- data/lib/doorkeeper/oauth/token_response.rb +9 -9
- data/lib/doorkeeper/oauth.rb +5 -5
- data/lib/doorkeeper/orm/active_record/access_grant.rb +27 -13
- data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
- data/lib/doorkeeper/orm/active_record/application.rb +21 -57
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
- data/lib/doorkeeper/orm/active_record.rb +6 -6
- data/lib/doorkeeper/rails/helpers.rb +1 -1
- data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
- data/lib/doorkeeper/rails/routes.rb +11 -11
- data/lib/doorkeeper/rake/db.rake +13 -13
- data/lib/doorkeeper/rake.rb +1 -1
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/secret_storing/base.rb +64 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +60 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +26 -0
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +3 -3
- data/lib/doorkeeper.rb +69 -60
- data/lib/generators/doorkeeper/application_owner_generator.rb +10 -9
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +10 -9
- data/lib/generators/doorkeeper/install_generator.rb +11 -9
- data/lib/generators/doorkeeper/migration_generator.rb +9 -9
- data/lib/generators/doorkeeper/pkce_generator.rb +10 -9
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +10 -9
- data/lib/generators/doorkeeper/templates/initializer.rb +120 -13
- data/lib/generators/doorkeeper/templates/migration.rb.erb +15 -7
- data/lib/generators/doorkeeper/views_generator.rb +6 -4
- data/spec/controllers/application_metal_controller_spec.rb +24 -10
- data/spec/controllers/applications_controller_spec.rb +54 -52
- data/spec/controllers/authorizations_controller_spec.rb +139 -145
- data/spec/controllers/protected_resources_controller_spec.rb +78 -76
- data/spec/controllers/token_info_controller_spec.rb +14 -12
- data/spec/controllers/tokens_controller_spec.rb +167 -108
- data/spec/dummy/Rakefile +3 -1
- data/spec/dummy/app/controllers/application_controller.rb +3 -1
- data/spec/dummy/app/controllers/custom_authorizations_controller.rb +2 -0
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/controllers/home_controller.rb +5 -3
- data/spec/dummy/app/controllers/metal_controller.rb +2 -0
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +4 -2
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/models/user.rb +2 -0
- data/spec/dummy/config/application.rb +25 -1
- data/spec/dummy/config/environments/development.rb +2 -0
- data/spec/dummy/config/environments/production.rb +2 -0
- data/spec/dummy/config/environments/test.rb +3 -1
- data/spec/dummy/config/initializers/backtrace_silencers.rb +2 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +5 -2
- data/spec/dummy/config/initializers/secret_token.rb +3 -1
- data/spec/dummy/config/initializers/session_store.rb +3 -1
- data/spec/dummy/config/initializers/wrap_parameters.rb +2 -0
- data/spec/dummy/config.ru +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +17 -10
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +2 -0
- data/spec/dummy/db/schema.rb +1 -1
- data/spec/dummy/script/rails +5 -3
- data/spec/factories.rb +8 -6
- data/spec/generators/application_owner_generator_spec.rb +13 -26
- data/spec/generators/confidential_applications_generator_spec.rb +12 -28
- data/spec/generators/install_generator_spec.rb +17 -15
- data/spec/generators/migration_generator_spec.rb +13 -26
- data/spec/generators/pkce_generator_spec.rb +11 -26
- data/spec/generators/previous_refresh_token_generator_spec.rb +16 -29
- data/spec/generators/templates/routes.rb +2 -0
- data/spec/generators/views_generator_spec.rb +14 -12
- data/spec/grape/grape_integration_spec.rb +34 -32
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +9 -7
- data/spec/lib/config_spec.rb +268 -99
- data/spec/lib/doorkeeper_spec.rb +3 -1
- data/spec/lib/models/expirable_spec.rb +22 -8
- data/spec/lib/models/reusable_spec.rb +40 -0
- data/spec/lib/models/revocable_spec.rb +8 -6
- data/spec/lib/models/scopes_spec.rb +27 -13
- data/spec/lib/models/secret_storable_spec.rb +135 -0
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
- data/spec/lib/oauth/authorization_code_request_spec.rb +34 -11
- data/spec/lib/oauth/base_request_spec.rb +20 -8
- data/spec/lib/oauth/base_response_spec.rb +3 -1
- data/spec/lib/oauth/client/credentials_spec.rb +24 -22
- data/spec/lib/oauth/client_credentials/creator_spec.rb +56 -10
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
- data/spec/lib/oauth/client_credentials/validation_spec.rb +20 -15
- data/spec/lib/oauth/client_credentials_integration_spec.rb +7 -5
- data/spec/lib/oauth/client_credentials_request_spec.rb +27 -21
- data/spec/lib/oauth/client_spec.rb +15 -13
- data/spec/lib/oauth/code_request_spec.rb +8 -6
- data/spec/lib/oauth/code_response_spec.rb +9 -7
- data/spec/lib/oauth/error_response_spec.rb +19 -11
- data/spec/lib/oauth/error_spec.rb +4 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +7 -5
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +68 -31
- data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +115 -95
- data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +79 -30
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -54
- data/spec/lib/oauth/refresh_token_request_spec.rb +36 -33
- data/spec/lib/oauth/scopes_spec.rb +63 -61
- data/spec/lib/oauth/token_request_spec.rb +79 -24
- data/spec/lib/oauth/token_response_spec.rb +40 -38
- data/spec/lib/oauth/token_spec.rb +60 -44
- data/spec/lib/request/strategy_spec.rb +3 -1
- data/spec/lib/secret_storing/base_spec.rb +60 -0
- data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
- data/spec/lib/secret_storing/plain_spec.rb +44 -0
- data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
- data/spec/lib/server_spec.rb +16 -14
- data/spec/lib/stale_records_cleaner_spec.rb +17 -17
- data/spec/models/doorkeeper/access_grant_spec.rb +80 -15
- data/spec/models/doorkeeper/access_token_spec.rb +198 -73
- data/spec/models/doorkeeper/application_spec.rb +280 -288
- data/spec/requests/applications/applications_request_spec.rb +98 -66
- data/spec/requests/applications/authorized_applications_spec.rb +20 -18
- data/spec/requests/endpoints/authorization_spec.rb +25 -23
- data/spec/requests/endpoints/token_spec.rb +38 -36
- data/spec/requests/flows/authorization_code_errors_spec.rb +26 -24
- data/spec/requests/flows/authorization_code_spec.rb +193 -151
- data/spec/requests/flows/client_credentials_spec.rb +54 -52
- data/spec/requests/flows/implicit_grant_errors_spec.rb +10 -8
- data/spec/requests/flows/implicit_grant_spec.rb +27 -25
- data/spec/requests/flows/password_spec.rb +59 -55
- data/spec/requests/flows/refresh_token_spec.rb +45 -43
- data/spec/requests/flows/revoke_token_spec.rb +40 -54
- data/spec/requests/flows/skip_authorization_spec.rb +23 -21
- data/spec/requests/protected_resources/metal_spec.rb +7 -5
- data/spec/requests/protected_resources/private_api_spec.rb +35 -33
- data/spec/routing/custom_controller_routes_spec.rb +71 -65
- data/spec/routing/default_routes_spec.rb +22 -20
- data/spec/routing/scoped_routes_spec.rb +20 -18
- data/spec/spec_helper.rb +15 -13
- data/spec/spec_helper_integration.rb +3 -1
- data/spec/support/dependencies/factory_bot.rb +3 -1
- data/spec/support/doorkeeper_rspec.rb +3 -1
- data/spec/support/helpers/access_token_request_helper.rb +3 -1
- data/spec/support/helpers/authorization_request_helper.rb +4 -2
- data/spec/support/helpers/config_helper.rb +2 -0
- data/spec/support/helpers/model_helper.rb +3 -1
- data/spec/support/helpers/request_spec_helper.rb +5 -3
- data/spec/support/helpers/url_helper.rb +9 -7
- data/spec/support/http_method_shim.rb +4 -9
- data/spec/support/orm/active_record.rb +3 -1
- data/spec/support/shared/controllers_shared_context.rb +18 -16
- data/spec/support/shared/hashing_shared_context.rb +36 -0
- data/spec/support/shared/models_shared_examples.rb +12 -10
- data/spec/validators/redirect_uri_validator_spec.rb +74 -45
- data/spec/version/version_spec.rb +7 -5
- metadata +60 -26
- data/gemfiles/rails_4_2.gemfile +0 -13
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
|
@@ -1,119 +1,121 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe "Client Credentials Request" do
|
|
4
6
|
let(:client) { FactoryBot.create :application }
|
|
5
7
|
|
|
6
|
-
context
|
|
7
|
-
it
|
|
8
|
+
context "a valid request" do
|
|
9
|
+
it "authorizes the client and returns the token response" do
|
|
8
10
|
headers = authorization client.uid, client.secret
|
|
9
|
-
params = { grant_type:
|
|
11
|
+
params = { grant_type: "client_credentials" }
|
|
10
12
|
|
|
11
|
-
post
|
|
13
|
+
post "/oauth/token", params: params, headers: headers
|
|
12
14
|
|
|
13
|
-
should_have_json
|
|
14
|
-
should_have_json_within
|
|
15
|
-
should_not_have_json
|
|
16
|
-
should_not_have_json
|
|
15
|
+
should_have_json "access_token", Doorkeeper::AccessToken.first.token
|
|
16
|
+
should_have_json_within "expires_in", Doorkeeper.configuration.access_token_expires_in, 1
|
|
17
|
+
should_not_have_json "scope"
|
|
18
|
+
should_not_have_json "refresh_token"
|
|
17
19
|
|
|
18
|
-
should_not_have_json
|
|
19
|
-
should_not_have_json
|
|
20
|
+
should_not_have_json "error"
|
|
21
|
+
should_not_have_json "error_description"
|
|
20
22
|
end
|
|
21
23
|
|
|
22
|
-
context
|
|
24
|
+
context "with scopes" do
|
|
23
25
|
before do
|
|
24
26
|
optional_scopes_exist :write
|
|
25
27
|
default_scopes_exist :public
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
it
|
|
30
|
+
it "adds the scope to the token an returns in the response" do
|
|
29
31
|
headers = authorization client.uid, client.secret
|
|
30
|
-
params = { grant_type:
|
|
32
|
+
params = { grant_type: "client_credentials", scope: "write" }
|
|
31
33
|
|
|
32
|
-
post
|
|
34
|
+
post "/oauth/token", params: params, headers: headers
|
|
33
35
|
|
|
34
|
-
should_have_json
|
|
35
|
-
should_have_json
|
|
36
|
+
should_have_json "access_token", Doorkeeper::AccessToken.first.token
|
|
37
|
+
should_have_json "scope", "write"
|
|
36
38
|
end
|
|
37
39
|
|
|
38
|
-
context
|
|
39
|
-
it
|
|
40
|
+
context "that are default" do
|
|
41
|
+
it "adds the scope to the token an returns in the response" do
|
|
40
42
|
headers = authorization client.uid, client.secret
|
|
41
|
-
params = { grant_type:
|
|
43
|
+
params = { grant_type: "client_credentials", scope: "public" }
|
|
42
44
|
|
|
43
|
-
post
|
|
45
|
+
post "/oauth/token", params: params, headers: headers
|
|
44
46
|
|
|
45
|
-
should_have_json
|
|
46
|
-
should_have_json
|
|
47
|
+
should_have_json "access_token", Doorkeeper::AccessToken.first.token
|
|
48
|
+
should_have_json "scope", "public"
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
|
|
50
|
-
context
|
|
51
|
-
it
|
|
52
|
+
context "that are invalid" do
|
|
53
|
+
it "does not authorize the client and returns the error" do
|
|
52
54
|
headers = authorization client.uid, client.secret
|
|
53
|
-
params = { grant_type:
|
|
55
|
+
params = { grant_type: "client_credentials", scope: "random" }
|
|
54
56
|
|
|
55
|
-
post
|
|
57
|
+
post "/oauth/token", params: params, headers: headers
|
|
56
58
|
|
|
57
|
-
should_have_json
|
|
58
|
-
should_have_json
|
|
59
|
-
should_not_have_json
|
|
59
|
+
should_have_json "error", "invalid_scope"
|
|
60
|
+
should_have_json "error_description", translated_error_message(:invalid_scope)
|
|
61
|
+
should_not_have_json "access_token"
|
|
60
62
|
|
|
61
|
-
expect(response.status).to eq(
|
|
63
|
+
expect(response.status).to eq(400)
|
|
62
64
|
end
|
|
63
65
|
end
|
|
64
66
|
end
|
|
65
67
|
end
|
|
66
68
|
|
|
67
|
-
context
|
|
69
|
+
context "when application scopes contain some of the default scopes and no scope is passed" do
|
|
68
70
|
before do
|
|
69
|
-
client.
|
|
71
|
+
client.update(scopes: "read write public")
|
|
70
72
|
end
|
|
71
73
|
|
|
72
|
-
it
|
|
74
|
+
it "issues new token with one default scope that are present in application scopes" do
|
|
73
75
|
default_scopes_exist :public
|
|
74
76
|
|
|
75
77
|
headers = authorization client.uid, client.secret
|
|
76
|
-
params = { grant_type:
|
|
78
|
+
params = { grant_type: "client_credentials" }
|
|
77
79
|
|
|
78
80
|
expect do
|
|
79
|
-
post
|
|
81
|
+
post "/oauth/token", params: params, headers: headers
|
|
80
82
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
81
83
|
|
|
82
84
|
token = Doorkeeper::AccessToken.first
|
|
83
85
|
|
|
84
86
|
expect(token.application_id).to eq client.id
|
|
85
|
-
should_have_json
|
|
86
|
-
should_have_json
|
|
87
|
+
should_have_json "access_token", token.token
|
|
88
|
+
should_have_json "scope", "public"
|
|
87
89
|
end
|
|
88
90
|
|
|
89
|
-
it
|
|
91
|
+
it "issues new token with multiple default scopes that are present in application scopes" do
|
|
90
92
|
default_scopes_exist :public, :read, :update
|
|
91
93
|
|
|
92
94
|
headers = authorization client.uid, client.secret
|
|
93
|
-
params = { grant_type:
|
|
95
|
+
params = { grant_type: "client_credentials" }
|
|
94
96
|
|
|
95
97
|
expect do
|
|
96
|
-
post
|
|
98
|
+
post "/oauth/token", params: params, headers: headers
|
|
97
99
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
98
100
|
|
|
99
101
|
token = Doorkeeper::AccessToken.first
|
|
100
102
|
|
|
101
103
|
expect(token.application_id).to eq client.id
|
|
102
|
-
should_have_json
|
|
103
|
-
should_have_json
|
|
104
|
+
should_have_json "access_token", token.token
|
|
105
|
+
should_have_json "scope", "public read"
|
|
104
106
|
end
|
|
105
107
|
end
|
|
106
108
|
|
|
107
|
-
context
|
|
108
|
-
it
|
|
109
|
+
context "an invalid request" do
|
|
110
|
+
it "does not authorize the client and returns the error" do
|
|
109
111
|
headers = {}
|
|
110
|
-
params = { grant_type:
|
|
112
|
+
params = { grant_type: "client_credentials" }
|
|
111
113
|
|
|
112
|
-
post
|
|
114
|
+
post "/oauth/token", params: params, headers: headers
|
|
113
115
|
|
|
114
|
-
should_have_json
|
|
115
|
-
should_have_json
|
|
116
|
-
should_not_have_json
|
|
116
|
+
should_have_json "error", "invalid_client"
|
|
117
|
+
should_have_json "error_description", translated_error_message(:invalid_client)
|
|
118
|
+
should_not_have_json "access_token"
|
|
117
119
|
|
|
118
120
|
expect(response.status).to eq(401)
|
|
119
121
|
end
|
|
@@ -121,6 +123,6 @@ describe 'Client Credentials Request' do
|
|
|
121
123
|
|
|
122
124
|
def authorization(username, password)
|
|
123
125
|
credentials = ActionController::HttpAuthentication::Basic.encode_credentials username, password
|
|
124
|
-
{
|
|
126
|
+
{ "HTTP_AUTHORIZATION" => credentials }
|
|
125
127
|
end
|
|
126
128
|
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
feature "Implicit Grant Flow Errors" do
|
|
4
6
|
background do
|
|
5
|
-
config_is_set(:authenticate_resource_owner) { User.first || redirect_to(
|
|
7
|
+
config_is_set(:authenticate_resource_owner) { User.first || redirect_to("/sign_in") }
|
|
6
8
|
config_is_set(:grant_flows, ["implicit"])
|
|
7
9
|
client_exists
|
|
8
10
|
create_resource_owner
|
|
@@ -15,17 +17,17 @@ feature 'Implicit Grant Flow Errors' do
|
|
|
15
17
|
|
|
16
18
|
[
|
|
17
19
|
%i[client_id invalid_client],
|
|
18
|
-
%i[redirect_uri invalid_redirect_uri]
|
|
20
|
+
%i[redirect_uri invalid_redirect_uri],
|
|
19
21
|
].each do |error|
|
|
20
22
|
scenario "displays #{error.last} error for invalid #{error.first}" do
|
|
21
|
-
visit authorization_endpoint_url(client: @client, error.first =>
|
|
22
|
-
i_should_not_see
|
|
23
|
+
visit authorization_endpoint_url(client: @client, error.first => "invalid", response_type: "token")
|
|
24
|
+
i_should_not_see "Authorize"
|
|
23
25
|
i_should_see_translated_error_message error.last
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
scenario "displays #{error.last} error when #{error.first} is missing" do
|
|
27
|
-
visit authorization_endpoint_url(client: @client, error.first =>
|
|
28
|
-
i_should_not_see
|
|
29
|
+
visit authorization_endpoint_url(client: @client, error.first => "", response_type: "token")
|
|
30
|
+
i_should_not_see "Authorize"
|
|
29
31
|
i_should_see_translated_error_message error.last
|
|
30
32
|
end
|
|
31
33
|
end
|
|
@@ -1,57 +1,59 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
feature "Implicit Grant Flow (feature spec)" do
|
|
4
6
|
background do
|
|
5
|
-
config_is_set(:authenticate_resource_owner) { User.first || redirect_to(
|
|
7
|
+
config_is_set(:authenticate_resource_owner) { User.first || redirect_to("/sign_in") }
|
|
6
8
|
config_is_set(:grant_flows, ["implicit"])
|
|
7
9
|
client_exists
|
|
8
10
|
create_resource_owner
|
|
9
11
|
sign_in
|
|
10
12
|
end
|
|
11
13
|
|
|
12
|
-
scenario
|
|
13
|
-
visit authorization_endpoint_url(client: @client, response_type:
|
|
14
|
-
click_on
|
|
14
|
+
scenario "resource owner authorizes the client" do
|
|
15
|
+
visit authorization_endpoint_url(client: @client, response_type: "token")
|
|
16
|
+
click_on "Authorize"
|
|
15
17
|
|
|
16
18
|
access_token_should_exist_for @client, @resource_owner
|
|
17
19
|
|
|
18
20
|
i_should_be_on_client_callback @client
|
|
19
21
|
end
|
|
20
22
|
|
|
21
|
-
context
|
|
23
|
+
context "when application scopes are present and no scope is passed" do
|
|
22
24
|
background do
|
|
23
|
-
@client.
|
|
25
|
+
@client.update(scopes: "public write read")
|
|
24
26
|
end
|
|
25
27
|
|
|
26
|
-
scenario
|
|
28
|
+
scenario "access token has no scopes" do
|
|
27
29
|
default_scopes_exist :admin
|
|
28
|
-
visit authorization_endpoint_url(client: @client, response_type:
|
|
29
|
-
click_on
|
|
30
|
+
visit authorization_endpoint_url(client: @client, response_type: "token")
|
|
31
|
+
click_on "Authorize"
|
|
30
32
|
access_token_should_exist_for @client, @resource_owner
|
|
31
33
|
token = Doorkeeper::AccessToken.first
|
|
32
34
|
expect(token.scopes).to be_empty
|
|
33
35
|
end
|
|
34
36
|
|
|
35
|
-
scenario
|
|
37
|
+
scenario "access token has scopes which are common in application scopees and default scopes" do
|
|
36
38
|
default_scopes_exist :public, :write
|
|
37
|
-
visit authorization_endpoint_url(client: @client, response_type:
|
|
38
|
-
click_on
|
|
39
|
+
visit authorization_endpoint_url(client: @client, response_type: "token")
|
|
40
|
+
click_on "Authorize"
|
|
39
41
|
access_token_should_exist_for @client, @resource_owner
|
|
40
42
|
access_token_should_have_scopes :public, :write
|
|
41
43
|
end
|
|
42
44
|
end
|
|
43
45
|
end
|
|
44
46
|
|
|
45
|
-
describe
|
|
47
|
+
describe "Implicit Grant Flow (request spec)" do
|
|
46
48
|
before do
|
|
47
|
-
config_is_set(:authenticate_resource_owner) { User.first || redirect_to(
|
|
49
|
+
config_is_set(:authenticate_resource_owner) { User.first || redirect_to("/sign_in") }
|
|
48
50
|
config_is_set(:grant_flows, ["implicit"])
|
|
49
51
|
client_exists
|
|
50
52
|
create_resource_owner
|
|
51
53
|
end
|
|
52
54
|
|
|
53
|
-
context
|
|
54
|
-
it
|
|
55
|
+
context "token reuse" do
|
|
56
|
+
it "should return a new token each request" do
|
|
55
57
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(false)
|
|
56
58
|
|
|
57
59
|
token = client_is_authorized(@client, @resource_owner)
|
|
@@ -59,16 +61,16 @@ describe 'Implicit Grant Flow (request spec)' do
|
|
|
59
61
|
post "/oauth/authorize",
|
|
60
62
|
params: {
|
|
61
63
|
client_id: @client.uid,
|
|
62
|
-
state:
|
|
64
|
+
state: "",
|
|
63
65
|
redirect_uri: @client.redirect_uri,
|
|
64
|
-
response_type:
|
|
65
|
-
commit:
|
|
66
|
+
response_type: "token",
|
|
67
|
+
commit: "Authorize",
|
|
66
68
|
}
|
|
67
69
|
|
|
68
70
|
expect(response.location).not_to include(token.token)
|
|
69
71
|
end
|
|
70
72
|
|
|
71
|
-
it
|
|
73
|
+
it "should return the same token if it is still accessible" do
|
|
72
74
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
|
73
75
|
|
|
74
76
|
token = client_is_authorized(@client, @resource_owner)
|
|
@@ -76,10 +78,10 @@ describe 'Implicit Grant Flow (request spec)' do
|
|
|
76
78
|
post "/oauth/authorize",
|
|
77
79
|
params: {
|
|
78
80
|
client_id: @client.uid,
|
|
79
|
-
state:
|
|
81
|
+
state: "",
|
|
80
82
|
redirect_uri: @client.redirect_uri,
|
|
81
|
-
response_type:
|
|
82
|
-
commit:
|
|
83
|
+
response_type: "token",
|
|
84
|
+
commit: "Authorize",
|
|
83
85
|
}
|
|
84
86
|
|
|
85
87
|
expect(response.location).to include(token.token)
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
|
|
1
|
+
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe "Resource Owner Password Credentials Flow not set up" do
|
|
4
6
|
before do
|
|
5
7
|
client_exists
|
|
6
8
|
create_resource_owner
|
|
7
9
|
end
|
|
8
10
|
|
|
9
|
-
context
|
|
10
|
-
it
|
|
11
|
+
context "with valid user credentials" do
|
|
12
|
+
it "does not issue new token" do
|
|
11
13
|
expect do
|
|
12
14
|
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
13
15
|
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
@@ -15,8 +17,8 @@ describe 'Resource Owner Password Credentials Flow not set up' do
|
|
|
15
17
|
end
|
|
16
18
|
end
|
|
17
19
|
|
|
18
|
-
describe
|
|
19
|
-
let(:client_attributes) { {} }
|
|
20
|
+
describe "Resource Owner Password Credentials Flow" do
|
|
21
|
+
let(:client_attributes) { { redirect_uri: nil } }
|
|
20
22
|
|
|
21
23
|
before do
|
|
22
24
|
config_is_set(:grant_flows, ["password"])
|
|
@@ -25,7 +27,7 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
25
27
|
create_resource_owner
|
|
26
28
|
end
|
|
27
29
|
|
|
28
|
-
context
|
|
30
|
+
context "with valid user credentials" do
|
|
29
31
|
context "with non-confidential/public client" do
|
|
30
32
|
let(:client_attributes) { { confidential: false } }
|
|
31
33
|
|
|
@@ -38,7 +40,7 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
38
40
|
token = Doorkeeper::AccessToken.first
|
|
39
41
|
|
|
40
42
|
expect(token.application_id).to eq @client.id
|
|
41
|
-
should_have_json
|
|
43
|
+
should_have_json "access_token", token.token
|
|
42
44
|
end
|
|
43
45
|
end
|
|
44
46
|
|
|
@@ -51,7 +53,7 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
51
53
|
token = Doorkeeper::AccessToken.first
|
|
52
54
|
|
|
53
55
|
expect(token.application_id).to eq @client.id
|
|
54
|
-
should_have_json
|
|
56
|
+
should_have_json "access_token", token.token
|
|
55
57
|
end
|
|
56
58
|
|
|
57
59
|
context "when client_secret incorrect" do
|
|
@@ -59,12 +61,13 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
59
61
|
expect do
|
|
60
62
|
post password_token_endpoint_url(
|
|
61
63
|
client_id: @client.uid,
|
|
62
|
-
client_secret:
|
|
64
|
+
client_secret: "foobar",
|
|
63
65
|
resource_owner: @resource_owner
|
|
64
66
|
)
|
|
65
67
|
end.not_to(change { Doorkeeper::AccessToken.count })
|
|
66
68
|
|
|
67
|
-
expect(response).
|
|
69
|
+
expect(response.status).to eq(401)
|
|
70
|
+
should_have_json "error", "invalid_client"
|
|
68
71
|
end
|
|
69
72
|
end
|
|
70
73
|
end
|
|
@@ -79,7 +82,7 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
79
82
|
token = Doorkeeper::AccessToken.first
|
|
80
83
|
|
|
81
84
|
expect(token.application_id).to eq @client.id
|
|
82
|
-
should_have_json
|
|
85
|
+
should_have_json "access_token", token.token
|
|
83
86
|
end
|
|
84
87
|
|
|
85
88
|
context "when client_secret absent" do
|
|
@@ -88,12 +91,13 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
88
91
|
post password_token_endpoint_url(client_id: @client.uid, resource_owner: @resource_owner)
|
|
89
92
|
end.not_to(change { Doorkeeper::AccessToken.count })
|
|
90
93
|
|
|
91
|
-
expect(response).
|
|
94
|
+
expect(response.status).to eq(401)
|
|
95
|
+
should_have_json "error", "invalid_client"
|
|
92
96
|
end
|
|
93
97
|
end
|
|
94
98
|
end
|
|
95
99
|
|
|
96
|
-
it
|
|
100
|
+
it "should issue new token without client credentials" do
|
|
97
101
|
expect do
|
|
98
102
|
post password_token_endpoint_url(resource_owner: @resource_owner)
|
|
99
103
|
end.to(change { Doorkeeper::AccessToken.count }.by(1))
|
|
@@ -101,20 +105,20 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
101
105
|
token = Doorkeeper::AccessToken.first
|
|
102
106
|
|
|
103
107
|
expect(token.application_id).to be_nil
|
|
104
|
-
should_have_json
|
|
108
|
+
should_have_json "access_token", token.token
|
|
105
109
|
end
|
|
106
110
|
|
|
107
|
-
it
|
|
111
|
+
it "should issue a refresh token if enabled" do
|
|
108
112
|
config_is_set(:refresh_token_enabled, true)
|
|
109
113
|
|
|
110
114
|
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
111
115
|
|
|
112
116
|
token = Doorkeeper::AccessToken.first
|
|
113
117
|
|
|
114
|
-
should_have_json
|
|
118
|
+
should_have_json "refresh_token", token.refresh_token
|
|
115
119
|
end
|
|
116
120
|
|
|
117
|
-
it
|
|
121
|
+
it "should return the same token if it is still accessible" do
|
|
118
122
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
|
119
123
|
|
|
120
124
|
client_is_authorized(@client, @resource_owner)
|
|
@@ -122,35 +126,35 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
122
126
|
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
123
127
|
|
|
124
128
|
expect(Doorkeeper::AccessToken.count).to be(1)
|
|
125
|
-
should_have_json
|
|
129
|
+
should_have_json "access_token", Doorkeeper::AccessToken.first.token
|
|
126
130
|
end
|
|
127
131
|
|
|
128
|
-
context
|
|
132
|
+
context "with valid, default scope" do
|
|
129
133
|
before do
|
|
130
134
|
default_scopes_exist :public
|
|
131
135
|
end
|
|
132
136
|
|
|
133
|
-
it
|
|
137
|
+
it "should issue new token" do
|
|
134
138
|
expect do
|
|
135
|
-
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner, scope:
|
|
139
|
+
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner, scope: "public")
|
|
136
140
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
137
141
|
|
|
138
142
|
token = Doorkeeper::AccessToken.first
|
|
139
143
|
|
|
140
144
|
expect(token.application_id).to eq @client.id
|
|
141
|
-
should_have_json
|
|
142
|
-
should_have_json
|
|
145
|
+
should_have_json "access_token", token.token
|
|
146
|
+
should_have_json "scope", "public"
|
|
143
147
|
end
|
|
144
148
|
end
|
|
145
149
|
end
|
|
146
150
|
|
|
147
|
-
context
|
|
151
|
+
context "when application scopes are present and differs from configured default scopes and no scope is passed" do
|
|
148
152
|
before do
|
|
149
153
|
default_scopes_exist :public
|
|
150
|
-
@client.
|
|
154
|
+
@client.update(scopes: "abc")
|
|
151
155
|
end
|
|
152
156
|
|
|
153
|
-
it
|
|
157
|
+
it "issues new token without any scope" do
|
|
154
158
|
expect do
|
|
155
159
|
post password_token_endpoint_url(client: @client, resource_owner: @resource_owner)
|
|
156
160
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
|
@@ -159,17 +163,17 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
159
163
|
|
|
160
164
|
expect(token.application_id).to eq @client.id
|
|
161
165
|
expect(token.scopes).to be_empty
|
|
162
|
-
should_have_json
|
|
163
|
-
should_not_have_json
|
|
166
|
+
should_have_json "access_token", token.token
|
|
167
|
+
should_not_have_json "scope"
|
|
164
168
|
end
|
|
165
169
|
end
|
|
166
170
|
|
|
167
|
-
context
|
|
171
|
+
context "when application scopes contain some of the default scopes and no scope is passed" do
|
|
168
172
|
before do
|
|
169
|
-
@client.
|
|
173
|
+
@client.update(scopes: "read write public")
|
|
170
174
|
end
|
|
171
175
|
|
|
172
|
-
it
|
|
176
|
+
it "issues new token with one default scope that are present in application scopes" do
|
|
173
177
|
default_scopes_exist :public, :admin
|
|
174
178
|
|
|
175
179
|
expect do
|
|
@@ -179,11 +183,11 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
179
183
|
token = Doorkeeper::AccessToken.first
|
|
180
184
|
|
|
181
185
|
expect(token.application_id).to eq @client.id
|
|
182
|
-
should_have_json
|
|
183
|
-
should_have_json
|
|
186
|
+
should_have_json "access_token", token.token
|
|
187
|
+
should_have_json "scope", "public"
|
|
184
188
|
end
|
|
185
189
|
|
|
186
|
-
it
|
|
190
|
+
it "issues new token with multiple default scopes that are present in application scopes" do
|
|
187
191
|
default_scopes_exist :public, :read, :update
|
|
188
192
|
|
|
189
193
|
expect do
|
|
@@ -193,62 +197,62 @@ describe 'Resource Owner Password Credentials Flow' do
|
|
|
193
197
|
token = Doorkeeper::AccessToken.first
|
|
194
198
|
|
|
195
199
|
expect(token.application_id).to eq @client.id
|
|
196
|
-
should_have_json
|
|
197
|
-
should_have_json
|
|
200
|
+
should_have_json "access_token", token.token
|
|
201
|
+
should_have_json "scope", "public read"
|
|
198
202
|
end
|
|
199
203
|
end
|
|
200
204
|
|
|
201
|
-
context
|
|
205
|
+
context "with invalid scopes" do
|
|
202
206
|
subject do
|
|
203
207
|
post password_token_endpoint_url(client: @client,
|
|
204
208
|
resource_owner: @resource_owner,
|
|
205
|
-
scope:
|
|
209
|
+
scope: "random")
|
|
206
210
|
end
|
|
207
211
|
|
|
208
|
-
it
|
|
212
|
+
it "should not issue new token" do
|
|
209
213
|
expect { subject }.to_not(change { Doorkeeper::AccessToken.count })
|
|
210
214
|
end
|
|
211
215
|
|
|
212
|
-
it
|
|
216
|
+
it "should return invalid_scope error" do
|
|
213
217
|
subject
|
|
214
|
-
should_have_json
|
|
215
|
-
should_have_json
|
|
216
|
-
should_not_have_json
|
|
218
|
+
should_have_json "error", "invalid_scope"
|
|
219
|
+
should_have_json "error_description", translated_error_message(:invalid_scope)
|
|
220
|
+
should_not_have_json "access_token"
|
|
217
221
|
|
|
218
|
-
expect(response.status).to eq(
|
|
222
|
+
expect(response.status).to eq(400)
|
|
219
223
|
end
|
|
220
224
|
end
|
|
221
225
|
|
|
222
|
-
context
|
|
223
|
-
it
|
|
226
|
+
context "with invalid user credentials" do
|
|
227
|
+
it "should not issue new token with bad password" do
|
|
224
228
|
expect do
|
|
225
229
|
post password_token_endpoint_url(client: @client,
|
|
226
230
|
resource_owner_username: @resource_owner.name,
|
|
227
|
-
resource_owner_password:
|
|
231
|
+
resource_owner_password: "wrongpassword")
|
|
228
232
|
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
229
233
|
end
|
|
230
234
|
|
|
231
|
-
it
|
|
235
|
+
it "should not issue new token without credentials" do
|
|
232
236
|
expect do
|
|
233
237
|
post password_token_endpoint_url(client: @client)
|
|
234
238
|
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
235
239
|
end
|
|
236
240
|
end
|
|
237
241
|
|
|
238
|
-
context
|
|
239
|
-
it
|
|
242
|
+
context "with invalid confidential client credentials" do
|
|
243
|
+
it "should not issue new token with bad client credentials" do
|
|
240
244
|
expect do
|
|
241
245
|
post password_token_endpoint_url(client_id: @client.uid,
|
|
242
|
-
client_secret:
|
|
246
|
+
client_secret: "bad_secret",
|
|
243
247
|
resource_owner: @resource_owner)
|
|
244
248
|
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
245
249
|
end
|
|
246
250
|
end
|
|
247
251
|
|
|
248
|
-
context
|
|
249
|
-
it
|
|
252
|
+
context "with invalid public client id" do
|
|
253
|
+
it "should not issue new token with bad client id" do
|
|
250
254
|
expect do
|
|
251
|
-
post password_token_endpoint_url(client_id:
|
|
255
|
+
post password_token_endpoint_url(client_id: "bad_id", resource_owner: @resource_owner)
|
|
252
256
|
end.to_not(change { Doorkeeper::AccessToken.count })
|
|
253
257
|
end
|
|
254
258
|
end
|