doorkeeper 4.3.2 → 5.0.0.rc1
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/.gitignore +1 -0
- data/.rubocop.yml +4 -0
- data/.travis.yml +2 -0
- data/Appraisals +2 -2
- data/Gemfile +1 -1
- data/NEWS.md +36 -0
- data/README.md +85 -3
- data/Rakefile +6 -0
- data/app/assets/stylesheets/doorkeeper/admin/application.css +2 -2
- data/app/controllers/doorkeeper/application_controller.rb +4 -3
- data/app/controllers/doorkeeper/application_metal_controller.rb +4 -0
- data/app/controllers/doorkeeper/applications_controller.rb +43 -22
- data/app/controllers/doorkeeper/authorizations_controller.rb +55 -12
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +15 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +2 -6
- data/app/helpers/doorkeeper/dashboard_helper.rb +7 -7
- data/app/validators/redirect_uri_validator.rb +3 -2
- data/app/views/doorkeeper/applications/_delete_form.html.erb +3 -1
- data/app/views/doorkeeper/applications/_form.html.erb +31 -19
- data/app/views/doorkeeper/applications/edit.html.erb +1 -1
- data/app/views/doorkeeper/applications/index.html.erb +18 -6
- data/app/views/doorkeeper/applications/new.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +8 -5
- data/app/views/doorkeeper/authorizations/error.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +4 -0
- data/app/views/layouts/doorkeeper/admin.html.erb +15 -15
- data/config/locales/en.yml +15 -1
- data/gemfiles/rails_5_2.gemfile +1 -1
- data/lib/doorkeeper/config.rb +60 -23
- data/lib/doorkeeper/engine.rb +4 -0
- data/lib/doorkeeper/errors.rb +2 -5
- data/lib/doorkeeper/grape/helpers.rb +1 -1
- data/lib/doorkeeper/helpers/controller.rb +7 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +56 -0
- data/lib/doorkeeper/models/access_token_mixin.rb +37 -20
- data/lib/doorkeeper/models/application_mixin.rb +8 -1
- data/lib/doorkeeper/models/concerns/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/code.rb +31 -8
- data/lib/doorkeeper/oauth/authorization/context.rb +15 -0
- data/lib/doorkeeper/oauth/authorization/token.rb +23 -6
- data/lib/doorkeeper/oauth/authorization_code_request.rb +27 -2
- data/lib/doorkeeper/oauth/base_request.rb +18 -8
- data/lib/doorkeeper/oauth/client/credentials.rb +4 -2
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +6 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -2
- data/lib/doorkeeper/oauth/error_response.rb +11 -3
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +0 -8
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +1 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -4
- data/lib/doorkeeper/oauth/pre_authorization.rb +45 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +6 -1
- data/lib/doorkeeper/oauth/scopes.rb +1 -1
- data/lib/doorkeeper/oauth/token.rb +5 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +2 -2
- data/lib/doorkeeper/oauth/token_response.rb +4 -2
- data/lib/doorkeeper/oauth.rb +13 -0
- data/lib/doorkeeper/orm/active_record/application.rb +14 -0
- data/lib/doorkeeper/orm/active_record/stale_records_cleaner.rb +26 -0
- data/lib/doorkeeper/orm/active_record.rb +2 -0
- data/lib/doorkeeper/rails/helpers.rb +2 -4
- data/lib/doorkeeper/rails/routes.rb +13 -1
- data/lib/doorkeeper/rake/db.rake +40 -0
- data/lib/doorkeeper/rake/setup.rake +6 -0
- data/lib/doorkeeper/rake.rb +14 -0
- data/lib/doorkeeper/request/password.rb +1 -11
- data/lib/doorkeeper/request.rb +28 -28
- data/lib/doorkeeper/version.rb +5 -4
- data/lib/doorkeeper.rb +4 -17
- data/lib/generators/doorkeeper/application_owner_generator.rb +23 -18
- data/lib/generators/doorkeeper/confidential_applications_generator.rb +32 -0
- data/lib/generators/doorkeeper/install_generator.rb +17 -9
- data/lib/generators/doorkeeper/migration_generator.rb +23 -18
- data/lib/generators/doorkeeper/pkce_generator.rb +32 -0
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -24
- data/lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb +13 -0
- data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +6 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +60 -9
- data/lib/generators/doorkeeper/templates/migration.rb.erb +1 -0
- data/lib/generators/doorkeeper/views_generator.rb +3 -1
- data/spec/controllers/application_metal_controller_spec.rb +50 -0
- data/spec/controllers/applications_controller_spec.rb +126 -13
- data/spec/controllers/authorizations_controller_spec.rb +250 -15
- data/spec/controllers/protected_resources_controller_spec.rb +16 -16
- data/spec/controllers/token_info_controller_spec.rb +4 -12
- data/spec/controllers/tokens_controller_spec.rb +12 -14
- data/spec/dummy/app/assets/config/manifest.js +2 -0
- data/spec/dummy/config/environments/test.rb +4 -5
- data/spec/dummy/config/initializers/doorkeeper.rb +6 -0
- data/spec/dummy/config/initializers/new_framework_defaults.rb +4 -0
- data/spec/dummy/config/routes.rb +3 -42
- data/spec/dummy/db/migrate/20111122132257_create_users.rb +3 -1
- data/spec/dummy/db/migrate/20120312140401_add_password_to_users.rb +3 -1
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -1
- data/spec/dummy/db/migrate/20151223200000_add_owner_to_application.rb +3 -1
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +3 -1
- data/spec/dummy/db/migrate/20170822064514_enable_pkce.rb +6 -0
- data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +13 -0
- data/spec/dummy/db/schema.rb +38 -37
- data/spec/generators/application_owner_generator_spec.rb +1 -1
- data/spec/generators/confidential_applications_generator_spec.rb +45 -0
- data/spec/generators/install_generator_spec.rb +1 -1
- data/spec/generators/migration_generator_spec.rb +1 -1
- data/spec/generators/pkce_generator_spec.rb +43 -0
- data/spec/generators/previous_refresh_token_generator_spec.rb +1 -1
- data/spec/generators/views_generator_spec.rb +1 -1
- data/spec/grape/grape_integration_spec.rb +1 -1
- data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
- data/spec/lib/config_spec.rb +59 -14
- data/spec/lib/doorkeeper_spec.rb +1 -126
- data/spec/lib/models/expirable_spec.rb +0 -3
- data/spec/lib/models/revocable_spec.rb +0 -2
- data/spec/lib/models/scopes_spec.rb +0 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +0 -4
- data/spec/lib/oauth/authorization_code_request_spec.rb +24 -2
- data/spec/lib/oauth/base_request_spec.rb +16 -2
- data/spec/lib/oauth/base_response_spec.rb +1 -1
- data/spec/lib/oauth/client/credentials_spec.rb +5 -5
- data/spec/lib/oauth/client_credentials/creator_spec.rb +5 -1
- data/spec/lib/oauth/client_credentials/issuer_spec.rb +26 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +2 -3
- data/spec/lib/oauth/client_credentials_integration_spec.rb +1 -1
- data/spec/lib/oauth/client_credentials_request_spec.rb +3 -5
- data/spec/lib/oauth/client_spec.rb +0 -3
- data/spec/lib/oauth/code_request_spec.rb +4 -2
- data/spec/lib/oauth/error_response_spec.rb +0 -3
- data/spec/lib/oauth/error_spec.rb +0 -2
- data/spec/lib/oauth/forbidden_token_response_spec.rb +1 -4
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +0 -3
- data/spec/lib/oauth/helpers/unique_token_spec.rb +0 -1
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +5 -2
- data/spec/lib/oauth/invalid_token_response_spec.rb +1 -4
- data/spec/lib/oauth/password_access_token_request_spec.rb +37 -2
- data/spec/lib/oauth/pre_authorization_spec.rb +40 -6
- data/spec/lib/oauth/refresh_token_request_spec.rb +11 -7
- data/spec/lib/oauth/scopes_spec.rb +0 -3
- data/spec/lib/oauth/token_request_spec.rb +4 -5
- data/spec/lib/oauth/token_response_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +37 -14
- data/spec/lib/orm/active_record/stale_records_cleaner_spec.rb +79 -0
- data/spec/lib/request/strategy_spec.rb +0 -1
- data/spec/lib/server_spec.rb +1 -1
- data/spec/models/doorkeeper/access_grant_spec.rb +1 -1
- data/spec/models/doorkeeper/access_token_spec.rb +50 -16
- data/spec/models/doorkeeper/application_spec.rb +51 -6
- data/spec/requests/applications/applications_request_spec.rb +89 -1
- data/spec/requests/applications/authorized_applications_spec.rb +1 -1
- data/spec/requests/endpoints/authorization_spec.rb +1 -1
- data/spec/requests/endpoints/token_spec.rb +7 -5
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_spec.rb +197 -1
- data/spec/requests/flows/client_credentials_spec.rb +46 -6
- data/spec/requests/flows/implicit_grant_errors_spec.rb +1 -1
- data/spec/requests/flows/implicit_grant_spec.rb +38 -11
- data/spec/requests/flows/password_spec.rb +120 -23
- data/spec/requests/flows/refresh_token_spec.rb +2 -2
- data/spec/requests/flows/revoke_token_spec.rb +11 -11
- data/spec/requests/flows/skip_authorization_spec.rb +16 -11
- data/spec/requests/protected_resources/metal_spec.rb +1 -1
- data/spec/requests/protected_resources/private_api_spec.rb +1 -1
- data/spec/routing/custom_controller_routes_spec.rb +59 -7
- data/spec/routing/default_routes_spec.rb +2 -2
- data/spec/routing/scoped_routes_spec.rb +16 -2
- data/spec/spec_helper.rb +54 -3
- data/spec/spec_helper_integration.rb +2 -74
- data/spec/support/doorkeeper_rspec.rb +19 -0
- data/spec/support/helpers/authorization_request_helper.rb +4 -4
- data/spec/support/helpers/request_spec_helper.rb +2 -2
- data/spec/support/helpers/url_helper.rb +7 -3
- data/spec/support/http_method_shim.rb +12 -16
- data/spec/validators/redirect_uri_validator_spec.rb +7 -1
- data/spec/version/version_spec.rb +3 -3
- data/vendor/assets/stylesheets/doorkeeper/bootstrap.min.css +4 -5
- metadata +32 -8
- data/spec/controllers/application_metal_controller.rb +0 -10
- /data/spec/support/dependencies/{factory_girl.rb → factory_bot.rb} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper::OAuth
|
|
4
4
|
describe RefreshTokenRequest do
|
|
@@ -9,7 +9,7 @@ module Doorkeeper::OAuth
|
|
|
9
9
|
let(:server) do
|
|
10
10
|
double :server,
|
|
11
11
|
access_token_expires_in: 2.minutes,
|
|
12
|
-
custom_access_token_expires_in: ->
|
|
12
|
+
custom_access_token_expires_in: ->(_context) { nil }
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
let(:refresh_token) do
|
|
@@ -30,7 +30,9 @@ module Doorkeeper::OAuth
|
|
|
30
30
|
it 'issues a new token for the client with custom expires_in' do
|
|
31
31
|
server = double :server,
|
|
32
32
|
access_token_expires_in: 2.minutes,
|
|
33
|
-
custom_access_token_expires_in:
|
|
33
|
+
custom_access_token_expires_in: lambda { |context|
|
|
34
|
+
context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
|
|
35
|
+
}
|
|
34
36
|
|
|
35
37
|
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
|
36
38
|
|
|
@@ -85,7 +87,9 @@ module Doorkeeper::OAuth
|
|
|
85
87
|
let(:server) do
|
|
86
88
|
double :server,
|
|
87
89
|
access_token_expires_in: 2.minutes,
|
|
88
|
-
custom_access_token_expires_in:
|
|
90
|
+
custom_access_token_expires_in: lambda { |context|
|
|
91
|
+
context.grant_type == Doorkeeper::OAuth::REFRESH_TOKEN ? 1234 : nil
|
|
92
|
+
}
|
|
89
93
|
end
|
|
90
94
|
|
|
91
95
|
before do
|
|
@@ -131,13 +135,13 @@ module Doorkeeper::OAuth
|
|
|
131
135
|
|
|
132
136
|
it 'transfers scopes from the old token to the new token' do
|
|
133
137
|
subject.authorize
|
|
134
|
-
expect(Doorkeeper::AccessToken.last.scopes).to eq([
|
|
138
|
+
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public write])
|
|
135
139
|
end
|
|
136
140
|
|
|
137
141
|
it 'reduces scopes to the provided scopes' do
|
|
138
142
|
parameters[:scopes] = 'public'
|
|
139
143
|
subject.authorize
|
|
140
|
-
expect(Doorkeeper::AccessToken.last.scopes).to eq([
|
|
144
|
+
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
|
|
141
145
|
end
|
|
142
146
|
|
|
143
147
|
it 'validates that scopes are included in the original access token' do
|
|
@@ -151,7 +155,7 @@ module Doorkeeper::OAuth
|
|
|
151
155
|
parameters[:scopes] = 'public update'
|
|
152
156
|
parameters[:scope] = 'public'
|
|
153
157
|
subject.authorize
|
|
154
|
-
expect(Doorkeeper::AccessToken.last.scopes).to eq([
|
|
158
|
+
expect(Doorkeeper::AccessToken.last.scopes).to eq(%i[public])
|
|
155
159
|
end
|
|
156
160
|
|
|
157
161
|
it 'uses params[:scope] in favor of scopes if present (invalid)' do
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper::OAuth
|
|
4
4
|
describe TokenRequest do
|
|
5
5
|
let :application do
|
|
6
|
-
|
|
7
|
-
double(:application, id: 9990, scopes: scopes)
|
|
6
|
+
FactoryBot.create(:application, scopes: "public")
|
|
8
7
|
end
|
|
9
8
|
|
|
10
9
|
let :pre_auth do
|
|
@@ -51,8 +50,8 @@ module Doorkeeper::OAuth
|
|
|
51
50
|
before do
|
|
52
51
|
Doorkeeper.configure do
|
|
53
52
|
orm DOORKEEPER_ORM
|
|
54
|
-
custom_access_token_expires_in do |
|
|
55
|
-
1234
|
|
53
|
+
custom_access_token_expires_in do |context|
|
|
54
|
+
context.grant_type == Doorkeeper::OAuth::IMPLICIT ? 1234 : nil
|
|
56
55
|
end
|
|
57
56
|
end
|
|
58
57
|
end
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
require 'active_support/core_ext/string'
|
|
3
|
-
require 'doorkeeper/oauth/token'
|
|
4
2
|
|
|
5
3
|
module Doorkeeper
|
|
6
4
|
unless defined?(AccessToken)
|
|
@@ -14,7 +12,7 @@ module Doorkeeper
|
|
|
14
12
|
let(:request) { double.as_null_object }
|
|
15
13
|
|
|
16
14
|
let(:method) do
|
|
17
|
-
->(
|
|
15
|
+
->(*) { 'token-value' }
|
|
18
16
|
end
|
|
19
17
|
|
|
20
18
|
it 'accepts anything that responds to #call' do
|
|
@@ -96,19 +94,44 @@ module Doorkeeper
|
|
|
96
94
|
end
|
|
97
95
|
|
|
98
96
|
describe :authenticate do
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
97
|
+
context 'refresh tokens are disabled (default)' do
|
|
98
|
+
context 'refresh tokens are enabled' do
|
|
99
|
+
it 'does not revoke previous refresh_token if token was found' do
|
|
100
|
+
token = ->(_r) { 'token' }
|
|
101
|
+
expect(
|
|
102
|
+
AccessToken
|
|
103
|
+
).to receive(:by_token).with('token').and_return(token)
|
|
104
|
+
expect(token).not_to receive(:revoke_previous_refresh_token!)
|
|
105
|
+
Token.authenticate double, token
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it 'calls the finder if token was returned' do
|
|
110
|
+
token = ->(_r) { 'token' }
|
|
111
|
+
expect(AccessToken).to receive(:by_token).with('token')
|
|
112
|
+
Token.authenticate double, token
|
|
113
|
+
end
|
|
103
114
|
end
|
|
104
115
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
116
|
+
context 'refresh tokens are enabled' do
|
|
117
|
+
before do
|
|
118
|
+
Doorkeeper.configure { use_refresh_token }
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
it 'revokes previous refresh_token if token was found' do
|
|
122
|
+
token = ->(_r) { 'token' }
|
|
123
|
+
expect(
|
|
124
|
+
AccessToken
|
|
125
|
+
).to receive(:by_token).with('token').and_return(token)
|
|
126
|
+
expect(token).to receive(:revoke_previous_refresh_token!)
|
|
127
|
+
Token.authenticate double, token
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it 'calls the finder if token was returned' do
|
|
131
|
+
token = ->(_r) { 'token' }
|
|
132
|
+
expect(AccessToken).to receive(:by_token).with('token')
|
|
133
|
+
Token.authenticate double, token
|
|
134
|
+
end
|
|
112
135
|
end
|
|
113
136
|
end
|
|
114
137
|
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'spec_helper'
|
|
4
|
+
|
|
5
|
+
describe Doorkeeper::Orm::ActiveRecord::StaleRecordsCleaner do
|
|
6
|
+
let(:cleaner) { described_class.new(model) }
|
|
7
|
+
let(:models_by_name) do
|
|
8
|
+
{
|
|
9
|
+
access_token: Doorkeeper::AccessToken,
|
|
10
|
+
access_grant: Doorkeeper::AccessGrant
|
|
11
|
+
}
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
%i[access_token access_grant].each do |model_name|
|
|
15
|
+
context "(#{model_name})" do
|
|
16
|
+
let(:model) { models_by_name.fetch(model_name) }
|
|
17
|
+
|
|
18
|
+
describe '#clean_revoked' do
|
|
19
|
+
subject { cleaner.clean_revoked }
|
|
20
|
+
|
|
21
|
+
context 'with revoked record' do
|
|
22
|
+
before do
|
|
23
|
+
FactoryBot.create model_name, revoked_at: Time.current - 1.minute
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'removes the record' do
|
|
27
|
+
expect { subject }.to change { model.count }.to(0)
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
context 'with record revoked in the future' do
|
|
32
|
+
before do
|
|
33
|
+
FactoryBot.create model_name, revoked_at: Time.current + 1.minute
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it 'keeps the record' do
|
|
37
|
+
expect { subject }.not_to change { model.count }
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
context 'with unrevoked record' do
|
|
42
|
+
before do
|
|
43
|
+
FactoryBot.create model_name, revoked_at: nil
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it 'keeps the record' do
|
|
47
|
+
expect { subject }.not_to change { model.count }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe '#clean_expired' do
|
|
53
|
+
subject { cleaner.clean_expired(ttl) }
|
|
54
|
+
let(:ttl) { 500 }
|
|
55
|
+
let(:expiry_border) { ttl.seconds.ago }
|
|
56
|
+
|
|
57
|
+
context 'with record that is expired' do
|
|
58
|
+
before do
|
|
59
|
+
FactoryBot.create model_name, created_at: expiry_border - 1.minute
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it 'removes the record' do
|
|
63
|
+
expect { subject }.to change { model.count }.to(0)
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context 'with record that is not expired' do
|
|
68
|
+
before do
|
|
69
|
+
FactoryBot.create model_name, created_at: expiry_border + 1.minute
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it 'keeps the record' do
|
|
73
|
+
expect { subject }.not_to change { model.count }
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
data/spec/lib/server_spec.rb
CHANGED
|
@@ -46,7 +46,7 @@ describe Doorkeeper::Server do
|
|
|
46
46
|
subject.authorization_request :code
|
|
47
47
|
end
|
|
48
48
|
|
|
49
|
-
it 'builds the request with
|
|
49
|
+
it 'builds the request with composite strategy name' do
|
|
50
50
|
allow(Doorkeeper.configuration).
|
|
51
51
|
to receive(:authorization_response_types).
|
|
52
52
|
and_return(['id_token token'])
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
describe AccessToken do
|
|
@@ -144,7 +144,7 @@ module Doorkeeper
|
|
|
144
144
|
end
|
|
145
145
|
|
|
146
146
|
module CustomGeneratorArgs
|
|
147
|
-
def self.generate(
|
|
147
|
+
def self.generate(_opts = {})
|
|
148
148
|
raise LoadError, 'custom behaviour'
|
|
149
149
|
end
|
|
150
150
|
end
|
|
@@ -218,7 +218,7 @@ module Doorkeeper
|
|
|
218
218
|
context 'with default parameters' do
|
|
219
219
|
|
|
220
220
|
let(:resource_owner_id) { 100 }
|
|
221
|
-
let(:application)
|
|
221
|
+
let(:application) { FactoryBot.create :application }
|
|
222
222
|
let(:default_attributes) do
|
|
223
223
|
{ application: application, resource_owner_id: resource_owner_id }
|
|
224
224
|
end
|
|
@@ -330,6 +330,10 @@ module Doorkeeper
|
|
|
330
330
|
}
|
|
331
331
|
end
|
|
332
332
|
|
|
333
|
+
before do
|
|
334
|
+
default_scopes_exist(*scopes.all)
|
|
335
|
+
end
|
|
336
|
+
|
|
333
337
|
it 'returns only one token' do
|
|
334
338
|
token = FactoryBot.create :access_token, default_attributes
|
|
335
339
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
@@ -355,37 +359,45 @@ module Doorkeeper
|
|
|
355
359
|
expect(last_token).to be_nil
|
|
356
360
|
end
|
|
357
361
|
|
|
358
|
-
it
|
|
362
|
+
it "excludes tokens with a different application" do
|
|
359
363
|
FactoryBot.create :access_token, default_attributes.merge(application: FactoryBot.create(:application))
|
|
360
364
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
361
365
|
expect(last_token).to be_nil
|
|
362
366
|
end
|
|
363
367
|
|
|
364
|
-
it
|
|
368
|
+
it "excludes tokens with a different resource owner" do
|
|
365
369
|
FactoryBot.create :access_token, default_attributes.merge(resource_owner_id: 2)
|
|
366
370
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
367
371
|
expect(last_token).to be_nil
|
|
368
372
|
end
|
|
369
373
|
|
|
370
|
-
it
|
|
374
|
+
it "excludes tokens with fewer scopes" do
|
|
371
375
|
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
|
|
372
376
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
373
377
|
expect(last_token).to be_nil
|
|
374
378
|
end
|
|
375
379
|
|
|
376
|
-
it '
|
|
380
|
+
it 'excludes tokens with different scopes' do
|
|
377
381
|
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public email')
|
|
378
382
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
379
383
|
expect(last_token).to be_nil
|
|
380
384
|
end
|
|
381
385
|
|
|
382
|
-
it '
|
|
386
|
+
it 'excludes tokens with additional scopes' do
|
|
383
387
|
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public write email')
|
|
384
388
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
385
389
|
expect(last_token).to be_nil
|
|
386
390
|
end
|
|
387
391
|
|
|
388
|
-
it '
|
|
392
|
+
it 'excludes tokens with scopes that are not present in server scopes' do
|
|
393
|
+
FactoryBot.create :access_token, default_attributes.merge(
|
|
394
|
+
application: application, scopes: 'public read'
|
|
395
|
+
)
|
|
396
|
+
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
397
|
+
expect(last_token).to be_nil
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
it 'excludes tokens with scopes that are not present in application scopes' do
|
|
389
401
|
application = FactoryBot.create :application, scopes: "private read"
|
|
390
402
|
FactoryBot.create :access_token, default_attributes.merge(
|
|
391
403
|
application: application
|
|
@@ -394,25 +406,47 @@ module Doorkeeper
|
|
|
394
406
|
expect(last_token).to be_nil
|
|
395
407
|
end
|
|
396
408
|
|
|
397
|
-
it '
|
|
409
|
+
it 'does not match token if empty scope requested and token/app scopes present' do
|
|
410
|
+
application = FactoryBot.create :application, scopes: "sample:scope"
|
|
411
|
+
app_params = {
|
|
412
|
+
application_id: application.id, scopes: "sample:scope",
|
|
413
|
+
resource_owner_id: 100
|
|
414
|
+
}
|
|
415
|
+
FactoryBot.create :access_token, app_params
|
|
416
|
+
empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
|
|
417
|
+
last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
|
|
418
|
+
expect(last_token).to be_nil
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
it 'matches token if empty scope requested and no token scopes present' do
|
|
422
|
+
empty_scopes = Doorkeeper::OAuth::Scopes.from_string("")
|
|
423
|
+
token = FactoryBot.create :access_token, default_attributes.merge(scopes: empty_scopes)
|
|
424
|
+
last_token = AccessToken.matching_token_for(application, 100, empty_scopes)
|
|
425
|
+
expect(last_token).to eq(token)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
it 'returns the last matching token' do
|
|
398
429
|
FactoryBot.create :access_token, default_attributes.merge(created_at: 1.day.ago)
|
|
399
|
-
|
|
430
|
+
matching_token = FactoryBot.create :access_token, default_attributes
|
|
431
|
+
FactoryBot.create :access_token, default_attributes.merge(scopes: 'public')
|
|
432
|
+
|
|
400
433
|
last_token = AccessToken.matching_token_for(application, resource_owner_id, scopes)
|
|
401
|
-
expect(last_token).to eq(
|
|
434
|
+
expect(last_token).to eq(matching_token)
|
|
402
435
|
end
|
|
436
|
+
end
|
|
403
437
|
|
|
404
|
-
|
|
405
|
-
|
|
438
|
+
describe "#as_json" do
|
|
439
|
+
it "returns as_json hash" do
|
|
440
|
+
token = FactoryBot.create :access_token
|
|
406
441
|
token_hash = {
|
|
407
442
|
resource_owner_id: token.resource_owner_id,
|
|
408
443
|
scopes: token.scopes,
|
|
409
444
|
expires_in_seconds: token.expires_in_seconds,
|
|
410
445
|
application: { uid: token.application.uid },
|
|
411
|
-
created_at: token.created_at.to_i
|
|
446
|
+
created_at: token.created_at.to_i
|
|
412
447
|
}
|
|
413
448
|
expect(token.as_json).to eq token_hash
|
|
414
449
|
end
|
|
415
450
|
end
|
|
416
|
-
|
|
417
451
|
end
|
|
418
452
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
module Doorkeeper
|
|
4
4
|
describe Application do
|
|
@@ -49,6 +49,11 @@ module Doorkeeper
|
|
|
49
49
|
expect(new_application).not_to be_valid
|
|
50
50
|
end
|
|
51
51
|
|
|
52
|
+
it 'is invalid without determining confidentiality' do
|
|
53
|
+
new_application.confidential = nil
|
|
54
|
+
expect(new_application).not_to be_valid
|
|
55
|
+
end
|
|
56
|
+
|
|
52
57
|
it 'generates uid on create' do
|
|
53
58
|
expect(new_application.uid).to be_nil
|
|
54
59
|
new_application.save
|
|
@@ -201,11 +206,51 @@ module Doorkeeper
|
|
|
201
206
|
end
|
|
202
207
|
end
|
|
203
208
|
|
|
204
|
-
describe :
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
describe :by_uid_and_secret do
|
|
210
|
+
context "when application is private/confidential" do
|
|
211
|
+
it "finds the application via uid/secret" do
|
|
212
|
+
app = FactoryBot.create :application
|
|
213
|
+
authenticated = Application.by_uid_and_secret(app.uid, app.secret)
|
|
214
|
+
expect(authenticated).to eq(app)
|
|
215
|
+
end
|
|
216
|
+
context "when secret is wrong" do
|
|
217
|
+
it "should not find the application" do
|
|
218
|
+
app = FactoryBot.create :application
|
|
219
|
+
authenticated = Application.by_uid_and_secret(app.uid, 'bad')
|
|
220
|
+
expect(authenticated).to eq(nil)
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
context "when application is public/non-confidential" do
|
|
226
|
+
context "when secret is blank" do
|
|
227
|
+
it "should find the application" do
|
|
228
|
+
app = FactoryBot.create :application, confidential: false
|
|
229
|
+
authenticated = Application.by_uid_and_secret(app.uid, nil)
|
|
230
|
+
expect(authenticated).to eq(app)
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
context "when secret is wrong" do
|
|
234
|
+
it "should not find the application" do
|
|
235
|
+
app = FactoryBot.create :application, confidential: false
|
|
236
|
+
authenticated = Application.by_uid_and_secret(app.uid, 'bad')
|
|
237
|
+
expect(authenticated).to eq(nil)
|
|
238
|
+
end
|
|
239
|
+
end
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
describe :confidential? do
|
|
244
|
+
subject { FactoryBot.create(:application, confidential: confidential).confidential? }
|
|
245
|
+
|
|
246
|
+
context 'when application is private/confidential' do
|
|
247
|
+
let(:confidential) { true }
|
|
248
|
+
it { expect(subject).to eq(true) }
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
context 'when application is public/non-confidential' do
|
|
252
|
+
let(:confidential) { false }
|
|
253
|
+
it { expect(subject).to eq(false) }
|
|
209
254
|
end
|
|
210
255
|
end
|
|
211
256
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
feature 'Adding applications' do
|
|
4
4
|
context 'in application form' do
|
|
@@ -20,6 +20,77 @@ feature 'Adding applications' do
|
|
|
20
20
|
click_button 'Submit'
|
|
21
21
|
i_should_see 'Whoops! Check your form for possible errors'
|
|
22
22
|
end
|
|
23
|
+
|
|
24
|
+
scenario "adding app ignoring bad scope" do
|
|
25
|
+
config_is_set("enforce_configured_scopes", false)
|
|
26
|
+
|
|
27
|
+
fill_in "doorkeeper_application[name]", with: "My Application"
|
|
28
|
+
fill_in "doorkeeper_application[redirect_uri]",
|
|
29
|
+
with: "https://example.com"
|
|
30
|
+
fill_in "doorkeeper_application[scopes]", with: "blahblah"
|
|
31
|
+
|
|
32
|
+
click_button "Submit"
|
|
33
|
+
i_should_see "Application created"
|
|
34
|
+
i_should_see "My Application"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
scenario "adding app validating bad scope" do
|
|
38
|
+
config_is_set("enforce_configured_scopes", true)
|
|
39
|
+
|
|
40
|
+
fill_in "doorkeeper_application[name]", with: "My Application"
|
|
41
|
+
fill_in "doorkeeper_application[redirect_uri]",
|
|
42
|
+
with: "https://example.com"
|
|
43
|
+
fill_in "doorkeeper_application[scopes]", with: "blahblah"
|
|
44
|
+
|
|
45
|
+
click_button "Submit"
|
|
46
|
+
i_should_see "Whoops! Check your form for possible errors"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
scenario "adding app validating scope, blank scope is accepted" do
|
|
50
|
+
config_is_set("enforce_configured_scopes", true)
|
|
51
|
+
|
|
52
|
+
fill_in "doorkeeper_application[name]", with: "My Application"
|
|
53
|
+
fill_in "doorkeeper_application[redirect_uri]",
|
|
54
|
+
with: "https://example.com"
|
|
55
|
+
fill_in "doorkeeper_application[scopes]", with: ""
|
|
56
|
+
|
|
57
|
+
click_button "Submit"
|
|
58
|
+
i_should_see "Application created"
|
|
59
|
+
i_should_see "My Application"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
scenario "adding app validating scope, multiple scopes configured" do
|
|
63
|
+
config_is_set("enforce_configured_scopes", true)
|
|
64
|
+
scopes = Doorkeeper::OAuth::Scopes.from_array(%w(read write admin))
|
|
65
|
+
config_is_set("optional_scopes", scopes)
|
|
66
|
+
|
|
67
|
+
fill_in "doorkeeper_application[name]", with: "My Application"
|
|
68
|
+
fill_in "doorkeeper_application[redirect_uri]",
|
|
69
|
+
with: "https://example.com"
|
|
70
|
+
fill_in "doorkeeper_application[scopes]", with: "read write"
|
|
71
|
+
|
|
72
|
+
click_button "Submit"
|
|
73
|
+
i_should_see "Application created"
|
|
74
|
+
i_should_see "My Application"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
scenario "adding app validating scope, bad scope with multiple scopes configured" do
|
|
78
|
+
config_is_set("enforce_configured_scopes", true)
|
|
79
|
+
scopes = Doorkeeper::OAuth::Scopes.from_array(%w(read write admin))
|
|
80
|
+
config_is_set("optional_scopes", scopes)
|
|
81
|
+
|
|
82
|
+
fill_in "doorkeeper_application[name]", with: "My Application"
|
|
83
|
+
fill_in "doorkeeper_application[redirect_uri]",
|
|
84
|
+
with: "https://example.com"
|
|
85
|
+
fill_in "doorkeeper_application[scopes]", with: "read blah"
|
|
86
|
+
|
|
87
|
+
click_button "Submit"
|
|
88
|
+
i_should_see "Whoops! Check your form for possible errors"
|
|
89
|
+
i_should_see Regexp.new(
|
|
90
|
+
I18n.t('activerecord.errors.models.doorkeeper/application.attributes.scopes.not_match_configured'),
|
|
91
|
+
true
|
|
92
|
+
)
|
|
93
|
+
end
|
|
23
94
|
end
|
|
24
95
|
end
|
|
25
96
|
|
|
@@ -36,6 +107,23 @@ feature 'Listing applications' do
|
|
|
36
107
|
end
|
|
37
108
|
end
|
|
38
109
|
|
|
110
|
+
feature 'Renders assets' do
|
|
111
|
+
scenario 'admin stylesheets' do
|
|
112
|
+
visit '/assets/doorkeeper/admin/application.css'
|
|
113
|
+
|
|
114
|
+
i_should_see 'Bootstrap'
|
|
115
|
+
i_should_see '.doorkeeper-admin'
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
scenario 'application stylesheets' do
|
|
119
|
+
visit '/assets/doorkeeper/application.css'
|
|
120
|
+
|
|
121
|
+
i_should_see 'Bootstrap'
|
|
122
|
+
i_should_see '#oauth-permissions'
|
|
123
|
+
i_should_see '#container'
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
39
127
|
feature 'Show application' do
|
|
40
128
|
given :app do
|
|
41
129
|
FactoryBot.create :application, name: 'Just another oauth app'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require '
|
|
1
|
+
require 'spec_helper'
|
|
2
2
|
|
|
3
3
|
describe 'Token endpoint' do
|
|
4
4
|
before do
|
|
@@ -21,10 +21,12 @@ describe 'Token endpoint' do
|
|
|
21
21
|
end
|
|
22
22
|
|
|
23
23
|
it 'accepts client credentials with basic auth header' do
|
|
24
|
-
post token_endpoint_url
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
post token_endpoint_url,
|
|
25
|
+
params: {
|
|
26
|
+
code: @authorization.token,
|
|
27
|
+
redirect_uri: @client.redirect_uri
|
|
28
|
+
},
|
|
29
|
+
headers: { 'HTTP_AUTHORIZATION' => basic_auth_header_for_client(@client) }
|
|
28
30
|
|
|
29
31
|
should_have_json 'access_token', Doorkeeper::AccessToken.first.token
|
|
30
32
|
end
|