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,19 +1,21 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
module Doorkeeper::OAuth::Helpers
|
4
6
|
describe UniqueToken do
|
5
7
|
let :generator do
|
6
|
-
->(size) {
|
8
|
+
->(size) { "a" * size }
|
7
9
|
end
|
8
10
|
|
9
|
-
it
|
11
|
+
it "is able to customize the generator method" do
|
10
12
|
token = UniqueToken.generate(generator: generator)
|
11
|
-
expect(token).to eq(
|
13
|
+
expect(token).to eq("a" * 32)
|
12
14
|
end
|
13
15
|
|
14
|
-
it
|
16
|
+
it "is able to customize the size of the token" do
|
15
17
|
token = UniqueToken.generate(generator: generator, size: 2)
|
16
|
-
expect(token).to eq(
|
18
|
+
expect(token).to eq("aa")
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
@@ -1,244 +1,246 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
module Doorkeeper::OAuth::Helpers
|
4
6
|
describe URIChecker do
|
5
|
-
describe
|
6
|
-
it
|
7
|
-
uri =
|
7
|
+
describe ".valid?" do
|
8
|
+
it "is valid for valid uris" do
|
9
|
+
uri = "http://app.co"
|
8
10
|
expect(URIChecker.valid?(uri)).to be_truthy
|
9
11
|
end
|
10
12
|
|
11
|
-
it
|
12
|
-
uri =
|
13
|
+
it "is valid if include path param" do
|
14
|
+
uri = "http://app.co/path"
|
13
15
|
expect(URIChecker.valid?(uri)).to be_truthy
|
14
16
|
end
|
15
17
|
|
16
|
-
it
|
17
|
-
uri =
|
18
|
+
it "is valid if include query param" do
|
19
|
+
uri = "http://app.co/?query=1"
|
18
20
|
expect(URIChecker.valid?(uri)).to be_truthy
|
19
21
|
end
|
20
22
|
|
21
|
-
it
|
22
|
-
uri =
|
23
|
+
it "is invalid if uri includes fragment" do
|
24
|
+
uri = "http://app.co/test#fragment"
|
23
25
|
expect(URIChecker.valid?(uri)).to be_falsey
|
24
26
|
end
|
25
27
|
|
26
|
-
it
|
27
|
-
uri =
|
28
|
+
it "is invalid if scheme is missing" do
|
29
|
+
uri = "app.co"
|
28
30
|
expect(URIChecker.valid?(uri)).to be_falsey
|
29
31
|
end
|
30
32
|
|
31
|
-
it
|
32
|
-
uri =
|
33
|
+
it "is invalid if is a relative uri" do
|
34
|
+
uri = "/abc/123"
|
33
35
|
expect(URIChecker.valid?(uri)).to be_falsey
|
34
36
|
end
|
35
37
|
|
36
|
-
it
|
37
|
-
uri =
|
38
|
+
it "is invalid if is not a url" do
|
39
|
+
uri = "http://"
|
38
40
|
expect(URIChecker.valid?(uri)).to be_falsey
|
39
41
|
end
|
40
42
|
|
41
|
-
it
|
42
|
-
uri =
|
43
|
+
it "is invalid if is not an uri" do
|
44
|
+
uri = " "
|
43
45
|
expect(URIChecker.valid?(uri)).to be_falsey
|
44
46
|
end
|
45
47
|
|
46
|
-
it
|
47
|
-
uri =
|
48
|
+
it "is valid for native uris" do
|
49
|
+
uri = "urn:ietf:wg:oauth:2.0:oob"
|
48
50
|
expect(URIChecker.valid?(uri)).to be_truthy
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
|
-
describe
|
53
|
-
it
|
54
|
-
uri = client_uri =
|
54
|
+
describe ".matches?" do
|
55
|
+
it "is true if both url matches" do
|
56
|
+
uri = client_uri = "http://app.co/aaa"
|
55
57
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
56
58
|
end
|
57
59
|
|
58
|
-
it
|
59
|
-
uri =
|
60
|
-
client_uri =
|
60
|
+
it "ignores query parameter on comparsion" do
|
61
|
+
uri = "http://app.co/?query=hello"
|
62
|
+
client_uri = "http://app.co"
|
61
63
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
62
64
|
end
|
63
65
|
|
64
66
|
it "doesn't allow non-matching domains through" do
|
65
|
-
uri =
|
66
|
-
client_uri =
|
67
|
+
uri = "http://app.abc/?query=hello"
|
68
|
+
client_uri = "http://app.co"
|
67
69
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
68
70
|
end
|
69
71
|
|
70
72
|
it "doesn't allow non-matching domains that don't start at the beginning" do
|
71
|
-
uri =
|
72
|
-
client_uri =
|
73
|
+
uri = "http://app.co/?query=hello"
|
74
|
+
client_uri = "http://example.com?app.co=test"
|
73
75
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
74
76
|
end
|
75
77
|
|
76
|
-
context
|
77
|
-
it
|
78
|
-
uri =
|
79
|
-
client_uri =
|
78
|
+
context "loopback IP redirect URIs" do
|
79
|
+
it "ignores port for same URIs" do
|
80
|
+
uri = "http://127.0.0.1:5555/auth/callback"
|
81
|
+
client_uri = "http://127.0.0.1:48599/auth/callback"
|
80
82
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
81
83
|
|
82
|
-
uri =
|
83
|
-
client_uri =
|
84
|
+
uri = "http://[::1]:5555/auth/callback"
|
85
|
+
client_uri = "http://[::1]:5555/auth/callback"
|
84
86
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
85
87
|
end
|
86
88
|
|
87
89
|
it "doesn't ignore port for URIs with different queries" do
|
88
|
-
uri =
|
89
|
-
client_uri =
|
90
|
+
uri = "http://127.0.0.1:5555/auth/callback"
|
91
|
+
client_uri = "http://127.0.0.1:48599/auth/callback2"
|
90
92
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
91
93
|
end
|
92
94
|
end
|
93
95
|
|
94
96
|
context "client registered query params" do
|
95
97
|
it "doesn't allow query being absent" do
|
96
|
-
uri =
|
97
|
-
client_uri =
|
98
|
+
uri = "http://app.co"
|
99
|
+
client_uri = "http://app.co/?vendorId=AJ4L7XXW9"
|
98
100
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
99
101
|
end
|
100
102
|
|
101
103
|
it "is false if query values differ but key same" do
|
102
|
-
uri =
|
103
|
-
client_uri =
|
104
|
+
uri = "http://app.co/?vendorId=pancakes"
|
105
|
+
client_uri = "http://app.co/?vendorId=waffles"
|
104
106
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
105
107
|
end
|
106
108
|
|
107
109
|
it "is false if query values same but key differs" do
|
108
|
-
uri =
|
109
|
-
client_uri =
|
110
|
+
uri = "http://app.co/?foo=pancakes"
|
111
|
+
client_uri = "http://app.co/?bar=pancakes"
|
110
112
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
111
113
|
end
|
112
114
|
|
113
115
|
it "is false if query present and match, but unknown queries present" do
|
114
|
-
uri =
|
115
|
-
client_uri =
|
116
|
+
uri = "http://app.co/?vendorId=pancakes&unknown=query"
|
117
|
+
client_uri = "http://app.co/?vendorId=waffles"
|
116
118
|
expect(URIChecker.matches?(uri, client_uri)).to be_falsey
|
117
119
|
end
|
118
120
|
|
119
121
|
it "is true if queries are present and matche" do
|
120
|
-
uri =
|
121
|
-
client_uri =
|
122
|
+
uri = "http://app.co/?vendorId=AJ4L7XXW9&foo=bar"
|
123
|
+
client_uri = "http://app.co/?vendorId=AJ4L7XXW9&foo=bar"
|
122
124
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
123
125
|
end
|
124
126
|
|
125
127
|
it "is true if queries are present, match and in different order" do
|
126
|
-
uri =
|
127
|
-
client_uri =
|
128
|
+
uri = "http://app.co/?bing=bang&foo=bar"
|
129
|
+
client_uri = "http://app.co/?foo=bar&bing=bang"
|
128
130
|
expect(URIChecker.matches?(uri, client_uri)).to be_truthy
|
129
131
|
end
|
130
132
|
end
|
131
133
|
end
|
132
134
|
|
133
|
-
describe
|
134
|
-
it
|
135
|
-
uri = client_uri =
|
135
|
+
describe ".valid_for_authorization?" do
|
136
|
+
it "is true if valid and matches" do
|
137
|
+
uri = client_uri = "http://app.co/aaa"
|
136
138
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
137
139
|
|
138
|
-
uri = client_uri =
|
140
|
+
uri = client_uri = "http://app.co/aaa?b=c"
|
139
141
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
140
142
|
end
|
141
143
|
|
142
|
-
it
|
143
|
-
uri = client_uri =
|
144
|
+
it "is true if uri includes blank query" do
|
145
|
+
uri = client_uri = "http://app.co/aaa?"
|
144
146
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
145
147
|
|
146
|
-
uri =
|
147
|
-
client_uri =
|
148
|
+
uri = "http://app.co/aaa?"
|
149
|
+
client_uri = "http://app.co/aaa"
|
148
150
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
149
151
|
|
150
|
-
uri =
|
151
|
-
client_uri =
|
152
|
+
uri = "http://app.co/aaa"
|
153
|
+
client_uri = "http://app.co/aaa?"
|
152
154
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
153
155
|
end
|
154
156
|
|
155
|
-
it
|
156
|
-
uri =
|
157
|
-
client_uri =
|
157
|
+
it "is false if valid and mismatches" do
|
158
|
+
uri = "http://app.co/aaa"
|
159
|
+
client_uri = "http://app.co/bbb"
|
158
160
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
|
159
161
|
end
|
160
162
|
|
161
|
-
it
|
162
|
-
uri =
|
163
|
+
it "is true if valid and included in array" do
|
164
|
+
uri = "http://app.co/aaa"
|
163
165
|
client_uri = "http://example.com/bbb\nhttp://app.co/aaa"
|
164
166
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_truthy
|
165
167
|
end
|
166
168
|
|
167
|
-
it
|
168
|
-
uri =
|
169
|
+
it "is false if valid and not included in array" do
|
170
|
+
uri = "http://app.co/aaa"
|
169
171
|
client_uri = "http://example.com/bbb\nhttp://app.co/cc"
|
170
172
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be_falsey
|
171
173
|
end
|
172
174
|
|
173
|
-
it
|
174
|
-
uri =
|
175
|
-
client_uri =
|
175
|
+
it "is false if queries does not match" do
|
176
|
+
uri = "http://app.co/aaa?pankcakes=abc"
|
177
|
+
client_uri = "http://app.co/aaa?waffles=abc"
|
176
178
|
expect(URIChecker.valid_for_authorization?(uri, client_uri)).to be false
|
177
179
|
end
|
178
180
|
|
179
|
-
it
|
180
|
-
uri =
|
181
|
-
client_uri =
|
181
|
+
it "calls .matches?" do
|
182
|
+
uri = "http://app.co/aaa?pankcakes=abc"
|
183
|
+
client_uri = "http://app.co/aaa?waffles=abc"
|
182
184
|
expect(URIChecker).to receive(:matches?).with(uri, client_uri).once
|
183
185
|
URIChecker.valid_for_authorization?(uri, client_uri)
|
184
186
|
end
|
185
187
|
|
186
|
-
it
|
187
|
-
uri =
|
188
|
-
client_uri =
|
188
|
+
it "calls .valid?" do
|
189
|
+
uri = "http://app.co/aaa?pankcakes=abc"
|
190
|
+
client_uri = "http://app.co/aaa?waffles=abc"
|
189
191
|
expect(URIChecker).to receive(:valid?).with(uri).once
|
190
192
|
URIChecker.valid_for_authorization?(uri, client_uri)
|
191
193
|
end
|
192
194
|
end
|
193
195
|
|
194
|
-
describe
|
195
|
-
it
|
196
|
-
expect(URIChecker.query_matches?(
|
196
|
+
describe ".query_matches?" do
|
197
|
+
it "is true if no queries" do
|
198
|
+
expect(URIChecker.query_matches?("", "")).to be_truthy
|
197
199
|
expect(URIChecker.query_matches?(nil, nil)).to be_truthy
|
198
200
|
end
|
199
201
|
|
200
|
-
it
|
201
|
-
expect(URIChecker.query_matches?(
|
202
|
+
it "is true if same query" do
|
203
|
+
expect(URIChecker.query_matches?("foo", "foo")).to be_truthy
|
202
204
|
end
|
203
205
|
|
204
|
-
it
|
205
|
-
expect(URIChecker.query_matches?(
|
206
|
+
it "is false if different query" do
|
207
|
+
expect(URIChecker.query_matches?("foo", "bar")).to be_falsey
|
206
208
|
end
|
207
209
|
|
208
|
-
it
|
209
|
-
expect(URIChecker.query_matches?(
|
210
|
+
it "is true if same queries" do
|
211
|
+
expect(URIChecker.query_matches?("foo&bar", "foo&bar")).to be_truthy
|
210
212
|
end
|
211
213
|
|
212
|
-
it
|
213
|
-
expect(URIChecker.query_matches?(
|
214
|
+
it "is true if same queries, different order" do
|
215
|
+
expect(URIChecker.query_matches?("foo&bar", "bar&foo")).to be_truthy
|
214
216
|
end
|
215
217
|
|
216
|
-
it
|
217
|
-
expect(URIChecker.query_matches?(
|
218
|
+
it "is false if one different query" do
|
219
|
+
expect(URIChecker.query_matches?("foo&bang", "foo&bing")).to be_falsey
|
218
220
|
end
|
219
221
|
|
220
|
-
it
|
221
|
-
expect(URIChecker.query_matches?(
|
222
|
+
it "is true if same query with same value" do
|
223
|
+
expect(URIChecker.query_matches?("foo=bar", "foo=bar")).to be_truthy
|
222
224
|
end
|
223
225
|
|
224
|
-
it
|
225
|
-
expect(URIChecker.query_matches?(
|
226
|
+
it "is true if same queries with same values" do
|
227
|
+
expect(URIChecker.query_matches?("foo=bar&bing=bang", "foo=bar&bing=bang")).to be_truthy
|
226
228
|
end
|
227
229
|
|
228
|
-
it
|
229
|
-
expect(URIChecker.query_matches?(
|
230
|
+
it "is true if same queries with same values, different order" do
|
231
|
+
expect(URIChecker.query_matches?("foo=bar&bing=bang", "bing=bang&foo=bar")).to be_truthy
|
230
232
|
end
|
231
233
|
|
232
|
-
it
|
233
|
-
expect(URIChecker.query_matches?(
|
234
|
+
it "is false if same query with different value" do
|
235
|
+
expect(URIChecker.query_matches?("foo=bar", "foo=bang")).to be_falsey
|
234
236
|
end
|
235
237
|
|
236
|
-
it
|
237
|
-
expect(URIChecker.query_matches?(
|
238
|
+
it "is false if some queries missing" do
|
239
|
+
expect(URIChecker.query_matches?("foo=bar", "foo=bar&bing=bang")).to be_falsey
|
238
240
|
end
|
239
241
|
|
240
|
-
it
|
241
|
-
expect(URIChecker.query_matches?(
|
242
|
+
it "is false if some queries different value" do
|
243
|
+
expect(URIChecker.query_matches?("foo=bar&bing=bang", "foo=bar&bing=banana")).to be_falsey
|
242
244
|
end
|
243
245
|
end
|
244
246
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
2
4
|
|
3
5
|
module Doorkeeper::OAuth
|
4
6
|
describe PasswordAccessTokenRequest do
|
@@ -16,11 +18,15 @@ module Doorkeeper::OAuth
|
|
16
18
|
let(:client) { FactoryBot.create(:application) }
|
17
19
|
let(:owner) { double :owner, id: 99 }
|
18
20
|
|
21
|
+
before do
|
22
|
+
allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
|
23
|
+
end
|
24
|
+
|
19
25
|
subject do
|
20
26
|
PasswordAccessTokenRequest.new(server, client, owner)
|
21
27
|
end
|
22
28
|
|
23
|
-
it
|
29
|
+
it "issues a new token for the client" do
|
24
30
|
expect do
|
25
31
|
subject.authorize
|
26
32
|
end.to change { client.reload.access_tokens.count }.by(1)
|
@@ -28,35 +34,35 @@ module Doorkeeper::OAuth
|
|
28
34
|
expect(client.reload.access_tokens.max_by(&:created_at).expires_in).to eq(1234)
|
29
35
|
end
|
30
36
|
|
31
|
-
it
|
37
|
+
it "issues a new token without a client" do
|
32
38
|
expect do
|
33
39
|
subject.client = nil
|
34
40
|
subject.authorize
|
35
41
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
36
42
|
end
|
37
43
|
|
38
|
-
it
|
44
|
+
it "does not issue a new token with an invalid client" do
|
39
45
|
expect do
|
40
46
|
subject.client = nil
|
41
|
-
subject.parameters = { client_id:
|
47
|
+
subject.parameters = { client_id: "bad_id" }
|
42
48
|
subject.authorize
|
43
49
|
end.not_to(change { Doorkeeper::AccessToken.count })
|
44
50
|
|
45
51
|
expect(subject.error).to eq(:invalid_client)
|
46
52
|
end
|
47
53
|
|
48
|
-
it
|
54
|
+
it "requires the owner" do
|
49
55
|
subject.resource_owner = nil
|
50
56
|
subject.validate
|
51
57
|
expect(subject.error).to eq(:invalid_grant)
|
52
58
|
end
|
53
59
|
|
54
|
-
it
|
60
|
+
it "optionally accepts the client" do
|
55
61
|
subject.client = nil
|
56
62
|
expect(subject).to be_valid
|
57
63
|
end
|
58
64
|
|
59
|
-
it
|
65
|
+
it "creates token even when there is already one (default)" do
|
60
66
|
FactoryBot.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
|
61
67
|
|
62
68
|
expect do
|
@@ -64,7 +70,7 @@ module Doorkeeper::OAuth
|
|
64
70
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
65
71
|
end
|
66
72
|
|
67
|
-
it
|
73
|
+
it "skips token creation if there is already one reusable" do
|
68
74
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
69
75
|
FactoryBot.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
|
70
76
|
|
@@ -73,7 +79,7 @@ module Doorkeeper::OAuth
|
|
73
79
|
end.not_to(change { Doorkeeper::AccessToken.count })
|
74
80
|
end
|
75
81
|
|
76
|
-
it
|
82
|
+
it "creates token when there is already one but non reusable" do
|
77
83
|
allow(Doorkeeper.configuration).to receive(:reuse_access_token).and_return(true)
|
78
84
|
FactoryBot.create(:access_token, application_id: client.id, resource_owner_id: owner.id)
|
79
85
|
allow_any_instance_of(Doorkeeper::AccessToken).to receive(:reusable?).and_return(false)
|
@@ -93,49 +99,53 @@ module Doorkeeper::OAuth
|
|
93
99
|
subject.authorize
|
94
100
|
end
|
95
101
|
|
96
|
-
describe
|
102
|
+
describe "with scopes" do
|
97
103
|
subject do
|
98
|
-
PasswordAccessTokenRequest.new(server, client, owner, scope:
|
104
|
+
PasswordAccessTokenRequest.new(server, client, owner, scope: "public")
|
99
105
|
end
|
100
106
|
|
101
|
-
context
|
102
|
-
it
|
103
|
-
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string(
|
107
|
+
context "when scopes_by_grant_type is not configured for grant_type" do
|
108
|
+
it "returns error when scopes are invalid" do
|
109
|
+
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("another"))
|
104
110
|
subject.validate
|
105
111
|
expect(subject.error).to eq(:invalid_scope)
|
106
112
|
end
|
107
113
|
|
108
|
-
it
|
109
|
-
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string(
|
114
|
+
it "creates the token with scopes if scopes are valid" do
|
115
|
+
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("public"))
|
110
116
|
expect do
|
111
117
|
subject.authorize
|
112
118
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
113
119
|
|
114
|
-
expect(Doorkeeper::AccessToken.last.scopes).to include(
|
120
|
+
expect(Doorkeeper::AccessToken.last.scopes).to include("public")
|
115
121
|
end
|
116
122
|
end
|
117
123
|
|
118
|
-
context
|
119
|
-
it
|
120
|
-
allow(server)
|
121
|
-
|
124
|
+
context "when scopes_by_grant_type is configured for grant_type" do
|
125
|
+
it "returns error when scopes are valid but not permitted for grant_type" do
|
126
|
+
allow(server)
|
127
|
+
.to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("public"))
|
128
|
+
allow(Doorkeeper.configuration)
|
129
|
+
.to receive(:scopes_by_grant_type).and_return(password: "another")
|
122
130
|
subject.validate
|
123
131
|
expect(subject.error).to eq(:invalid_scope)
|
124
132
|
end
|
125
133
|
|
126
|
-
it
|
127
|
-
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string(
|
128
|
-
allow(Doorkeeper.configuration)
|
134
|
+
it "creates the token with scopes if scopes are valid and permitted for grant_type" do
|
135
|
+
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("public"))
|
136
|
+
allow(Doorkeeper.configuration)
|
137
|
+
.to receive(:scopes_by_grant_type).and_return(password: [:public])
|
138
|
+
|
129
139
|
expect do
|
130
140
|
subject.authorize
|
131
141
|
end.to change { Doorkeeper::AccessToken.count }.by(1)
|
132
142
|
|
133
|
-
expect(Doorkeeper::AccessToken.last.scopes).to include(
|
143
|
+
expect(Doorkeeper::AccessToken.last.scopes).to include("public")
|
134
144
|
end
|
135
145
|
end
|
136
146
|
end
|
137
147
|
|
138
|
-
describe
|
148
|
+
describe "with custom expiry" do
|
139
149
|
let(:server) do
|
140
150
|
double(
|
141
151
|
:server,
|
@@ -143,14 +153,22 @@ module Doorkeeper::OAuth
|
|
143
153
|
access_token_expires_in: 2.hours,
|
144
154
|
refresh_token_enabled?: false,
|
145
155
|
custom_access_token_expires_in: lambda { |context|
|
146
|
-
context.scopes.exists?(
|
156
|
+
if context.scopes.exists?("public")
|
157
|
+
222
|
158
|
+
elsif context.scopes.exists?("magic")
|
159
|
+
Float::INFINITY
|
160
|
+
end
|
147
161
|
}
|
148
162
|
)
|
149
163
|
end
|
150
164
|
|
151
|
-
|
152
|
-
|
153
|
-
|
165
|
+
before do
|
166
|
+
allow(server).to receive(:option_defined?).with(:custom_access_token_expires_in).and_return(true)
|
167
|
+
end
|
168
|
+
|
169
|
+
it "checks scopes" do
|
170
|
+
subject = PasswordAccessTokenRequest.new(server, client, owner, scope: "public")
|
171
|
+
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("public"))
|
154
172
|
|
155
173
|
expect do
|
156
174
|
subject.authorize
|
@@ -159,9 +177,9 @@ module Doorkeeper::OAuth
|
|
159
177
|
expect(Doorkeeper::AccessToken.last.expires_in).to eq(222)
|
160
178
|
end
|
161
179
|
|
162
|
-
it
|
163
|
-
subject = PasswordAccessTokenRequest.new(server, client, owner, scope:
|
164
|
-
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string(
|
180
|
+
it "falls back to the default otherwise" do
|
181
|
+
subject = PasswordAccessTokenRequest.new(server, client, owner, scope: "private")
|
182
|
+
allow(server).to receive(:scopes).and_return(Doorkeeper::OAuth::Scopes.from_string("private"))
|
165
183
|
|
166
184
|
expect do
|
167
185
|
subject.authorize
|