doorkeeper 5.1.0.rc2 → 5.1.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/.hound.yml +2 -1
- data/.rubocop.yml +37 -4
- data/.travis.yml +4 -27
- data/Appraisals +8 -12
- data/Gemfile +6 -2
- data/NEWS.md +16 -0
- data/README.md +11 -2
- 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 +17 -5
- data/app/controllers/doorkeeper/token_info_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +7 -7
- 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/bin/console +5 -4
- data/config/locales/en.yml +1 -0
- data/doorkeeper.gemspec +24 -22
- data/gemfiles/rails_5_0.gemfile +2 -1
- data/gemfiles/rails_5_1.gemfile +2 -1
- data/gemfiles/rails_5_2.gemfile +2 -1
- data/gemfiles/rails_6_0.gemfile +1 -0
- data/gemfiles/rails_master.gemfile +1 -0
- data/lib/doorkeeper.rb +68 -66
- data/lib/doorkeeper/config.rb +53 -90
- data/lib/doorkeeper/config/option.rb +64 -0
- 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 +1 -1
- data/lib/doorkeeper/models/access_grant_mixin.rb +4 -2
- data/lib/doorkeeper/models/access_token_mixin.rb +10 -10
- data/lib/doorkeeper/models/application_mixin.rb +1 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +1 -0
- data/lib/doorkeeper/models/concerns/ownership.rb +1 -6
- data/lib/doorkeeper/models/concerns/revocable.rb +2 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +2 -0
- data/lib/doorkeeper/oauth.rb +5 -5
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/token.rb +9 -6
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +1 -1
- data/lib/doorkeeper/oauth/authorization_code_request.rb +5 -3
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
- data/lib/doorkeeper/oauth/error_response.rb +5 -5
- data/lib/doorkeeper/oauth/forbidden_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +2 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +6 -2
- data/lib/doorkeeper/oauth/invalid_token_response.rb +1 -1
- data/lib/doorkeeper/oauth/pre_authorization.rb +4 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +1 -1
- data/lib/doorkeeper/oauth/scopes.rb +5 -3
- data/lib/doorkeeper/oauth/token.rb +2 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +4 -4
- data/lib/doorkeeper/oauth/token_response.rb +9 -9
- data/lib/doorkeeper/orm/active_record.rb +6 -6
- data/lib/doorkeeper/orm/active_record/access_grant.rb +5 -12
- data/lib/doorkeeper/orm/active_record/access_token.rb +6 -13
- data/lib/doorkeeper/orm/active_record/application.rb +6 -5
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +10 -3
- data/lib/doorkeeper/rails/helpers.rb +1 -1
- data/lib/doorkeeper/rails/routes.rb +11 -11
- data/lib/doorkeeper/rails/routes/mapping.rb +7 -7
- data/lib/doorkeeper/rake.rb +1 -1
- data/lib/doorkeeper/rake/db.rake +13 -13
- data/lib/doorkeeper/request.rb +1 -1
- data/lib/doorkeeper/secret_storing/base.rb +7 -6
- data/lib/doorkeeper/secret_storing/bcrypt.rb +4 -3
- data/lib/doorkeeper/secret_storing/plain.rb +4 -4
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +3 -2
- data/lib/doorkeeper/stale_records_cleaner.rb +1 -1
- data/lib/doorkeeper/version.rb +2 -2
- 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 +30 -5
- 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 +10 -10
- data/spec/controllers/applications_controller_spec.rb +54 -52
- data/spec/controllers/authorizations_controller_spec.rb +136 -142
- data/spec/controllers/protected_resources_controller_spec.rb +78 -76
- data/spec/controllers/token_info_controller_spec.rb +13 -11
- data/spec/controllers/tokens_controller_spec.rb +109 -94
- data/spec/dummy/Rakefile +3 -1
- data/spec/dummy/app/controllers/application_controller.rb +2 -0
- 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.ru +3 -1
- data/spec/dummy/config/application.rb +13 -0
- 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/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 +5 -3
- 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 +137 -136
- data/spec/lib/doorkeeper_spec.rb +3 -1
- data/spec/lib/models/expirable_spec.rb +12 -10
- data/spec/lib/models/reusable_spec.rb +6 -6
- data/spec/lib/models/revocable_spec.rb +8 -6
- data/spec/lib/models/scopes_spec.rb +19 -17
- data/spec/lib/models/secret_storable_spec.rb +71 -49
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +17 -15
- data/spec/lib/oauth/authorization_code_request_spec.rb +18 -12
- 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 +13 -11
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +27 -18
- data/spec/lib/oauth/client_credentials/validation_spec.rb +17 -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 +14 -12
- 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 +35 -33
- data/spec/lib/oauth/helpers/unique_token_spec.rb +8 -6
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +103 -101
- data/spec/lib/oauth/invalid_token_response_spec.rb +3 -1
- data/spec/lib/oauth/password_access_token_request_spec.rb +52 -34
- data/spec/lib/oauth/pre_authorization_spec.rb +64 -62
- 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 +66 -26
- data/spec/lib/oauth/token_response_spec.rb +39 -37
- data/spec/lib/oauth/token_spec.rb +51 -49
- data/spec/lib/request/strategy_spec.rb +3 -1
- data/spec/lib/secret_storing/base_spec.rb +23 -23
- data/spec/lib/secret_storing/bcrypt_spec.rb +18 -18
- data/spec/lib/secret_storing/plain_spec.rb +17 -17
- data/spec/lib/secret_storing/sha256_hash_spec.rb +16 -16
- 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 +30 -26
- data/spec/models/doorkeeper/access_token_spec.rb +97 -95
- data/spec/models/doorkeeper/application_spec.rb +98 -57
- 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 +161 -159
- data/spec/requests/flows/client_credentials_spec.rb +53 -51
- 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 +56 -54
- data/spec/requests/flows/refresh_token_spec.rb +45 -43
- data/spec/requests/flows/revoke_token_spec.rb +29 -27
- 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 +67 -65
- data/spec/routing/default_routes_spec.rb +22 -20
- data/spec/routing/scoped_routes_spec.rb +20 -18
- data/spec/spec_helper.rb +14 -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 +3 -3
- 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 +12 -16
- data/gemfiles/rails_4_2.gemfile +0 -17
- data/spec/dummy/config/initializers/new_framework_defaults.rb +0 -8
- data/spec/support/ruby_2_6_rails_4_2_patch.rb +0 -14
@@ -1,29 +1,31 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
module Doorkeeper::OAuth
|
4
6
|
describe PreAuthorization do
|
5
7
|
let(:server) do
|
6
8
|
server = Doorkeeper.configuration
|
7
9
|
allow(server).to receive(:default_scopes).and_return(Scopes.new)
|
8
|
-
allow(server).to receive(:scopes).and_return(Scopes.from_string(
|
10
|
+
allow(server).to receive(:scopes).and_return(Scopes.from_string("public profile"))
|
9
11
|
server
|
10
12
|
end
|
11
13
|
|
12
14
|
let(:application) do
|
13
15
|
application = double :application
|
14
|
-
allow(application).to receive(:scopes).and_return(Scopes.from_string(
|
16
|
+
allow(application).to receive(:scopes).and_return(Scopes.from_string(""))
|
15
17
|
application
|
16
18
|
end
|
17
19
|
|
18
20
|
let(:client) do
|
19
|
-
double :client, redirect_uri:
|
21
|
+
double :client, redirect_uri: "http://tst.com/auth", application: application
|
20
22
|
end
|
21
23
|
|
22
24
|
let :attributes do
|
23
25
|
{
|
24
|
-
response_type:
|
25
|
-
redirect_uri:
|
26
|
-
state:
|
26
|
+
response_type: "code",
|
27
|
+
redirect_uri: "http://tst.com/auth",
|
28
|
+
state: "save-this",
|
27
29
|
}
|
28
30
|
end
|
29
31
|
|
@@ -31,157 +33,157 @@ module Doorkeeper::OAuth
|
|
31
33
|
PreAuthorization.new(server, client, attributes)
|
32
34
|
end
|
33
35
|
|
34
|
-
it
|
36
|
+
it "is authorizable when request is valid" do
|
35
37
|
expect(subject).to be_authorizable
|
36
38
|
end
|
37
39
|
|
38
|
-
it
|
39
|
-
subject.response_type =
|
40
|
+
it "accepts code as response type" do
|
41
|
+
subject.response_type = "code"
|
40
42
|
expect(subject).to be_authorizable
|
41
43
|
end
|
42
44
|
|
43
|
-
it
|
44
|
-
allow(server).to receive(:grant_flows).and_return([
|
45
|
-
subject.response_type =
|
45
|
+
it "accepts token as response type" do
|
46
|
+
allow(server).to receive(:grant_flows).and_return(["implicit"])
|
47
|
+
subject.response_type = "token"
|
46
48
|
expect(subject).to be_authorizable
|
47
49
|
end
|
48
50
|
|
49
|
-
context
|
51
|
+
context "when using default grant flows" do
|
50
52
|
it 'accepts "code" as response type' do
|
51
|
-
subject.response_type =
|
53
|
+
subject.response_type = "code"
|
52
54
|
expect(subject).to be_authorizable
|
53
55
|
end
|
54
56
|
|
55
57
|
it 'accepts "token" as response type' do
|
56
|
-
allow(server).to receive(:grant_flows).and_return([
|
57
|
-
subject.response_type =
|
58
|
+
allow(server).to receive(:grant_flows).and_return(["implicit"])
|
59
|
+
subject.response_type = "token"
|
58
60
|
expect(subject).to be_authorizable
|
59
61
|
end
|
60
62
|
end
|
61
63
|
|
62
|
-
context
|
64
|
+
context "when authorization code grant flow is disabled" do
|
63
65
|
before do
|
64
|
-
allow(server).to receive(:grant_flows).and_return([
|
66
|
+
allow(server).to receive(:grant_flows).and_return(["implicit"])
|
65
67
|
end
|
66
68
|
|
67
69
|
it 'does not accept "code" as response type' do
|
68
|
-
subject.response_type =
|
70
|
+
subject.response_type = "code"
|
69
71
|
expect(subject).not_to be_authorizable
|
70
72
|
end
|
71
73
|
end
|
72
74
|
|
73
|
-
context
|
75
|
+
context "when implicit grant flow is disabled" do
|
74
76
|
before do
|
75
|
-
allow(server).to receive(:grant_flows).and_return([
|
77
|
+
allow(server).to receive(:grant_flows).and_return(["authorization_code"])
|
76
78
|
end
|
77
79
|
|
78
80
|
it 'does not accept "token" as response type' do
|
79
|
-
subject.response_type =
|
81
|
+
subject.response_type = "token"
|
80
82
|
expect(subject).not_to be_authorizable
|
81
83
|
end
|
82
84
|
end
|
83
85
|
|
84
|
-
context
|
85
|
-
it
|
86
|
-
subject.scope =
|
86
|
+
context "client application does not restrict valid scopes" do
|
87
|
+
it "accepts valid scopes" do
|
88
|
+
subject.scope = "public"
|
87
89
|
expect(subject).to be_authorizable
|
88
90
|
end
|
89
91
|
|
90
|
-
it
|
91
|
-
subject.scope =
|
92
|
+
it "rejects (globally) non-valid scopes" do
|
93
|
+
subject.scope = "invalid"
|
92
94
|
expect(subject).not_to be_authorizable
|
93
95
|
end
|
94
96
|
|
95
|
-
it
|
97
|
+
it "accepts scopes which are permitted for grant_type" do
|
96
98
|
allow(server).to receive(:scopes_by_grant_type).and_return(authorization_code: [:public])
|
97
|
-
subject.scope =
|
99
|
+
subject.scope = "public"
|
98
100
|
expect(subject).to be_authorizable
|
99
101
|
end
|
100
102
|
|
101
|
-
it
|
103
|
+
it "rejects scopes which are not permitted for grant_type" do
|
102
104
|
allow(server).to receive(:scopes_by_grant_type).and_return(authorization_code: [:profile])
|
103
|
-
subject.scope =
|
105
|
+
subject.scope = "public"
|
104
106
|
expect(subject).not_to be_authorizable
|
105
107
|
end
|
106
108
|
end
|
107
109
|
|
108
|
-
context
|
110
|
+
context "client application restricts valid scopes" do
|
109
111
|
let(:application) do
|
110
112
|
application = double :application
|
111
|
-
allow(application).to receive(:scopes).and_return(Scopes.from_string(
|
113
|
+
allow(application).to receive(:scopes).and_return(Scopes.from_string("public nonsense"))
|
112
114
|
application
|
113
115
|
end
|
114
116
|
|
115
|
-
it
|
116
|
-
subject.scope =
|
117
|
+
it "accepts valid scopes" do
|
118
|
+
subject.scope = "public"
|
117
119
|
expect(subject).to be_authorizable
|
118
120
|
end
|
119
121
|
|
120
|
-
it
|
121
|
-
subject.scope =
|
122
|
+
it "rejects (globally) non-valid scopes" do
|
123
|
+
subject.scope = "invalid"
|
122
124
|
expect(subject).not_to be_authorizable
|
123
125
|
end
|
124
126
|
|
125
|
-
it
|
126
|
-
subject.scope =
|
127
|
+
it "rejects (application level) non-valid scopes" do
|
128
|
+
subject.scope = "profile"
|
127
129
|
expect(subject).to_not be_authorizable
|
128
130
|
end
|
129
131
|
|
130
|
-
it
|
132
|
+
it "accepts scopes which are permitted for grant_type" do
|
131
133
|
allow(server).to receive(:scopes_by_grant_type).and_return(authorization_code: [:public])
|
132
|
-
subject.scope =
|
134
|
+
subject.scope = "public"
|
133
135
|
expect(subject).to be_authorizable
|
134
136
|
end
|
135
137
|
|
136
|
-
it
|
138
|
+
it "rejects scopes which are not permitted for grant_type" do
|
137
139
|
allow(server).to receive(:scopes_by_grant_type).and_return(authorization_code: [:profile])
|
138
|
-
subject.scope =
|
140
|
+
subject.scope = "public"
|
139
141
|
expect(subject).not_to be_authorizable
|
140
142
|
end
|
141
143
|
end
|
142
144
|
|
143
|
-
it
|
144
|
-
allow(server).to receive(:default_scopes).and_return(Scopes.from_string(
|
145
|
+
it "uses default scopes when none is required" do
|
146
|
+
allow(server).to receive(:default_scopes).and_return(Scopes.from_string("default"))
|
145
147
|
subject.scope = nil
|
146
|
-
expect(subject.scope).to eq(
|
147
|
-
expect(subject.scopes).to eq(Scopes.from_string(
|
148
|
+
expect(subject.scope).to eq("default")
|
149
|
+
expect(subject.scopes).to eq(Scopes.from_string("default"))
|
148
150
|
end
|
149
151
|
|
150
|
-
context
|
151
|
-
let(:native_redirect_uri) {
|
152
|
+
context "with native redirect uri" do
|
153
|
+
let(:native_redirect_uri) { "urn:ietf:wg:oauth:2.0:oob" }
|
152
154
|
|
153
|
-
it
|
155
|
+
it "accepts redirect_uri when it matches with the client" do
|
154
156
|
subject.redirect_uri = native_redirect_uri
|
155
157
|
allow(subject.client).to receive(:redirect_uri) { native_redirect_uri }
|
156
158
|
expect(subject).to be_authorizable
|
157
159
|
end
|
158
160
|
|
159
|
-
it
|
160
|
-
subject.redirect_uri =
|
161
|
+
it "invalidates redirect_uri when it does'n match with the client" do
|
162
|
+
subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
|
161
163
|
expect(subject).not_to be_authorizable
|
162
164
|
end
|
163
165
|
end
|
164
166
|
|
165
|
-
it
|
166
|
-
subject.redirect_uri =
|
167
|
+
it "matches the redirect uri against client's one" do
|
168
|
+
subject.redirect_uri = "http://nothesame.com"
|
167
169
|
expect(subject).not_to be_authorizable
|
168
170
|
end
|
169
171
|
|
170
|
-
it
|
171
|
-
expect(subject.state).to eq(
|
172
|
+
it "stores the state" do
|
173
|
+
expect(subject.state).to eq("save-this")
|
172
174
|
end
|
173
175
|
|
174
|
-
it
|
175
|
-
subject.response_type =
|
176
|
+
it "rejects if response type is not allowed" do
|
177
|
+
subject.response_type = "whops"
|
176
178
|
expect(subject).not_to be_authorizable
|
177
179
|
end
|
178
180
|
|
179
|
-
it
|
181
|
+
it "requires an existing client" do
|
180
182
|
subject.client = nil
|
181
183
|
expect(subject).not_to be_authorizable
|
182
184
|
end
|
183
185
|
|
184
|
-
it
|
186
|
+
it "requires a redirect uri" do
|
185
187
|
subject.redirect_uri = nil
|
186
188
|
expect(subject).not_to be_authorizable
|
187
189
|
end
|
@@ -206,7 +208,7 @@ module Doorkeeper::OAuth
|
|
206
208
|
expect(json[:response_type]).to eq subject.response_type
|
207
209
|
expect(json[:scope]).to eq subject.scope
|
208
210
|
expect(json[:client_name]).to eq client_name
|
209
|
-
expect(json[:status]).to eq I18n.t(
|
211
|
+
expect(json[:status]).to eq I18n.t("doorkeeper.pre_authorization.status")
|
210
212
|
end
|
211
213
|
end
|
212
214
|
end
|
@@ -1,15 +1,12 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
module Doorkeeper::OAuth
|
4
6
|
describe RefreshTokenRequest do
|
5
|
-
before do
|
6
|
-
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
7
|
-
end
|
8
|
-
|
9
7
|
let(:server) do
|
10
8
|
double :server,
|
11
|
-
access_token_expires_in: 2.minutes
|
12
|
-
custom_access_token_expires_in: ->(_context) { nil }
|
9
|
+
access_token_expires_in: 2.minutes
|
13
10
|
end
|
14
11
|
|
15
12
|
let(:refresh_token) do
|
@@ -19,21 +16,27 @@ module Doorkeeper::OAuth
|
|
19
16
|
let(:client) { refresh_token.application }
|
20
17
|
let(:credentials) { Client::Credentials.new(client.uid, client.secret) }
|
21
18
|
|
19
|
+
before do
|
20
|
+
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
21
|
+
allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(false)
|
22
|
+
end
|
23
|
+
|
22
24
|
subject { RefreshTokenRequest.new server, refresh_token, credentials }
|
23
25
|
|
24
|
-
it
|
26
|
+
it "issues a new token for the client" do
|
25
27
|
expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
|
26
28
|
# #sort_by used for MongoDB ORM extensions for valid ordering
|
27
29
|
expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(120)
|
28
30
|
end
|
29
31
|
|
30
|
-
it
|
32
|
+
it "issues a new token for the client with custom expires_in" do
|
31
33
|
server = double :server,
|
32
34
|
access_token_expires_in: 2.minutes,
|
33
35
|
custom_access_token_expires_in: lambda { |context|
|
34
36
|
context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
|
35
37
|
}
|
36
38
|
|
39
|
+
allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
|
37
40
|
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
38
41
|
|
39
42
|
RefreshTokenRequest.new(server, refresh_token, credentials).authorize
|
@@ -42,7 +45,7 @@ module Doorkeeper::OAuth
|
|
42
45
|
expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
|
43
46
|
end
|
44
47
|
|
45
|
-
it
|
48
|
+
it "revokes the previous token" do
|
46
49
|
expect { subject.authorize }.to change { refresh_token.revoked? }.from(false).to(true)
|
47
50
|
end
|
48
51
|
|
@@ -56,13 +59,13 @@ module Doorkeeper::OAuth
|
|
56
59
|
subject.authorize
|
57
60
|
end
|
58
61
|
|
59
|
-
it
|
62
|
+
it "requires the refresh token" do
|
60
63
|
subject.refresh_token = nil
|
61
64
|
subject.validate
|
62
65
|
expect(subject.error).to eq(:invalid_request)
|
63
66
|
end
|
64
67
|
|
65
|
-
it
|
68
|
+
it "requires credentials to be valid if provided" do
|
66
69
|
subject.client = nil
|
67
70
|
subject.validate
|
68
71
|
expect(subject.error).to eq(:invalid_client)
|
@@ -74,20 +77,20 @@ module Doorkeeper::OAuth
|
|
74
77
|
expect(subject.error).to eq(:invalid_grant)
|
75
78
|
end
|
76
79
|
|
77
|
-
it
|
80
|
+
it "rejects revoked tokens" do
|
78
81
|
refresh_token.revoke
|
79
82
|
subject.validate
|
80
83
|
expect(subject.error).to eq(:invalid_grant)
|
81
84
|
end
|
82
85
|
|
83
|
-
it
|
86
|
+
it "accepts expired tokens" do
|
84
87
|
refresh_token.expires_in = -1
|
85
88
|
refresh_token.save
|
86
89
|
subject.validate
|
87
90
|
expect(subject).to be_valid
|
88
91
|
end
|
89
92
|
|
90
|
-
context
|
93
|
+
context "refresh tokens expire on access token use" do
|
91
94
|
let(:server) do
|
92
95
|
double :server,
|
93
96
|
access_token_expires_in: 2.minutes,
|
@@ -100,16 +103,16 @@ module Doorkeeper::OAuth
|
|
100
103
|
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(true)
|
101
104
|
end
|
102
105
|
|
103
|
-
it
|
106
|
+
it "issues a new token for the client" do
|
104
107
|
expect { subject.authorize }.to change { client.reload.access_tokens.count }.by(1)
|
105
108
|
end
|
106
109
|
|
107
|
-
it
|
110
|
+
it "does not revoke the previous token" do
|
108
111
|
subject.authorize
|
109
112
|
expect(refresh_token).not_to be_revoked
|
110
113
|
end
|
111
114
|
|
112
|
-
it
|
115
|
+
it "sets the previous refresh token in the new access token" do
|
113
116
|
subject.authorize
|
114
117
|
expect(
|
115
118
|
# #sort_by used for MongoDB ORM extensions for valid ordering
|
@@ -118,53 +121,53 @@ module Doorkeeper::OAuth
|
|
118
121
|
end
|
119
122
|
end
|
120
123
|
|
121
|
-
context
|
124
|
+
context "clientless access tokens" do
|
122
125
|
let!(:refresh_token) { FactoryBot.create(:clientless_access_token, use_refresh_token: true) }
|
123
126
|
|
124
127
|
subject { RefreshTokenRequest.new server, refresh_token, nil }
|
125
128
|
|
126
|
-
it
|
129
|
+
it "issues a new token without a client" do
|
127
130
|
expect { subject.authorize }.to change { Doorkeeper::AccessToken.count }.by(1)
|
128
131
|
end
|
129
132
|
end
|
130
133
|
|
131
|
-
context
|
134
|
+
context "with scopes" do
|
132
135
|
let(:refresh_token) do
|
133
136
|
FactoryBot.create :access_token,
|
134
137
|
use_refresh_token: true,
|
135
|
-
scopes:
|
138
|
+
scopes: "public write"
|
136
139
|
end
|
137
140
|
let(:parameters) { {} }
|
138
141
|
subject { RefreshTokenRequest.new server, refresh_token, credentials, parameters }
|
139
142
|
|
140
|
-
it
|
143
|
+
it "transfers scopes from the old token to the new token" do
|
141
144
|
subject.authorize
|
142
145
|
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public write])
|
143
146
|
end
|
144
147
|
|
145
|
-
it
|
146
|
-
parameters[:scopes] =
|
148
|
+
it "reduces scopes to the provided scopes" do
|
149
|
+
parameters[:scopes] = "public"
|
147
150
|
subject.authorize
|
148
151
|
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
|
149
152
|
end
|
150
153
|
|
151
|
-
it
|
152
|
-
parameters[:scopes] =
|
154
|
+
it "validates that scopes are included in the original access token" do
|
155
|
+
parameters[:scopes] = "public update"
|
153
156
|
|
154
157
|
subject.validate
|
155
158
|
expect(subject.error).to eq(:invalid_scope)
|
156
159
|
end
|
157
160
|
|
158
|
-
it
|
159
|
-
parameters[:scopes] =
|
160
|
-
parameters[:scope] =
|
161
|
+
it "uses params[:scope] in favor of scopes if present (valid)" do
|
162
|
+
parameters[:scopes] = "public update"
|
163
|
+
parameters[:scope] = "public"
|
161
164
|
subject.authorize
|
162
165
|
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
|
163
166
|
end
|
164
167
|
|
165
|
-
it
|
166
|
-
parameters[:scopes] =
|
167
|
-
parameters[:scope] =
|
168
|
+
it "uses params[:scope] in favor of scopes if present (invalid)" do
|
169
|
+
parameters[:scopes] = "public"
|
170
|
+
parameters[:scope] = "public update"
|
168
171
|
|
169
172
|
subject.validate
|
170
173
|
expect(subject.error).to eq(:invalid_scope)
|
@@ -1,113 +1,115 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
module Doorkeeper::OAuth
|
4
6
|
describe Scopes do
|
5
|
-
describe
|
6
|
-
it
|
7
|
+
describe "#add" do
|
8
|
+
it "allows you to add scopes with symbols" do
|
7
9
|
subject.add :public
|
8
|
-
expect(subject.all).to eq([
|
10
|
+
expect(subject.all).to eq(["public"])
|
9
11
|
end
|
10
12
|
|
11
|
-
it
|
12
|
-
subject.add
|
13
|
-
expect(subject.all).to eq([
|
13
|
+
it "allows you to add scopes with strings" do
|
14
|
+
subject.add "public"
|
15
|
+
expect(subject.all).to eq(["public"])
|
14
16
|
end
|
15
17
|
|
16
|
-
it
|
18
|
+
it "do not add already included scopes" do
|
17
19
|
subject.add :public
|
18
20
|
subject.add :public
|
19
|
-
expect(subject.all).to eq([
|
21
|
+
expect(subject.all).to eq(["public"])
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
23
|
-
describe
|
25
|
+
describe "#exists" do
|
24
26
|
before do
|
25
27
|
subject.add :public
|
26
28
|
end
|
27
29
|
|
28
|
-
it
|
29
|
-
expect(subject.exists?(
|
30
|
+
it "returns true if scope with given name is present" do
|
31
|
+
expect(subject.exists?("public")).to be_truthy
|
30
32
|
end
|
31
33
|
|
32
|
-
it
|
33
|
-
expect(subject.exists?(
|
34
|
+
it "returns false if scope with given name does not exist" do
|
35
|
+
expect(subject.exists?("other")).to be_falsey
|
34
36
|
end
|
35
37
|
|
36
|
-
it
|
38
|
+
it "handles symbols" do
|
37
39
|
expect(subject.exists?(:public)).to be_truthy
|
38
40
|
expect(subject.exists?(:other)).to be_falsey
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
|
-
describe
|
43
|
-
let(:string) {
|
44
|
+
describe ".from_string" do
|
45
|
+
let(:string) { "public write" }
|
44
46
|
|
45
47
|
subject { Scopes.from_string(string) }
|
46
48
|
|
47
49
|
it { expect(subject).to be_a(Scopes) }
|
48
50
|
|
49
|
-
describe
|
50
|
-
it
|
51
|
+
describe "#all" do
|
52
|
+
it "should be an array of the expected scopes" do
|
51
53
|
scopes_array = subject.all
|
52
54
|
expect(scopes_array.size).to eq(2)
|
53
|
-
expect(scopes_array).to include(
|
54
|
-
expect(scopes_array).to include(
|
55
|
+
expect(scopes_array).to include("public")
|
56
|
+
expect(scopes_array).to include("write")
|
55
57
|
end
|
56
58
|
end
|
57
59
|
end
|
58
60
|
|
59
|
-
describe
|
60
|
-
it
|
61
|
-
scopes = Scopes.from_string(
|
61
|
+
describe "#+" do
|
62
|
+
it "can add to another scope object" do
|
63
|
+
scopes = Scopes.from_string("public") + Scopes.from_string("admin")
|
62
64
|
expect(scopes.all).to eq(%w[public admin])
|
63
65
|
end
|
64
66
|
|
65
|
-
it
|
66
|
-
origin = Scopes.from_string(
|
67
|
-
expect(origin.to_s).to eq(
|
67
|
+
it "does not change the existing object" do
|
68
|
+
origin = Scopes.from_string("public")
|
69
|
+
expect(origin.to_s).to eq("public")
|
68
70
|
end
|
69
71
|
|
70
|
-
it
|
71
|
-
scopes = Scopes.from_string(
|
72
|
+
it "can add an array to a scope object" do
|
73
|
+
scopes = Scopes.from_string("public") + ["admin"]
|
72
74
|
expect(scopes.all).to eq(%w[public admin])
|
73
75
|
end
|
74
76
|
|
75
|
-
it
|
77
|
+
it "raises an error if cannot handle addition" do
|
76
78
|
expect do
|
77
|
-
Scopes.from_string(
|
79
|
+
Scopes.from_string("public") + "admin"
|
78
80
|
end.to raise_error(NoMethodError)
|
79
81
|
end
|
80
82
|
end
|
81
83
|
|
82
|
-
describe
|
83
|
-
it
|
84
|
-
scopes = Scopes.from_string(
|
84
|
+
describe "#&" do
|
85
|
+
it "can get intersection with another scope object" do
|
86
|
+
scopes = Scopes.from_string("public admin") & Scopes.from_string("write admin")
|
85
87
|
expect(scopes.all).to eq(%w[admin])
|
86
88
|
end
|
87
89
|
|
88
|
-
it
|
89
|
-
origin = Scopes.from_string(
|
90
|
-
origin & Scopes.from_string(
|
91
|
-
expect(origin.to_s).to eq(
|
90
|
+
it "does not change the existing object" do
|
91
|
+
origin = Scopes.from_string("public admin")
|
92
|
+
origin & Scopes.from_string("write admin")
|
93
|
+
expect(origin.to_s).to eq("public admin")
|
92
94
|
end
|
93
95
|
|
94
|
-
it
|
95
|
-
scopes = Scopes.from_string(
|
96
|
+
it "can get intersection with an array" do
|
97
|
+
scopes = Scopes.from_string("public admin") & %w[write admin]
|
96
98
|
expect(scopes.all).to eq(%w[admin])
|
97
99
|
end
|
98
100
|
end
|
99
101
|
|
100
|
-
describe
|
101
|
-
it
|
102
|
-
expect(Scopes.from_string(
|
102
|
+
describe "#==" do
|
103
|
+
it "is equal to another set of scopes" do
|
104
|
+
expect(Scopes.from_string("public")).to eq(Scopes.from_string("public"))
|
103
105
|
end
|
104
106
|
|
105
|
-
it
|
106
|
-
expect(Scopes.from_string(
|
107
|
+
it "is equal to another set of scopes with no particular order" do
|
108
|
+
expect(Scopes.from_string("public write")).to eq(Scopes.from_string("write public"))
|
107
109
|
end
|
108
110
|
|
109
|
-
it
|
110
|
-
expect(Scopes.from_string(
|
111
|
+
it "differs from another set of scopes when scopes are not the same" do
|
112
|
+
expect(Scopes.from_string("public write")).not_to eq(Scopes.from_string("write"))
|
111
113
|
end
|
112
114
|
|
113
115
|
it "does not raise an error when compared to a non-enumerable object" do
|
@@ -115,31 +117,31 @@ module Doorkeeper::OAuth
|
|
115
117
|
end
|
116
118
|
end
|
117
119
|
|
118
|
-
describe
|
119
|
-
subject { Scopes.from_string(
|
120
|
+
describe "#has_scopes?" do
|
121
|
+
subject { Scopes.from_string("public admin") }
|
120
122
|
|
121
|
-
it
|
122
|
-
expect(subject.has_scopes?(Scopes.from_string(
|
123
|
+
it "returns true when at least one scope is included" do
|
124
|
+
expect(subject.has_scopes?(Scopes.from_string("public"))).to be_truthy
|
123
125
|
end
|
124
126
|
|
125
|
-
it
|
126
|
-
expect(subject.has_scopes?(Scopes.from_string(
|
127
|
+
it "returns true when all scopes are included" do
|
128
|
+
expect(subject.has_scopes?(Scopes.from_string("public admin"))).to be_truthy
|
127
129
|
end
|
128
130
|
|
129
|
-
it
|
130
|
-
expect(subject.has_scopes?(Scopes.from_string(
|
131
|
+
it "is true if all scopes are included in any order" do
|
132
|
+
expect(subject.has_scopes?(Scopes.from_string("admin public"))).to be_truthy
|
131
133
|
end
|
132
134
|
|
133
|
-
it
|
134
|
-
expect(subject.has_scopes?(Scopes.from_string(
|
135
|
+
it "is false if no scopes are included" do
|
136
|
+
expect(subject.has_scopes?(Scopes.from_string("notexistent"))).to be_falsey
|
135
137
|
end
|
136
138
|
|
137
|
-
it
|
138
|
-
expect(subject.has_scopes?(Scopes.from_string(
|
139
|
+
it "returns false when any scope is not included" do
|
140
|
+
expect(subject.has_scopes?(Scopes.from_string("public nope"))).to be_falsey
|
139
141
|
end
|
140
142
|
|
141
|
-
it
|
142
|
-
expect(subject.has_scopes?(Scopes.from_string(
|
143
|
+
it "is false if no scopes are included even for existing ones" do
|
144
|
+
expect(subject.has_scopes?(Scopes.from_string("public admin notexistent"))).to be_falsey
|
143
145
|
end
|
144
146
|
end
|
145
147
|
end
|