doorkeeper 3.1.0 → 4.2.6
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/.coveralls.yml +1 -0
- data/.gitignore +5 -0
- data/.travis.yml +16 -12
- data/Appraisals +14 -0
- data/CONTRIBUTING.md +2 -0
- data/Gemfile +5 -5
- data/NEWS.md +83 -2
- data/README.md +73 -43
- data/RELEASING.md +5 -12
- data/Rakefile +1 -1
- data/app/controllers/doorkeeper/application_controller.rb +3 -1
- data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
- data/app/controllers/doorkeeper/applications_controller.rb +3 -7
- data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
- data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +50 -14
- data/app/helpers/doorkeeper/dashboard_helper.rb +13 -11
- data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
- data/app/views/doorkeeper/applications/_form.html.erb +1 -1
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
- data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
- data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
- data/config/locales/en.yml +3 -2
- data/doorkeeper.gemspec +12 -10
- data/gemfiles/rails_4_2.gemfile +11 -0
- data/gemfiles/rails_5_0.gemfile +12 -0
- data/gemfiles/rails_5_1.gemfile +13 -0
- data/lib/doorkeeper/config.rb +73 -16
- data/lib/doorkeeper/engine.rb +11 -7
- data/lib/doorkeeper/errors.rb +18 -0
- data/lib/doorkeeper/grape/helpers.rb +2 -1
- data/lib/doorkeeper/helpers/controller.rb +8 -23
- data/lib/doorkeeper/models/access_grant_mixin.rb +21 -5
- data/lib/doorkeeper/models/access_token_mixin.rb +145 -23
- data/lib/doorkeeper/models/application_mixin.rb +21 -9
- data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
- data/lib/doorkeeper/models/concerns/expirable.rb +10 -2
- data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
- data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
- data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
- data/lib/doorkeeper/oauth/authorization_code_request.rb +1 -4
- data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +3 -1
- data/lib/doorkeeper/oauth/base_response.rb +29 -0
- data/lib/doorkeeper/oauth/client/credentials.rb +17 -6
- data/lib/doorkeeper/oauth/client.rb +0 -1
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
- data/lib/doorkeeper/oauth/code_response.rb +16 -16
- data/lib/doorkeeper/oauth/error_response.rb +9 -8
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +2 -1
- data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -13
- data/lib/doorkeeper/oauth/refresh_token_request.rb +22 -14
- data/lib/doorkeeper/oauth/scopes.rb +2 -2
- data/lib/doorkeeper/oauth/token.rb +20 -21
- data/lib/doorkeeper/oauth/token_request.rb +1 -2
- data/lib/doorkeeper/oauth/token_response.rb +1 -1
- data/lib/doorkeeper/orm/active_record/access_token.rb +25 -0
- data/lib/doorkeeper/orm/active_record/application.rb +12 -12
- data/lib/doorkeeper/orm/active_record.rb +0 -16
- data/lib/doorkeeper/rails/helpers.rb +1 -3
- data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
- data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
- data/lib/doorkeeper/rails/routes.rb +4 -4
- data/lib/doorkeeper/request/authorization_code.rb +7 -1
- data/lib/doorkeeper/request/password.rb +11 -1
- data/lib/doorkeeper/request/refresh_token.rb +1 -1
- data/lib/doorkeeper/server.rb +0 -8
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/doorkeeper.rb +8 -2
- data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -0
- data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +1 -1
- data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb +11 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +8 -3
- data/lib/generators/doorkeeper/templates/migration.rb +23 -5
- data/spec/controllers/application_metal_controller.rb +10 -0
- data/spec/controllers/authorizations_controller_spec.rb +39 -24
- data/spec/controllers/protected_resources_controller_spec.rb +47 -18
- data/spec/controllers/tokens_controller_spec.rb +1 -1
- data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
- data/spec/dummy/app/controllers/home_controller.rb +1 -1
- data/spec/dummy/app/controllers/metal_controller.rb +1 -1
- data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
- data/spec/dummy/app/models/user.rb +0 -4
- data/spec/dummy/config/application.rb +2 -36
- data/spec/dummy/config/environment.rb +1 -1
- data/spec/dummy/config/environments/test.rb +4 -15
- data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +6 -0
- data/spec/dummy/config/initializers/doorkeeper.rb +2 -2
- data/spec/dummy/db/migrate/{20130902165751_create_doorkeeper_tables.rb → 20151223192035_create_doorkeeper_tables.rb} +24 -5
- data/spec/dummy/db/migrate/{20130902175349_add_owner_to_application.rb → 20151223200000_add_owner_to_application.rb} +0 -0
- data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +11 -0
- data/spec/dummy/db/schema.rb +23 -22
- data/spec/factories.rb +3 -1
- data/spec/lib/config_spec.rb +19 -2
- data/spec/lib/doorkeeper_spec.rb +135 -13
- data/spec/lib/models/expirable_spec.rb +0 -1
- data/spec/lib/models/revocable_spec.rb +27 -4
- data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
- data/spec/lib/oauth/authorization_code_request_spec.rb +1 -1
- data/spec/lib/oauth/base_request_spec.rb +160 -0
- data/spec/lib/oauth/base_response_spec.rb +45 -0
- data/spec/lib/oauth/client/credentials_spec.rb +41 -0
- data/spec/lib/oauth/code_response_spec.rb +34 -0
- data/spec/lib/oauth/error_response_spec.rb +9 -9
- data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
- data/spec/lib/oauth/password_access_token_request_spec.rb +5 -5
- data/spec/lib/oauth/refresh_token_request_spec.rb +34 -3
- data/spec/lib/oauth/scopes_spec.rb +0 -1
- data/spec/lib/oauth/token_spec.rb +12 -5
- data/spec/lib/server_spec.rb +0 -3
- data/spec/models/doorkeeper/access_token_spec.rb +45 -1
- data/spec/models/doorkeeper/application_spec.rb +3 -11
- data/spec/requests/endpoints/authorization_spec.rb +5 -6
- data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
- data/spec/requests/flows/authorization_code_spec.rb +4 -12
- data/spec/requests/flows/password_spec.rb +26 -5
- data/spec/requests/flows/refresh_token_spec.rb +87 -17
- data/spec/requests/flows/revoke_token_spec.rb +100 -86
- data/spec/spec_helper.rb +2 -0
- data/spec/spec_helper_integration.rb +8 -1
- data/spec/support/helpers/model_helper.rb +27 -5
- data/spec/support/helpers/request_spec_helper.rb +12 -4
- data/spec/support/http_method_shim.rb +38 -0
- data/spec/support/shared/controllers_shared_context.rb +13 -4
- data/spec/support/shared/models_shared_examples.rb +1 -1
- metadata +72 -42
- data/lib/doorkeeper/oauth/client/methods.rb +0 -18
- data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
- data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
- data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
- data/spec/lib/oauth/client/methods_spec.rb +0 -54
@@ -37,20 +37,62 @@ describe 'Refresh Token Flow' do
|
|
37
37
|
|
38
38
|
context 'refreshing the token' do
|
39
39
|
before do
|
40
|
-
@token = FactoryGirl.create(
|
40
|
+
@token = FactoryGirl.create(
|
41
|
+
:access_token,
|
42
|
+
application: @client,
|
43
|
+
resource_owner_id: 1,
|
44
|
+
use_refresh_token: true
|
45
|
+
)
|
41
46
|
end
|
42
47
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
48
|
+
context "refresh_token revoked on use" do
|
49
|
+
it 'client request a token with refresh token' do
|
50
|
+
post refresh_token_endpoint_url(
|
51
|
+
client: @client, refresh_token: @token.refresh_token
|
52
|
+
)
|
53
|
+
should_have_json(
|
54
|
+
'refresh_token', Doorkeeper::AccessToken.last.refresh_token
|
55
|
+
)
|
56
|
+
expect(@token.reload).not_to be_revoked
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'client request a token with expired access token' do
|
60
|
+
@token.update_attribute :expires_in, -100
|
61
|
+
post refresh_token_endpoint_url(
|
62
|
+
client: @client, refresh_token: @token.refresh_token
|
63
|
+
)
|
64
|
+
should_have_json(
|
65
|
+
'refresh_token', Doorkeeper::AccessToken.last.refresh_token
|
66
|
+
)
|
67
|
+
expect(@token.reload).not_to be_revoked
|
68
|
+
end
|
47
69
|
end
|
48
70
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
71
|
+
context "refresh_token revoked on refresh_token request" do
|
72
|
+
before do
|
73
|
+
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'client request a token with refresh token' do
|
77
|
+
post refresh_token_endpoint_url(
|
78
|
+
client: @client, refresh_token: @token.refresh_token
|
79
|
+
)
|
80
|
+
should_have_json(
|
81
|
+
'refresh_token', Doorkeeper::AccessToken.last.refresh_token
|
82
|
+
)
|
83
|
+
expect(@token.reload).to be_revoked
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'client request a token with expired access token' do
|
87
|
+
@token.update_attribute :expires_in, -100
|
88
|
+
post refresh_token_endpoint_url(
|
89
|
+
client: @client, refresh_token: @token.refresh_token
|
90
|
+
)
|
91
|
+
should_have_json(
|
92
|
+
'refresh_token', Doorkeeper::AccessToken.last.refresh_token
|
93
|
+
)
|
94
|
+
expect(@token.reload).to be_revoked
|
95
|
+
end
|
54
96
|
end
|
55
97
|
|
56
98
|
it 'client gets an error for invalid refresh token' do
|
@@ -79,20 +121,48 @@ describe 'Refresh Token Flow' do
|
|
79
121
|
before do
|
80
122
|
# enable password auth to simulate other devices
|
81
123
|
config_is_set(:grant_flows, ["password"])
|
82
|
-
config_is_set(:resource_owner_from_credentials)
|
124
|
+
config_is_set(:resource_owner_from_credentials) do
|
125
|
+
User.authenticate! params[:username], params[:password]
|
126
|
+
end
|
83
127
|
create_resource_owner
|
84
|
-
_another_token = post password_token_endpoint_url(
|
128
|
+
_another_token = post password_token_endpoint_url(
|
129
|
+
client: @client, resource_owner: @resource_owner
|
130
|
+
)
|
85
131
|
last_token.update_attribute :created_at, 5.seconds.ago
|
86
132
|
|
87
|
-
@token = FactoryGirl.create(
|
133
|
+
@token = FactoryGirl.create(
|
134
|
+
:access_token,
|
135
|
+
application: @client,
|
136
|
+
resource_owner_id: @resource_owner.id,
|
137
|
+
use_refresh_token: true
|
138
|
+
)
|
88
139
|
@token.update_attribute :expires_in, -100
|
89
140
|
end
|
90
141
|
|
91
|
-
|
92
|
-
|
142
|
+
context "refresh_token revoked on use" do
|
143
|
+
it 'client request a token after creating another token with the same user' do
|
144
|
+
post refresh_token_endpoint_url(
|
145
|
+
client: @client, refresh_token: @token.refresh_token
|
146
|
+
)
|
147
|
+
|
148
|
+
should_have_json 'refresh_token', last_token.refresh_token
|
149
|
+
expect(@token.reload).not_to be_revoked
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
context "refresh_token revoked on refresh_token request" do
|
154
|
+
before do
|
155
|
+
allow(Doorkeeper::AccessToken).to receive(:refresh_token_revoked_on_use?).and_return(false)
|
156
|
+
end
|
157
|
+
|
158
|
+
it 'client request a token after creating another token with the same user' do
|
159
|
+
post refresh_token_endpoint_url(
|
160
|
+
client: @client, refresh_token: @token.refresh_token
|
161
|
+
)
|
93
162
|
|
94
|
-
|
95
|
-
|
163
|
+
should_have_json 'refresh_token', last_token.refresh_token
|
164
|
+
expect(@token.reload).to be_revoked
|
165
|
+
end
|
96
166
|
end
|
97
167
|
|
98
168
|
def last_token
|
@@ -8,135 +8,149 @@ describe 'Revoke Token Flow' do
|
|
8
8
|
context 'with default parameters' do
|
9
9
|
let(:client_application) { FactoryGirl.create :application }
|
10
10
|
let(:resource_owner) { User.create!(name: 'John', password: 'sekret') }
|
11
|
-
let(:
|
11
|
+
let(:access_token) do
|
12
12
|
FactoryGirl.create(:access_token,
|
13
13
|
application: client_application,
|
14
14
|
resource_owner_id: resource_owner.id,
|
15
15
|
use_refresh_token: true)
|
16
16
|
end
|
17
|
-
let(:headers) { { 'HTTP_AUTHORIZATION' => "Bearer #{authorization_access_token.token}" } }
|
18
17
|
|
19
|
-
context '
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
# has been revoked successfully or if the client submitted an invalid token.
|
26
|
-
expect(response).to be_success
|
27
|
-
expect(authorization_access_token).to_not be_revoked
|
18
|
+
context 'with authenticated, confidential OAuth 2.0 client/application' do
|
19
|
+
let(:headers) do
|
20
|
+
client_id = client_application.uid
|
21
|
+
client_secret = client_application.secret
|
22
|
+
credentials = Base64.encode64("#{client_id}:#{client_secret}")
|
23
|
+
{ 'HTTP_AUTHORIZATION' => "Basic #{credentials}" }
|
28
24
|
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context 'The access token to revoke is the same than the authorization access token' do
|
32
|
-
let(:token_to_revoke) { authorization_access_token }
|
33
25
|
|
34
|
-
it '
|
35
|
-
post revocation_token_endpoint_url, { token:
|
26
|
+
it 'should revoke the access token provided' do
|
27
|
+
post revocation_token_endpoint_url, { token: access_token.token }, headers
|
36
28
|
|
37
|
-
|
38
|
-
authorization_access_token.reload
|
29
|
+
access_token.reload
|
39
30
|
|
40
31
|
expect(response).to be_success
|
41
|
-
expect(
|
42
|
-
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_truthy
|
32
|
+
expect(access_token.revoked?).to be_truthy
|
43
33
|
end
|
44
34
|
|
45
|
-
it '
|
46
|
-
|
47
|
-
post url_with_query_string, {}, headers
|
35
|
+
it 'should revoke the refresh token provided' do
|
36
|
+
post revocation_token_endpoint_url, { token: access_token.refresh_token }, headers
|
48
37
|
|
49
|
-
|
50
|
-
authorization_access_token.reload
|
38
|
+
access_token.reload
|
51
39
|
|
52
40
|
expect(response).to be_success
|
53
|
-
expect(
|
54
|
-
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_falsey
|
55
|
-
expect(authorization_access_token.revoked?).to be_falsey
|
41
|
+
expect(access_token.revoked?).to be_truthy
|
56
42
|
end
|
57
|
-
end
|
58
43
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
44
|
+
context 'with invalid token to revoke' do
|
45
|
+
it 'should not revoke any tokens and respond successfully' do
|
46
|
+
num_prev_revoked_tokens = Doorkeeper::AccessToken.where(revoked_at: nil).count
|
47
|
+
post revocation_token_endpoint_url, { token: 'I_AM_AN_INVALID_TOKEN' }, headers
|
48
|
+
|
49
|
+
# The authorization server responds with HTTP status code 200 even if
|
50
|
+
# token is invalid
|
51
|
+
expect(response).to be_success
|
52
|
+
expect(Doorkeeper::AccessToken.where(revoked_at: nil).count).to eq(num_prev_revoked_tokens)
|
53
|
+
end
|
65
54
|
end
|
66
55
|
|
67
|
-
|
68
|
-
|
56
|
+
context 'with bad credentials and a valid token' do
|
57
|
+
let(:headers) do
|
58
|
+
client_id = client_application.uid
|
59
|
+
credentials = Base64.encode64("#{client_id}:poop")
|
60
|
+
{ 'HTTP_AUTHORIZATION' => "Basic #{credentials}" }
|
61
|
+
end
|
62
|
+
it 'should not revoke any tokens and respond successfully' do
|
63
|
+
post revocation_token_endpoint_url, { token: access_token.token }, headers
|
69
64
|
|
70
|
-
|
71
|
-
authorization_access_token.reload
|
65
|
+
access_token.reload
|
72
66
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
expect(authorization_access_token.revoked?).to be_falsey
|
67
|
+
expect(response).to be_success
|
68
|
+
expect(access_token.revoked?).to be_falsey
|
69
|
+
end
|
77
70
|
end
|
78
|
-
end
|
79
71
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
72
|
+
context 'with no credentials and a valid token' do
|
73
|
+
it 'should not revoke any tokens and respond successfully' do
|
74
|
+
post revocation_token_endpoint_url, { token: access_token.token }
|
75
|
+
|
76
|
+
access_token.reload
|
77
|
+
|
78
|
+
expect(response).to be_success
|
79
|
+
expect(access_token.revoked?).to be_falsey
|
80
|
+
end
|
87
81
|
end
|
88
82
|
|
89
|
-
|
90
|
-
|
83
|
+
context 'with valid token for another client application' do
|
84
|
+
let(:other_client_application) { FactoryGirl.create :application }
|
85
|
+
let(:headers) do
|
86
|
+
client_id = other_client_application.uid
|
87
|
+
client_secret = other_client_application.secret
|
88
|
+
credentials = Base64.encode64("#{client_id}:#{client_secret}")
|
89
|
+
{ 'HTTP_AUTHORIZATION' => "Basic #{credentials}" }
|
90
|
+
end
|
91
91
|
|
92
|
-
|
93
|
-
|
92
|
+
it 'should not revoke the token as its unauthorized' do
|
93
|
+
post revocation_token_endpoint_url, { token: access_token.token }, headers
|
94
94
|
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
95
|
+
access_token.reload
|
96
|
+
|
97
|
+
expect(response).to be_success
|
98
|
+
expect(access_token.revoked?).to be_falsey
|
99
|
+
end
|
99
100
|
end
|
100
101
|
end
|
101
102
|
|
102
|
-
context '
|
103
|
-
let(:
|
104
|
-
let(:token_to_revoke) do
|
103
|
+
context 'with public OAuth 2.0 client/application' do
|
104
|
+
let(:access_token) do
|
105
105
|
FactoryGirl.create(:access_token,
|
106
|
-
application:
|
107
|
-
resource_owner_id:
|
106
|
+
application: nil,
|
107
|
+
resource_owner_id: resource_owner.id,
|
108
108
|
use_refresh_token: true)
|
109
109
|
end
|
110
110
|
|
111
|
-
it '
|
112
|
-
post revocation_token_endpoint_url, { token:
|
111
|
+
it 'should revoke the access token provided' do
|
112
|
+
post revocation_token_endpoint_url, { token: access_token.token }
|
113
113
|
|
114
|
-
|
115
|
-
authorization_access_token.reload
|
114
|
+
access_token.reload
|
116
115
|
|
117
116
|
expect(response).to be_success
|
118
|
-
expect(
|
119
|
-
expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_falsey
|
120
|
-
expect(authorization_access_token.revoked?).to be_falsey
|
117
|
+
expect(access_token.revoked?).to be_truthy
|
121
118
|
end
|
122
|
-
end
|
123
119
|
|
124
|
-
|
125
|
-
|
126
|
-
FactoryGirl.create(:access_token,
|
127
|
-
application: client_application,
|
128
|
-
resource_owner_id: resource_owner.id,
|
129
|
-
use_refresh_token: true)
|
130
|
-
end
|
120
|
+
it 'should revoke the refresh token provided' do
|
121
|
+
post revocation_token_endpoint_url, { token: access_token.refresh_token }
|
131
122
|
|
132
|
-
|
133
|
-
post revocation_token_endpoint_url, { token: token_to_revoke.refresh_token, token_type_hint: 'refresh_token' }, headers
|
134
|
-
authorization_access_token.reload
|
135
|
-
token_to_revoke.reload
|
123
|
+
access_token.reload
|
136
124
|
|
137
125
|
expect(response).to be_success
|
138
|
-
expect(
|
139
|
-
|
126
|
+
expect(access_token.revoked?).to be_truthy
|
127
|
+
end
|
128
|
+
|
129
|
+
context 'with a valid token issued for a confidential client' do
|
130
|
+
let(:access_token) do
|
131
|
+
FactoryGirl.create(:access_token,
|
132
|
+
application: client_application,
|
133
|
+
resource_owner_id: resource_owner.id,
|
134
|
+
use_refresh_token: true)
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'should not revoke the access token provided' do
|
138
|
+
post revocation_token_endpoint_url, { token: access_token.token }
|
139
|
+
|
140
|
+
access_token.reload
|
141
|
+
|
142
|
+
expect(response).to be_success
|
143
|
+
expect(access_token.revoked?).to be_falsey
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'should not revoke the refresh token provided' do
|
147
|
+
post revocation_token_endpoint_url, { token: access_token.token }
|
148
|
+
|
149
|
+
access_token.reload
|
150
|
+
|
151
|
+
expect(response).to be_success
|
152
|
+
expect(access_token.revoked?).to be_falsey
|
153
|
+
end
|
140
154
|
end
|
141
155
|
end
|
142
156
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
if ENV['TRAVIS']
|
2
|
+
require 'coveralls'
|
3
|
+
Coveralls.wear!('rails') { add_filter('/spec/') }
|
4
|
+
end
|
5
|
+
|
1
6
|
ENV['RAILS_ENV'] ||= 'test'
|
2
7
|
TABLE_NAME_PREFIX = ENV['table_name_prefix'] || nil
|
3
8
|
TABLE_NAME_SUFFIX = ENV['table_name_suffix'] || nil
|
@@ -11,7 +16,6 @@ require 'capybara/rspec'
|
|
11
16
|
require 'dummy/config/environment'
|
12
17
|
require 'rspec/rails'
|
13
18
|
require 'generator_spec/test_case'
|
14
|
-
require 'timecop'
|
15
19
|
require 'database_cleaner'
|
16
20
|
|
17
21
|
# Load JRuby SQLite3 if in that platform
|
@@ -35,6 +39,9 @@ ENGINE_RAILS_ROOT = File.join(File.dirname(__FILE__), '../')
|
|
35
39
|
|
36
40
|
Dir["#{File.dirname(__FILE__)}/support/{dependencies,helpers,shared}/*.rb"].each { |f| require f }
|
37
41
|
|
42
|
+
# Remove after dropping support of Rails 4.2
|
43
|
+
require "#{File.dirname(__FILE__)}/support/http_method_shim.rb"
|
44
|
+
|
38
45
|
RSpec.configure do |config|
|
39
46
|
config.infer_spec_type_from_file_location!
|
40
47
|
config.mock_with :rspec
|
@@ -13,14 +13,20 @@ module ModelHelper
|
|
13
13
|
|
14
14
|
def access_grant_should_exist_for(client, resource_owner)
|
15
15
|
grant = Doorkeeper::AccessGrant.first
|
16
|
-
|
17
|
-
grant.
|
16
|
+
|
17
|
+
expect(grant.application).to have_attributes(id: client.id).
|
18
|
+
and(be_instance_of(Doorkeeper::Application))
|
19
|
+
|
20
|
+
expect(grant.resource_owner_id).to eq(resource_owner.id)
|
18
21
|
end
|
19
22
|
|
20
23
|
def access_token_should_exist_for(client, resource_owner)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
+
token = Doorkeeper::AccessToken.first
|
25
|
+
|
26
|
+
expect(token.application).to have_attributes(id: client.id).
|
27
|
+
and(be_instance_of(Doorkeeper::Application))
|
28
|
+
|
29
|
+
expect(token.resource_owner_id).to eq(resource_owner.id)
|
24
30
|
end
|
25
31
|
|
26
32
|
def access_grant_should_not_exist
|
@@ -40,6 +46,22 @@ module ModelHelper
|
|
40
46
|
grant = Doorkeeper::AccessToken.last
|
41
47
|
expect(grant.scopes).to eq(Doorkeeper::OAuth::Scopes.from_array(args))
|
42
48
|
end
|
49
|
+
|
50
|
+
def uniqueness_error
|
51
|
+
case DOORKEEPER_ORM
|
52
|
+
when :active_record
|
53
|
+
ActiveRecord::RecordNotUnique
|
54
|
+
when :sequel
|
55
|
+
error_classes = [Sequel::UniqueConstraintViolation, Sequel::ValidationFailed]
|
56
|
+
proc { |error| expect(error.class).to be_in(error_classes) }
|
57
|
+
when :mongo_mapper
|
58
|
+
MongoMapper::DocumentNotValid
|
59
|
+
when /mongoid/
|
60
|
+
Mongoid::Errors::Validations
|
61
|
+
else
|
62
|
+
raise "'#{DOORKEEPER_ORM}' ORM is not supported!"
|
63
|
+
end
|
64
|
+
end
|
43
65
|
end
|
44
66
|
|
45
67
|
RSpec.configuration.send :include, ModelHelper
|
@@ -27,6 +27,10 @@ module RequestSpecHelper
|
|
27
27
|
URI.parse(page.current_url)
|
28
28
|
end
|
29
29
|
|
30
|
+
def request_response
|
31
|
+
respond_to?(:response) ? response : page.driver.response
|
32
|
+
end
|
33
|
+
|
30
34
|
def should_have_header(header, value)
|
31
35
|
expect(headers[header]).to eq(value)
|
32
36
|
end
|
@@ -44,15 +48,15 @@ module RequestSpecHelper
|
|
44
48
|
end
|
45
49
|
|
46
50
|
def should_have_json(key, value)
|
47
|
-
expect(JSON.parse(
|
51
|
+
expect(JSON.parse(request_response.body).fetch(key)).to eq(value)
|
48
52
|
end
|
49
53
|
|
50
54
|
def should_have_json_within(key, value, range)
|
51
|
-
expect(JSON.parse(
|
55
|
+
expect(JSON.parse(request_response.body).fetch(key)).to be_within(range).of(value)
|
52
56
|
end
|
53
57
|
|
54
58
|
def should_not_have_json(key)
|
55
|
-
expect(JSON.parse(
|
59
|
+
expect(JSON.parse(request_response.body)).not_to have_key(key)
|
56
60
|
end
|
57
61
|
|
58
62
|
def sign_in
|
@@ -60,6 +64,10 @@ module RequestSpecHelper
|
|
60
64
|
click_on 'Sign in'
|
61
65
|
end
|
62
66
|
|
67
|
+
def create_access_token(authorization_code, client)
|
68
|
+
page.driver.post token_endpoint_url(code: authorization_code, client: client)
|
69
|
+
end
|
70
|
+
|
63
71
|
def i_should_see_translated_error_message(key)
|
64
72
|
i_should_see translated_error_message(key)
|
65
73
|
end
|
@@ -69,7 +77,7 @@ module RequestSpecHelper
|
|
69
77
|
end
|
70
78
|
|
71
79
|
def response_status_should_be(status)
|
72
|
-
expect(
|
80
|
+
expect(request_response.status.to_i).to eq(status)
|
73
81
|
end
|
74
82
|
end
|
75
83
|
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# Rails 5 deprecates calling HTTP action methods with positional arguments
|
2
|
+
# in favor of keyword arguments. However, the keyword argument form is only
|
3
|
+
# supported in Rails 5+. Since we support back to 4, we need some sort of shim
|
4
|
+
# to avoid super noisy deprecations when running tests.
|
5
|
+
module RoutingHTTPMethodShim
|
6
|
+
def get(path, params = {}, headers = nil)
|
7
|
+
super(path, params: params, headers: headers)
|
8
|
+
end
|
9
|
+
|
10
|
+
def post(path, params = {}, headers = nil)
|
11
|
+
super(path, params: params, headers: headers)
|
12
|
+
end
|
13
|
+
|
14
|
+
def put(path, params = {}, headers = nil)
|
15
|
+
super(path, params: params, headers: headers)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module ControllerHTTPMethodShim
|
20
|
+
def get(path, params = {})
|
21
|
+
super(path, params: params)
|
22
|
+
end
|
23
|
+
|
24
|
+
def post(path, params = {})
|
25
|
+
super(path, params: params)
|
26
|
+
end
|
27
|
+
|
28
|
+
def put(path, params = {})
|
29
|
+
super(path, params: params)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
if ::Rails::VERSION::MAJOR >= 5
|
34
|
+
RSpec.configure do |config|
|
35
|
+
config.include ControllerHTTPMethodShim, type: :controller
|
36
|
+
config.include RoutingHTTPMethodShim, type: :request
|
37
|
+
end
|
38
|
+
end
|
@@ -4,11 +4,15 @@ shared_context 'valid token', token: :valid do
|
|
4
4
|
end
|
5
5
|
|
6
6
|
let :token do
|
7
|
-
double(Doorkeeper::AccessToken,
|
7
|
+
double(Doorkeeper::AccessToken,
|
8
|
+
accessible?: true, includes_scope?: true, acceptable?: true,
|
9
|
+
previous_refresh_token: "", revoke_previous_refresh_token!: true)
|
8
10
|
end
|
9
11
|
|
10
12
|
before :each do
|
11
|
-
allow(
|
13
|
+
allow(
|
14
|
+
Doorkeeper::AccessToken
|
15
|
+
).to receive(:by_token).with(token_string).and_return(token)
|
12
16
|
end
|
13
17
|
end
|
14
18
|
|
@@ -18,11 +22,16 @@ shared_context 'invalid token', token: :invalid do
|
|
18
22
|
end
|
19
23
|
|
20
24
|
let :token do
|
21
|
-
double(Doorkeeper::AccessToken,
|
25
|
+
double(Doorkeeper::AccessToken,
|
26
|
+
accessible?: false, revoked?: false, expired?: false,
|
27
|
+
includes_scope?: false, acceptable?: false,
|
28
|
+
previous_refresh_token: "", revoke_previous_refresh_token!: true)
|
22
29
|
end
|
23
30
|
|
24
31
|
before :each do
|
25
|
-
allow(
|
32
|
+
allow(
|
33
|
+
Doorkeeper::AccessToken
|
34
|
+
).to receive(:by_token).with(token_string).and_return(token)
|
26
35
|
end
|
27
36
|
end
|
28
37
|
|