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.

Files changed (137) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.gitignore +5 -0
  4. data/.travis.yml +16 -12
  5. data/Appraisals +14 -0
  6. data/CONTRIBUTING.md +2 -0
  7. data/Gemfile +5 -5
  8. data/NEWS.md +83 -2
  9. data/README.md +73 -43
  10. data/RELEASING.md +5 -12
  11. data/Rakefile +1 -1
  12. data/app/controllers/doorkeeper/application_controller.rb +3 -1
  13. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  14. data/app/controllers/doorkeeper/applications_controller.rb +3 -7
  15. data/app/controllers/doorkeeper/authorizations_controller.rb +1 -1
  16. data/app/controllers/doorkeeper/authorized_applications_controller.rb +1 -1
  17. data/app/controllers/doorkeeper/tokens_controller.rb +50 -14
  18. data/app/helpers/doorkeeper/dashboard_helper.rb +13 -11
  19. data/app/views/doorkeeper/applications/_delete_form.html.erb +1 -2
  20. data/app/views/doorkeeper/applications/_form.html.erb +1 -1
  21. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  22. data/app/views/doorkeeper/authorizations/new.html.erb +1 -1
  23. data/app/views/doorkeeper/authorized_applications/_delete_form.html.erb +1 -2
  24. data/app/views/layouts/doorkeeper/admin.html.erb +1 -1
  25. data/config/locales/en.yml +3 -2
  26. data/doorkeeper.gemspec +12 -10
  27. data/gemfiles/rails_4_2.gemfile +11 -0
  28. data/gemfiles/rails_5_0.gemfile +12 -0
  29. data/gemfiles/rails_5_1.gemfile +13 -0
  30. data/lib/doorkeeper/config.rb +73 -16
  31. data/lib/doorkeeper/engine.rb +11 -7
  32. data/lib/doorkeeper/errors.rb +18 -0
  33. data/lib/doorkeeper/grape/helpers.rb +2 -1
  34. data/lib/doorkeeper/helpers/controller.rb +8 -23
  35. data/lib/doorkeeper/models/access_grant_mixin.rb +21 -5
  36. data/lib/doorkeeper/models/access_token_mixin.rb +145 -23
  37. data/lib/doorkeeper/models/application_mixin.rb +21 -9
  38. data/lib/doorkeeper/models/concerns/accessible.rb +4 -0
  39. data/lib/doorkeeper/models/concerns/expirable.rb +10 -2
  40. data/lib/doorkeeper/models/concerns/ownership.rb +6 -1
  41. data/lib/doorkeeper/models/concerns/revocable.rb +37 -2
  42. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +20 -18
  43. data/lib/doorkeeper/oauth/authorization_code_request.rb +1 -4
  44. data/lib/doorkeeper/oauth/{request_concern.rb → base_request.rb} +3 -1
  45. data/lib/doorkeeper/oauth/base_response.rb +29 -0
  46. data/lib/doorkeeper/oauth/client/credentials.rb +17 -6
  47. data/lib/doorkeeper/oauth/client.rb +0 -1
  48. data/lib/doorkeeper/oauth/client_credentials/creator.rb +1 -1
  49. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  50. data/lib/doorkeeper/oauth/client_credentials/validation.rb +1 -1
  51. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -8
  52. data/lib/doorkeeper/oauth/code_response.rb +16 -16
  53. data/lib/doorkeeper/oauth/error_response.rb +9 -8
  54. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -1
  55. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +2 -1
  56. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -0
  57. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -13
  58. data/lib/doorkeeper/oauth/refresh_token_request.rb +22 -14
  59. data/lib/doorkeeper/oauth/scopes.rb +2 -2
  60. data/lib/doorkeeper/oauth/token.rb +20 -21
  61. data/lib/doorkeeper/oauth/token_request.rb +1 -2
  62. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  63. data/lib/doorkeeper/orm/active_record/access_token.rb +25 -0
  64. data/lib/doorkeeper/orm/active_record/application.rb +12 -12
  65. data/lib/doorkeeper/orm/active_record.rb +0 -16
  66. data/lib/doorkeeper/rails/helpers.rb +1 -3
  67. data/lib/doorkeeper/rails/routes/mapper.rb +4 -4
  68. data/lib/doorkeeper/rails/routes/mapping.rb +1 -1
  69. data/lib/doorkeeper/rails/routes.rb +4 -4
  70. data/lib/doorkeeper/request/authorization_code.rb +7 -1
  71. data/lib/doorkeeper/request/password.rb +11 -1
  72. data/lib/doorkeeper/request/refresh_token.rb +1 -1
  73. data/lib/doorkeeper/server.rb +0 -8
  74. data/lib/doorkeeper/version.rb +1 -1
  75. data/lib/doorkeeper.rb +8 -2
  76. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +29 -0
  77. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb +1 -1
  78. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb +11 -0
  79. data/lib/generators/doorkeeper/templates/initializer.rb +8 -3
  80. data/lib/generators/doorkeeper/templates/migration.rb +23 -5
  81. data/spec/controllers/application_metal_controller.rb +10 -0
  82. data/spec/controllers/authorizations_controller_spec.rb +39 -24
  83. data/spec/controllers/protected_resources_controller_spec.rb +47 -18
  84. data/spec/controllers/tokens_controller_spec.rb +1 -1
  85. data/spec/dummy/app/controllers/full_protected_resources_controller.rb +4 -4
  86. data/spec/dummy/app/controllers/home_controller.rb +1 -1
  87. data/spec/dummy/app/controllers/metal_controller.rb +1 -1
  88. data/spec/dummy/app/controllers/semi_protected_resources_controller.rb +3 -3
  89. data/spec/dummy/app/models/user.rb +0 -4
  90. data/spec/dummy/config/application.rb +2 -36
  91. data/spec/dummy/config/environment.rb +1 -1
  92. data/spec/dummy/config/environments/test.rb +4 -15
  93. data/spec/dummy/config/initializers/active_record_belongs_to_required_by_default.rb +6 -0
  94. data/spec/dummy/config/initializers/doorkeeper.rb +2 -2
  95. data/spec/dummy/db/migrate/{20130902165751_create_doorkeeper_tables.rb → 20151223192035_create_doorkeeper_tables.rb} +24 -5
  96. data/spec/dummy/db/migrate/{20130902175349_add_owner_to_application.rb → 20151223200000_add_owner_to_application.rb} +0 -0
  97. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +11 -0
  98. data/spec/dummy/db/schema.rb +23 -22
  99. data/spec/factories.rb +3 -1
  100. data/spec/lib/config_spec.rb +19 -2
  101. data/spec/lib/doorkeeper_spec.rb +135 -13
  102. data/spec/lib/models/expirable_spec.rb +0 -1
  103. data/spec/lib/models/revocable_spec.rb +27 -4
  104. data/spec/lib/oauth/authorization/uri_builder_spec.rb +1 -2
  105. data/spec/lib/oauth/authorization_code_request_spec.rb +1 -1
  106. data/spec/lib/oauth/base_request_spec.rb +160 -0
  107. data/spec/lib/oauth/base_response_spec.rb +45 -0
  108. data/spec/lib/oauth/client/credentials_spec.rb +41 -0
  109. data/spec/lib/oauth/code_response_spec.rb +34 -0
  110. data/spec/lib/oauth/error_response_spec.rb +9 -9
  111. data/spec/lib/oauth/invalid_token_response_spec.rb +36 -8
  112. data/spec/lib/oauth/password_access_token_request_spec.rb +5 -5
  113. data/spec/lib/oauth/refresh_token_request_spec.rb +34 -3
  114. data/spec/lib/oauth/scopes_spec.rb +0 -1
  115. data/spec/lib/oauth/token_spec.rb +12 -5
  116. data/spec/lib/server_spec.rb +0 -3
  117. data/spec/models/doorkeeper/access_token_spec.rb +45 -1
  118. data/spec/models/doorkeeper/application_spec.rb +3 -11
  119. data/spec/requests/endpoints/authorization_spec.rb +5 -6
  120. data/spec/requests/flows/authorization_code_errors_spec.rb +11 -1
  121. data/spec/requests/flows/authorization_code_spec.rb +4 -12
  122. data/spec/requests/flows/password_spec.rb +26 -5
  123. data/spec/requests/flows/refresh_token_spec.rb +87 -17
  124. data/spec/requests/flows/revoke_token_spec.rb +100 -86
  125. data/spec/spec_helper.rb +2 -0
  126. data/spec/spec_helper_integration.rb +8 -1
  127. data/spec/support/helpers/model_helper.rb +27 -5
  128. data/spec/support/helpers/request_spec_helper.rb +12 -4
  129. data/spec/support/http_method_shim.rb +38 -0
  130. data/spec/support/shared/controllers_shared_context.rb +13 -4
  131. data/spec/support/shared/models_shared_examples.rb +1 -1
  132. metadata +72 -42
  133. data/lib/doorkeeper/oauth/client/methods.rb +0 -18
  134. data/lib/generators/doorkeeper/application_scopes_generator.rb +0 -34
  135. data/lib/generators/doorkeeper/templates/add_scopes_to_oauth_applications.rb +0 -5
  136. data/spec/dummy/db/migrate/20141209001746_add_scopes_to_oauth_applications.rb +0 -5
  137. 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(:access_token, application: @client, resource_owner_id: 1, use_refresh_token: true)
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
- it 'client request a token with refresh token' do
44
- post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
45
- should_have_json 'refresh_token', Doorkeeper::AccessToken.last.refresh_token
46
- expect(@token.reload).to be_revoked
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
- it 'client request a token with expired access token' do
50
- @token.update_attribute :expires_in, -100
51
- post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
52
- should_have_json 'refresh_token', Doorkeeper::AccessToken.last.refresh_token
53
- expect(@token.reload).to be_revoked
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) { User.authenticate! params[:username], params[:password] }
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(client: @client, resource_owner: @resource_owner)
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(:access_token, application: @client, resource_owner_id: @resource_owner.id, use_refresh_token: true)
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
- it 'client request a token after creating another token with the same user' do
92
- post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
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
- should_have_json 'refresh_token', last_token.refresh_token
95
- expect(@token.reload).to be_revoked
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(:authorization_access_token) do
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 'With invalid token to revoke' do
20
- it 'client wants to revoke the given access token' do
21
- post revocation_token_endpoint_url, { token: 'I_AM_AN_INVALIDE_TOKEN' }, headers
22
-
23
- authorization_access_token.reload
24
- # The authorization server responds with HTTP status code 200 if the token
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 'client wants to revoke the given access token' do
35
- post revocation_token_endpoint_url, { token: token_to_revoke.token }, headers
26
+ it 'should revoke the access token provided' do
27
+ post revocation_token_endpoint_url, { token: access_token.token }, headers
36
28
 
37
- token_to_revoke.reload
38
- authorization_access_token.reload
29
+ access_token.reload
39
30
 
40
31
  expect(response).to be_success
41
- expect(token_to_revoke.revoked?).to be_truthy
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 'client wants to revoke the given access token using the POST query string' do
46
- url_with_query_string = revocation_token_endpoint_url + '?' + Rack::Utils.build_query(token: token_to_revoke.token)
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
- token_to_revoke.reload
50
- authorization_access_token.reload
38
+ access_token.reload
51
39
 
52
40
  expect(response).to be_success
53
- expect(token_to_revoke.revoked?).to be_falsey
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
- context 'The access token to revoke app and owners are the same than the authorization access token' do
60
- let(:token_to_revoke) do
61
- FactoryGirl.create(:access_token,
62
- application: client_application,
63
- resource_owner_id: resource_owner.id,
64
- use_refresh_token: true)
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
- it 'client wants to revoke the given access token' do
68
- post revocation_token_endpoint_url, { token: token_to_revoke.token }, headers
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
- token_to_revoke.reload
71
- authorization_access_token.reload
65
+ access_token.reload
72
66
 
73
- expect(response).to be_success
74
- expect(token_to_revoke.revoked?).to be_truthy
75
- expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_truthy
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
- context 'The access token to revoke authorization owner is the same than the authorization access token' do
81
- let(:other_client_application) { FactoryGirl.create :application }
82
- let(:token_to_revoke) do
83
- FactoryGirl.create(:access_token,
84
- application: other_client_application,
85
- resource_owner_id: resource_owner.id,
86
- use_refresh_token: true)
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
- it 'client wants to revoke the given access token' do
90
- post revocation_token_endpoint_url, { token: token_to_revoke.token }, headers
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
- token_to_revoke.reload
93
- authorization_access_token.reload
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
- expect(response).to be_success
96
- expect(token_to_revoke.revoked?).to be_falsey
97
- expect(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_falsey
98
- expect(authorization_access_token.revoked?).to be_falsey
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 'The access token to revoke app is the same than the authorization access token' do
103
- let(:other_resource_owner) { User.create!(name: 'Matheo', password: 'pareto') }
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: client_application,
107
- resource_owner_id: other_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 'client wants to revoke the given access token' do
112
- post revocation_token_endpoint_url, { token: token_to_revoke.token }, headers
111
+ it 'should revoke the access token provided' do
112
+ post revocation_token_endpoint_url, { token: access_token.token }
113
113
 
114
- token_to_revoke.reload
115
- authorization_access_token.reload
114
+ access_token.reload
116
115
 
117
116
  expect(response).to be_success
118
- expect(token_to_revoke.revoked?).to be_falsey
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
- context 'With valid refresh token to revoke' do
125
- let(:token_to_revoke) do
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
- it 'client wants to revoke the given refresh token' do
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(Doorkeeper::AccessToken.by_refresh_token(token_to_revoke.refresh_token).revoked?).to be_truthy
139
- expect(authorization_access_token).to_not be_revoked
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,2 +1,4 @@
1
1
  $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../lib'))
2
2
  $LOAD_PATH.unshift File.expand_path(File.join(File.dirname(__FILE__), '../app'))
3
+
4
+ require 'doorkeeper'
@@ -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
- expect(grant.application).to eq(client)
17
- grant.resource_owner_id == resource_owner.id
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
- grant = Doorkeeper::AccessToken.first
22
- expect(grant.application).to eq(client)
23
- grant.resource_owner_id == resource_owner.id
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(response.body).fetch(key)).to eq(value)
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(response.body).fetch(key)).to be_within(range).of(value)
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(response.body)).not_to have_key(key)
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(page.driver.response.status.to_i).to eq(status)
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, accessible?: true, includes_scope?: true, acceptable?: true)
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(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
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, accessible?: false, revoked?: false, expired?: false, includes_scope?: false, acceptable?: false)
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(Doorkeeper::AccessToken).to receive(:by_token).with(token_string).and_return(token)
32
+ allow(
33
+ Doorkeeper::AccessToken
34
+ ).to receive(:by_token).with(token_string).and_return(token)
26
35
  end
27
36
  end
28
37
 
@@ -46,7 +46,7 @@ shared_examples 'a unique token' do
46
46
  token2.token = token1.token
47
47
  expect do
48
48
  token2.save!(validate: false)
49
- end.to raise_error(ActiveRecord::RecordNotUnique)
49
+ end.to raise_error(uniqueness_error)
50
50
  end
51
51
  end
52
52
  end