doorkeeper 5.1.0 → 5.3.0

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.
Files changed (163) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +3 -3
  3. data/CHANGELOG.md +881 -0
  4. data/CONTRIBUTING.md +11 -9
  5. data/Dangerfile +2 -2
  6. data/Dockerfile +29 -0
  7. data/Gemfile +4 -3
  8. data/NEWS.md +1 -814
  9. data/README.md +11 -3
  10. data/RELEASING.md +6 -5
  11. data/app/controllers/doorkeeper/application_controller.rb +2 -2
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +3 -2
  13. data/app/controllers/doorkeeper/applications_controller.rb +1 -0
  14. data/app/controllers/doorkeeper/authorizations_controller.rb +16 -9
  15. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  16. data/app/controllers/doorkeeper/tokens_controller.rb +32 -9
  17. data/app/views/doorkeeper/applications/_form.html.erb +0 -6
  18. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  19. data/config/locales/en.yml +8 -2
  20. data/doorkeeper.gemspec +9 -1
  21. data/gemfiles/rails_5_0.gemfile +3 -2
  22. data/gemfiles/rails_5_1.gemfile +3 -2
  23. data/gemfiles/rails_5_2.gemfile +3 -2
  24. data/gemfiles/rails_6_0.gemfile +4 -3
  25. data/gemfiles/rails_master.gemfile +3 -2
  26. data/lib/doorkeeper/config/option.rb +13 -7
  27. data/lib/doorkeeper/config.rb +157 -42
  28. data/lib/doorkeeper/errors.rb +13 -18
  29. data/lib/doorkeeper/grape/helpers.rb +6 -2
  30. data/lib/doorkeeper/helpers/controller.rb +28 -7
  31. data/lib/doorkeeper/models/access_grant_mixin.rb +7 -6
  32. data/lib/doorkeeper/models/access_token_mixin.rb +99 -20
  33. data/lib/doorkeeper/models/application_mixin.rb +3 -3
  34. data/lib/doorkeeper/models/concerns/ownership.rb +1 -1
  35. data/lib/doorkeeper/models/concerns/reusable.rb +1 -1
  36. data/lib/doorkeeper/models/concerns/revocable.rb +0 -27
  37. data/lib/doorkeeper/oauth/authorization/code.rb +12 -14
  38. data/lib/doorkeeper/oauth/authorization/token.rb +10 -7
  39. data/lib/doorkeeper/oauth/authorization_code_request.rb +31 -15
  40. data/lib/doorkeeper/oauth/base_request.rb +10 -4
  41. data/lib/doorkeeper/oauth/client.rb +7 -8
  42. data/lib/doorkeeper/oauth/client_credentials/creator.rb +23 -2
  43. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +7 -7
  44. data/lib/doorkeeper/oauth/client_credentials/{validation.rb → validator.rb} +10 -2
  45. data/lib/doorkeeper/oauth/client_credentials_request.rb +1 -1
  46. data/lib/doorkeeper/oauth/code_request.rb +5 -11
  47. data/lib/doorkeeper/oauth/code_response.rb +4 -4
  48. data/lib/doorkeeper/oauth/error.rb +1 -1
  49. data/lib/doorkeeper/oauth/error_response.rb +6 -6
  50. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +7 -5
  51. data/lib/doorkeeper/oauth/helpers/unique_token.rb +8 -5
  52. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +19 -5
  53. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  54. data/lib/doorkeeper/oauth/invalid_token_response.rb +5 -2
  55. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  56. data/lib/doorkeeper/oauth/password_access_token_request.rb +9 -4
  57. data/lib/doorkeeper/oauth/pre_authorization.rb +76 -38
  58. data/lib/doorkeeper/oauth/refresh_token_request.rb +17 -14
  59. data/lib/doorkeeper/oauth/token.rb +2 -2
  60. data/lib/doorkeeper/oauth/token_introspection.rb +26 -16
  61. data/lib/doorkeeper/oauth/token_request.rb +4 -18
  62. data/lib/doorkeeper/orm/active_record/access_grant.rb +4 -43
  63. data/lib/doorkeeper/orm/active_record/access_token.rb +4 -35
  64. data/lib/doorkeeper/orm/active_record/application.rb +5 -83
  65. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +53 -0
  66. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +47 -0
  67. data/lib/doorkeeper/orm/active_record/mixins/application.rb +128 -0
  68. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
  69. data/lib/doorkeeper/orm/active_record.rb +21 -6
  70. data/lib/doorkeeper/rails/helpers.rb +4 -4
  71. data/lib/doorkeeper/rails/routes.rb +5 -7
  72. data/lib/doorkeeper/rake/db.rake +3 -3
  73. data/lib/doorkeeper/request/authorization_code.rb +5 -3
  74. data/lib/doorkeeper/request/client_credentials.rb +2 -2
  75. data/lib/doorkeeper/request/password.rb +2 -2
  76. data/lib/doorkeeper/request/refresh_token.rb +3 -3
  77. data/lib/doorkeeper/request.rb +7 -12
  78. data/lib/doorkeeper/server.rb +3 -7
  79. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  80. data/lib/doorkeeper/version.rb +1 -1
  81. data/lib/doorkeeper.rb +6 -3
  82. data/lib/generators/doorkeeper/application_owner_generator.rb +1 -1
  83. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  84. data/lib/generators/doorkeeper/migration_generator.rb +1 -1
  85. data/lib/generators/doorkeeper/pkce_generator.rb +1 -1
  86. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +7 -7
  87. data/lib/generators/doorkeeper/templates/initializer.rb +149 -33
  88. data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
  89. data/spec/controllers/application_metal_controller_spec.rb +1 -1
  90. data/spec/controllers/applications_controller_spec.rb +95 -1
  91. data/spec/controllers/authorizations_controller_spec.rb +156 -75
  92. data/spec/controllers/protected_resources_controller_spec.rb +28 -20
  93. data/spec/controllers/token_info_controller_spec.rb +1 -1
  94. data/spec/controllers/tokens_controller_spec.rb +206 -38
  95. data/spec/dummy/config/application.rb +3 -1
  96. data/spec/dummy/config/initializers/doorkeeper.rb +54 -9
  97. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +3 -3
  98. data/spec/dummy/db/migrate/20160320211015_add_previous_refresh_token_to_access_tokens.rb +1 -1
  99. data/spec/dummy/db/migrate/20180210183654_add_confidential_to_applications.rb +1 -1
  100. data/spec/generators/install_generator_spec.rb +1 -1
  101. data/spec/generators/previous_refresh_token_generator_spec.rb +2 -2
  102. data/spec/helpers/doorkeeper/dashboard_helper_spec.rb +1 -1
  103. data/spec/lib/config_spec.rb +104 -7
  104. data/spec/lib/doorkeeper_spec.rb +1 -1
  105. data/spec/lib/models/revocable_spec.rb +3 -3
  106. data/spec/lib/oauth/authorization_code_request_spec.rb +129 -115
  107. data/spec/lib/oauth/base_request_spec.rb +154 -135
  108. data/spec/lib/oauth/base_response_spec.rb +27 -29
  109. data/spec/lib/oauth/client/credentials_spec.rb +1 -1
  110. data/spec/lib/oauth/client_credentials/creator_spec.rb +43 -3
  111. data/spec/lib/oauth/client_credentials/issuer_spec.rb +12 -12
  112. data/spec/lib/oauth/client_credentials/validation_spec.rb +4 -4
  113. data/spec/lib/oauth/client_credentials_integration_spec.rb +16 -18
  114. data/spec/lib/oauth/client_credentials_request_spec.rb +78 -80
  115. data/spec/lib/oauth/client_spec.rb +26 -26
  116. data/spec/lib/oauth/code_request_spec.rb +34 -35
  117. data/spec/lib/oauth/code_response_spec.rb +21 -25
  118. data/spec/lib/oauth/error_response_spec.rb +42 -44
  119. data/spec/lib/oauth/error_spec.rb +12 -14
  120. data/spec/lib/oauth/forbidden_token_response_spec.rb +11 -13
  121. data/spec/lib/oauth/helpers/scope_checker_spec.rb +30 -18
  122. data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -2
  123. data/spec/lib/oauth/invalid_request_response_spec.rb +73 -0
  124. data/spec/lib/oauth/invalid_token_response_spec.rb +32 -34
  125. data/spec/lib/oauth/password_access_token_request_spec.rb +145 -147
  126. data/spec/lib/oauth/pre_authorization_spec.rb +161 -153
  127. data/spec/lib/oauth/refresh_token_request_spec.rb +138 -138
  128. data/spec/lib/oauth/scopes_spec.rb +104 -106
  129. data/spec/lib/oauth/token_request_spec.rb +117 -110
  130. data/spec/lib/oauth/token_response_spec.rb +71 -73
  131. data/spec/lib/oauth/token_spec.rb +121 -123
  132. data/spec/lib/server_spec.rb +0 -12
  133. data/spec/models/doorkeeper/access_grant_spec.rb +21 -4
  134. data/spec/models/doorkeeper/access_token_spec.rb +42 -11
  135. data/spec/models/doorkeeper/application_spec.rb +114 -77
  136. data/spec/requests/applications/applications_request_spec.rb +1 -1
  137. data/spec/requests/endpoints/authorization_spec.rb +26 -8
  138. data/spec/requests/endpoints/token_spec.rb +1 -1
  139. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
  140. data/spec/requests/flows/authorization_code_spec.rb +123 -45
  141. data/spec/requests/flows/client_credentials_spec.rb +38 -0
  142. data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
  143. data/spec/requests/flows/implicit_grant_spec.rb +9 -8
  144. data/spec/requests/flows/password_spec.rb +67 -10
  145. data/spec/requests/flows/refresh_token_spec.rb +20 -20
  146. data/spec/requests/flows/revoke_token_spec.rb +37 -23
  147. data/spec/spec_helper.rb +1 -4
  148. data/spec/support/doorkeeper_rspec.rb +1 -1
  149. data/spec/support/helpers/request_spec_helper.rb +14 -2
  150. data/spec/support/shared/controllers_shared_context.rb +33 -23
  151. data/spec/validators/redirect_uri_validator_spec.rb +41 -16
  152. metadata +19 -16
  153. data/.coveralls.yml +0 -1
  154. data/.github/ISSUE_TEMPLATE.md +0 -25
  155. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  156. data/.gitignore +0 -20
  157. data/.gitlab-ci.yml +0 -16
  158. data/.hound.yml +0 -3
  159. data/.rspec +0 -1
  160. data/.rubocop.yml +0 -50
  161. data/.travis.yml +0 -35
  162. data/app/validators/redirect_uri_validator.rb +0 -50
  163. data/spec/support/http_method_shim.rb +0 -29
@@ -44,17 +44,17 @@ describe "Refresh Token Flow" do
44
44
  :access_token,
45
45
  application: @client,
46
46
  resource_owner_id: 1,
47
- use_refresh_token: true
47
+ use_refresh_token: true,
48
48
  )
49
49
  end
50
50
 
51
51
  context "refresh_token revoked on use" do
52
52
  it "client request a token with refresh token" do
53
53
  post refresh_token_endpoint_url(
54
- client: @client, refresh_token: @token.refresh_token
54
+ client: @client, refresh_token: @token.refresh_token,
55
55
  )
56
56
  should_have_json(
57
- "refresh_token", Doorkeeper::AccessToken.last.refresh_token
57
+ "refresh_token", Doorkeeper::AccessToken.last.refresh_token,
58
58
  )
59
59
  expect(@token.reload).not_to be_revoked
60
60
  end
@@ -62,10 +62,10 @@ describe "Refresh Token Flow" do
62
62
  it "client request a token with expired access token" do
63
63
  @token.update_attribute :expires_in, -100
64
64
  post refresh_token_endpoint_url(
65
- client: @client, refresh_token: @token.refresh_token
65
+ client: @client, refresh_token: @token.refresh_token,
66
66
  )
67
67
  should_have_json(
68
- "refresh_token", Doorkeeper::AccessToken.last.refresh_token
68
+ "refresh_token", Doorkeeper::AccessToken.last.refresh_token,
69
69
  )
70
70
  expect(@token.reload).not_to be_revoked
71
71
  end
@@ -78,10 +78,10 @@ describe "Refresh Token Flow" do
78
78
 
79
79
  it "client request a token with refresh token" do
80
80
  post refresh_token_endpoint_url(
81
- client: @client, refresh_token: @token.refresh_token
81
+ client: @client, refresh_token: @token.refresh_token,
82
82
  )
83
83
  should_have_json(
84
- "refresh_token", Doorkeeper::AccessToken.last.refresh_token
84
+ "refresh_token", Doorkeeper::AccessToken.last.refresh_token,
85
85
  )
86
86
  expect(@token.reload).to be_revoked
87
87
  end
@@ -89,10 +89,10 @@ describe "Refresh Token Flow" do
89
89
  it "client request a token with expired access token" do
90
90
  @token.update_attribute :expires_in, -100
91
91
  post refresh_token_endpoint_url(
92
- client: @client, refresh_token: @token.refresh_token
92
+ client: @client, refresh_token: @token.refresh_token,
93
93
  )
94
94
  should_have_json(
95
- "refresh_token", Doorkeeper::AccessToken.last.refresh_token
95
+ "refresh_token", Doorkeeper::AccessToken.last.refresh_token,
96
96
  )
97
97
  expect(@token.reload).to be_revoked
98
98
  end
@@ -102,7 +102,7 @@ describe "Refresh Token Flow" do
102
102
  let(:public_client) do
103
103
  FactoryBot.create(
104
104
  :application,
105
- confidential: false
105
+ confidential: false,
106
106
  )
107
107
  end
108
108
 
@@ -111,7 +111,7 @@ describe "Refresh Token Flow" do
111
111
  :access_token,
112
112
  application: @client,
113
113
  resource_owner_id: 1,
114
- use_refresh_token: true
114
+ use_refresh_token: true,
115
115
  )
116
116
  end
117
117
 
@@ -120,14 +120,14 @@ describe "Refresh Token Flow" do
120
120
  :access_token,
121
121
  application: public_client,
122
122
  resource_owner_id: 1,
123
- use_refresh_token: true
123
+ use_refresh_token: true,
124
124
  )
125
125
  end
126
126
 
127
127
  it "issues a new token without client_secret when refresh token was issued to a public client" do
128
128
  post refresh_token_endpoint_url(
129
129
  client_id: public_client.uid,
130
- refresh_token: token_for_public_client.refresh_token
130
+ refresh_token: token_for_public_client.refresh_token,
131
131
  )
132
132
 
133
133
  new_token = Doorkeeper::AccessToken.last
@@ -146,7 +146,7 @@ describe "Refresh Token Flow" do
146
146
  post refresh_token_endpoint_url(
147
147
  client_id: "1",
148
148
  client_secret: "1",
149
- refresh_token: token_for_private_client.refresh_token
149
+ refresh_token: token_for_private_client.refresh_token,
150
150
  )
151
151
 
152
152
  should_not_have_json "refresh_token"
@@ -172,7 +172,7 @@ describe "Refresh Token Flow" do
172
172
  post refresh_token_endpoint_url(client: @client, refresh_token: @token.refresh_token)
173
173
 
174
174
  should_not_have_json "refresh_token"
175
- should_have_json "error", "invalid_request"
175
+ should_have_json "error", "invalid_grant"
176
176
  end
177
177
  end
178
178
 
@@ -185,7 +185,7 @@ describe "Refresh Token Flow" do
185
185
  end
186
186
  create_resource_owner
187
187
  _another_token = post password_token_endpoint_url(
188
- client: @client, resource_owner: @resource_owner
188
+ client: @client, resource_owner: @resource_owner,
189
189
  )
190
190
  last_token.update_attribute :created_at, 5.seconds.ago
191
191
 
@@ -193,7 +193,7 @@ describe "Refresh Token Flow" do
193
193
  :access_token,
194
194
  application: @client,
195
195
  resource_owner_id: @resource_owner.id,
196
- use_refresh_token: true
196
+ use_refresh_token: true,
197
197
  )
198
198
  @token.update_attribute :expires_in, -100
199
199
  end
@@ -201,7 +201,7 @@ describe "Refresh Token Flow" do
201
201
  context "refresh_token revoked on use" do
202
202
  it "client request a token after creating another token with the same user" do
203
203
  post refresh_token_endpoint_url(
204
- client: @client, refresh_token: @token.refresh_token
204
+ client: @client, refresh_token: @token.refresh_token,
205
205
  )
206
206
 
207
207
  should_have_json "refresh_token", last_token.refresh_token
@@ -216,7 +216,7 @@ describe "Refresh Token Flow" do
216
216
 
217
217
  it "client request a token after creating another token with the same user" do
218
218
  post refresh_token_endpoint_url(
219
- client: @client, refresh_token: @token.refresh_token
219
+ client: @client, refresh_token: @token.refresh_token,
220
220
  )
221
221
 
222
222
  should_have_json "refresh_token", last_token.refresh_token
@@ -226,7 +226,7 @@ describe "Refresh Token Flow" do
226
226
 
227
227
  def last_token
228
228
  Doorkeeper::AccessToken.last_authorized_token_for(
229
- @client.id, @resource_owner.id
229
+ @client.id, @resource_owner.id,
230
230
  )
231
231
  end
232
232
  end
@@ -11,10 +11,12 @@ describe "Revoke Token Flow" do
11
11
  let(:client_application) { FactoryBot.create :application }
12
12
  let(:resource_owner) { User.create!(name: "John", password: "sekret") }
13
13
  let(:access_token) do
14
- FactoryBot.create(:access_token,
15
- application: client_application,
16
- resource_owner_id: resource_owner.id,
17
- use_refresh_token: true)
14
+ FactoryBot.create(
15
+ :access_token,
16
+ application: client_application,
17
+ resource_owner_id: resource_owner.id,
18
+ use_refresh_token: true,
19
+ )
18
20
  end
19
21
 
20
22
  context "with authenticated, confidential OAuth 2.0 client/application" do
@@ -40,16 +42,14 @@ describe "Revoke Token Flow" do
40
42
  end
41
43
 
42
44
  context "with invalid token to revoke" do
43
- it "should not revoke any tokens and respond successfully" do
45
+ it "should not revoke any tokens and respond with forbidden" do
44
46
  expect do
45
47
  post revocation_token_endpoint_url,
46
48
  params: { token: "I_AM_AN_INVALID_TOKEN" },
47
49
  headers: headers
48
50
  end.not_to(change { Doorkeeper::AccessToken.where(revoked_at: nil).count })
49
51
 
50
- # The authorization server responds with HTTP status code 200 even if
51
- # token is invalid
52
- expect(response).to be_successful
52
+ expect(response).to be_forbidden
53
53
  end
54
54
  end
55
55
 
@@ -59,19 +59,23 @@ describe "Revoke Token Flow" do
59
59
  credentials = Base64.encode64("#{client_id}:poop")
60
60
  { "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
61
61
  end
62
- it "should not revoke any tokens and respond successfully" do
62
+ it "should not revoke any tokens and respond with forbidden" do
63
63
  post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
64
64
 
65
- expect(response).to be_successful
65
+ expect(response).to be_forbidden
66
+ expect(response.body).to include("unauthorized_client")
67
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
66
68
  expect(access_token.reload.revoked?).to be_falsey
67
69
  end
68
70
  end
69
71
 
70
72
  context "with no credentials and a valid token" do
71
- it "should not revoke any tokens and respond successfully" do
73
+ it "should not revoke any tokens and respond with forbidden" do
72
74
  post revocation_token_endpoint_url, params: { token: access_token.token }
73
75
 
74
- expect(response).to be_successful
76
+ expect(response).to be_forbidden
77
+ expect(response.body).to include("unauthorized_client")
78
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
75
79
  expect(access_token.reload.revoked?).to be_falsey
76
80
  end
77
81
  end
@@ -88,7 +92,9 @@ describe "Revoke Token Flow" do
88
92
  it "should not revoke the token as its unauthorized" do
89
93
  post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
90
94
 
91
- expect(response).to be_successful
95
+ expect(response).to be_forbidden
96
+ expect(response.body).to include("unauthorized_client")
97
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
92
98
  expect(access_token.reload.revoked?).to be_falsey
93
99
  end
94
100
  end
@@ -96,10 +102,12 @@ describe "Revoke Token Flow" do
96
102
 
97
103
  context "with public OAuth 2.0 client/application" do
98
104
  let(:access_token) do
99
- FactoryBot.create(:access_token,
100
- application: nil,
101
- resource_owner_id: resource_owner.id,
102
- use_refresh_token: true)
105
+ FactoryBot.create(
106
+ :access_token,
107
+ application: nil,
108
+ resource_owner_id: resource_owner.id,
109
+ use_refresh_token: true,
110
+ )
103
111
  end
104
112
 
105
113
  it "should revoke the access token provided" do
@@ -118,23 +126,29 @@ describe "Revoke Token Flow" do
118
126
 
119
127
  context "with a valid token issued for a confidential client" do
120
128
  let(:access_token) do
121
- FactoryBot.create(:access_token,
122
- application: client_application,
123
- resource_owner_id: resource_owner.id,
124
- use_refresh_token: true)
129
+ FactoryBot.create(
130
+ :access_token,
131
+ application: client_application,
132
+ resource_owner_id: resource_owner.id,
133
+ use_refresh_token: true,
134
+ )
125
135
  end
126
136
 
127
137
  it "should not revoke the access token provided" do
128
138
  post revocation_token_endpoint_url, params: { token: access_token.token }
129
139
 
130
- expect(response).to be_successful
140
+ expect(response).to be_forbidden
141
+ expect(response.body).to include("unauthorized_client")
142
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
131
143
  expect(access_token.reload.revoked?).to be_falsey
132
144
  end
133
145
 
134
146
  it "should not revoke the refresh token provided" do
135
147
  post revocation_token_endpoint_url, params: { token: access_token.token }
136
148
 
137
- expect(response).to be_successful
149
+ expect(response).to be_forbidden
150
+ expect(response.body).to include("unauthorized_client")
151
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
138
152
  expect(access_token.reload.revoked?).to be_falsey
139
153
  end
140
154
  end
data/spec/spec_helper.rb CHANGED
@@ -29,12 +29,9 @@ end
29
29
 
30
30
  Doorkeeper::RSpec.print_configuration_info
31
31
 
32
- # Remove after dropping support of Rails 4.2
33
- require "#{File.dirname(__FILE__)}/support/http_method_shim"
34
-
35
32
  require "support/orm/#{DOORKEEPER_ORM}"
36
33
 
37
- Dir["#{File.dirname(__FILE__)}/support/{dependencies,helpers,shared}/*.rb"].each { |file| require file }
34
+ Dir["#{File.dirname(__FILE__)}/support/{dependencies,helpers,shared}/*.rb"].sort.each { |file| require file }
38
35
 
39
36
  RSpec.configure do |config|
40
37
  config.infer_spec_type_from_file_location!
@@ -16,7 +16,7 @@ module Doorkeeper
16
16
  # Tries to find ORM from the Gemfile used to run test suite
17
17
  def self.detect_orm
18
18
  orm = (ENV["BUNDLE_GEMFILE"] || "").match(/Gemfile\.(.+)\.rb/)
19
- (orm && orm[1] || :active_record).to_sym
19
+ (orm && orm[1] || ENV["ORM"] || :active_record).to_sym
20
20
  end
21
21
  end
22
22
  end
@@ -54,7 +54,7 @@ module RequestSpecHelper
54
54
  end
55
55
 
56
56
  def with_header(header, value)
57
- page.driver.header header, value
57
+ page.driver.header(header, value)
58
58
  end
59
59
 
60
60
  def basic_auth_header_for_client(client)
@@ -86,8 +86,20 @@ module RequestSpecHelper
86
86
  i_should_see translated_error_message(key)
87
87
  end
88
88
 
89
+ def i_should_not_see_translated_error_message(key)
90
+ i_should_not_see translated_error_message(key)
91
+ end
92
+
89
93
  def translated_error_message(key)
90
- I18n.translate key, scope: %i[doorkeeper errors messages]
94
+ I18n.translate(key, scope: %i[doorkeeper errors messages])
95
+ end
96
+
97
+ def i_should_see_translated_invalid_request_error_message(key, value)
98
+ i_should_see translated_invalid_request_error_message(key, value)
99
+ end
100
+
101
+ def translated_invalid_request_error_message(key, value)
102
+ I18n.translate key, scope: %i[doorkeeper errors messages invalid_request], value: value
91
103
  end
92
104
 
93
105
  def response_status_should_be(status)
@@ -4,14 +4,16 @@ shared_context "valid token", token: :valid do
4
4
  let(:token_string) { "1A2B3C4D" }
5
5
 
6
6
  let :token do
7
- double(Doorkeeper::AccessToken,
8
- accessible?: true, includes_scope?: true, acceptable?: true,
9
- previous_refresh_token: "", revoke_previous_refresh_token!: true)
7
+ double(
8
+ Doorkeeper::AccessToken,
9
+ accessible?: true, includes_scope?: true, acceptable?: true,
10
+ previous_refresh_token: "", revoke_previous_refresh_token!: true,
11
+ )
10
12
  end
11
13
 
12
14
  before :each do
13
15
  allow(
14
- Doorkeeper::AccessToken
16
+ Doorkeeper::AccessToken,
15
17
  ).to receive(:by_token).with(token_string).and_return(token)
16
18
  end
17
19
  end
@@ -20,15 +22,17 @@ shared_context "invalid token", token: :invalid do
20
22
  let(:token_string) { "1A2B3C4D" }
21
23
 
22
24
  let :token do
23
- double(Doorkeeper::AccessToken,
24
- accessible?: false, revoked?: false, expired?: false,
25
- includes_scope?: false, acceptable?: false,
26
- previous_refresh_token: "", revoke_previous_refresh_token!: true)
25
+ double(
26
+ Doorkeeper::AccessToken,
27
+ accessible?: false, revoked?: false, expired?: false,
28
+ includes_scope?: false, acceptable?: false,
29
+ previous_refresh_token: "", revoke_previous_refresh_token!: true,
30
+ )
27
31
  end
28
32
 
29
33
  before :each do
30
34
  allow(
31
- Doorkeeper::AccessToken
35
+ Doorkeeper::AccessToken,
32
36
  ).to receive(:by_token).with(token_string).and_return(token)
33
37
  end
34
38
  end
@@ -72,15 +76,17 @@ shared_context "expired token", token: :expired do
72
76
  end
73
77
 
74
78
  let :token do
75
- double(Doorkeeper::AccessToken,
76
- accessible?: false, revoked?: false, expired?: true,
77
- includes_scope?: false, acceptable?: false,
78
- previous_refresh_token: "", revoke_previous_refresh_token!: true)
79
+ double(
80
+ Doorkeeper::AccessToken,
81
+ accessible?: false, revoked?: false, expired?: true,
82
+ includes_scope?: false, acceptable?: false,
83
+ previous_refresh_token: "", revoke_previous_refresh_token!: true,
84
+ )
79
85
  end
80
86
 
81
87
  before :each do
82
88
  allow(
83
- Doorkeeper::AccessToken
89
+ Doorkeeper::AccessToken,
84
90
  ).to receive(:by_token).with(token_string).and_return(token)
85
91
  end
86
92
  end
@@ -91,15 +97,17 @@ shared_context "revoked token", token: :revoked do
91
97
  end
92
98
 
93
99
  let :token do
94
- double(Doorkeeper::AccessToken,
95
- accessible?: false, revoked?: true, expired?: false,
96
- includes_scope?: false, acceptable?: false,
97
- previous_refresh_token: "", revoke_previous_refresh_token!: true)
100
+ double(
101
+ Doorkeeper::AccessToken,
102
+ accessible?: false, revoked?: true, expired?: false,
103
+ includes_scope?: false, acceptable?: false,
104
+ previous_refresh_token: "", revoke_previous_refresh_token!: true,
105
+ )
98
106
  end
99
107
 
100
108
  before :each do
101
109
  allow(
102
- Doorkeeper::AccessToken
110
+ Doorkeeper::AccessToken,
103
111
  ).to receive(:by_token).with(token_string).and_return(token)
104
112
  end
105
113
  end
@@ -110,14 +118,16 @@ shared_context "forbidden token", token: :forbidden do
110
118
  end
111
119
 
112
120
  let :token do
113
- double(Doorkeeper::AccessToken,
114
- accessible?: true, includes_scope?: true, acceptable?: false,
115
- previous_refresh_token: "", revoke_previous_refresh_token!: true)
121
+ double(
122
+ Doorkeeper::AccessToken,
123
+ accessible?: true, includes_scope?: true, acceptable?: false,
124
+ previous_refresh_token: "", revoke_previous_refresh_token!: true,
125
+ )
116
126
  end
117
127
 
118
128
  before :each do
119
129
  allow(
120
- Doorkeeper::AccessToken
130
+ Doorkeeper::AccessToken,
121
131
  ).to receive(:by_token).with(token_string).and_return(token)
122
132
  end
123
133
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require "spec_helper"
4
4
 
5
- describe RedirectUriValidator do
5
+ describe Doorkeeper::RedirectUriValidator do
6
6
  subject do
7
7
  FactoryBot.create(:application)
8
8
  end
@@ -18,7 +18,7 @@ describe RedirectUriValidator do
18
18
  #
19
19
  # @see https://www.oauth.com/oauth2-servers/redirect-uris/redirect-uris-native-apps/
20
20
  it "is valid when the uri is custom native URI" do
21
- subject.redirect_uri = "myapp://callback"
21
+ subject.redirect_uri = "myapp:/callback"
22
22
  expect(subject).to be_valid
23
23
  end
24
24
 
@@ -27,33 +27,48 @@ describe RedirectUriValidator do
27
27
  expect(subject).to be_valid
28
28
  end
29
29
 
30
- it "accepts native redirect uri" do
30
+ it "accepts nonstandard oob redirect uri" do
31
31
  subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
32
32
  expect(subject).to be_valid
33
33
  end
34
34
 
35
- it "rejects if test uri is disabled" do
36
- allow(RedirectUriValidator).to receive(:native_redirect_uri).and_return(nil)
37
- subject.redirect_uri = "urn:some:test"
38
- expect(subject).not_to be_valid
35
+ it "accepts nonstandard oob:auto redirect uri" do
36
+ subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob:auto"
37
+ expect(subject).to be_valid
39
38
  end
40
39
 
41
40
  it "is invalid when the uri is not a uri" do
42
41
  subject.redirect_uri = "]"
43
42
  expect(subject).not_to be_valid
44
- expect(subject.errors[:redirect_uri].first).to eq("must be a valid URI.")
43
+ expect(subject.errors[:redirect_uri].first).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.invalid_uri"))
45
44
  end
46
45
 
47
46
  it "is invalid when the uri is relative" do
48
47
  subject.redirect_uri = "/abcd"
49
48
  expect(subject).not_to be_valid
50
- expect(subject.errors[:redirect_uri].first).to eq("must be an absolute URI.")
49
+ expect(subject.errors[:redirect_uri].first).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.relative_uri"))
51
50
  end
52
51
 
53
52
  it "is invalid when the uri has a fragment" do
54
53
  subject.redirect_uri = "https://example.com/abcd#xyz"
55
54
  expect(subject).not_to be_valid
56
- expect(subject.errors[:redirect_uri].first).to eq("cannot contain a fragment.")
55
+ expect(subject.errors[:redirect_uri].first).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.fragment_present"))
56
+ end
57
+
58
+ it "is invalid when scheme resolves to localhost (needs an explict scheme)" do
59
+ subject.redirect_uri = "localhost:80"
60
+ expect(subject).to be_invalid
61
+ expect(subject.errors[:redirect_uri].first).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.unspecified_scheme"))
62
+ end
63
+
64
+ it "is invalid if an ip address" do
65
+ subject.redirect_uri = "127.0.0.1:8080"
66
+ expect(subject).to be_invalid
67
+ end
68
+
69
+ it "accepts an ip address based URI if a scheme is specified" do
70
+ subject.redirect_uri = "https://127.0.0.1:8080"
71
+ expect(subject).to be_valid
57
72
  end
58
73
 
59
74
  context "force secured uri" do
@@ -62,20 +77,30 @@ describe RedirectUriValidator do
62
77
  expect(subject).to be_valid
63
78
  end
64
79
 
65
- it "accepts native redirect uri" do
66
- subject.redirect_uri = "urn:ietf:wg:oauth:2.0:oob"
80
+ it "accepts custom scheme redirect uri (as per rfc8252 section 7.1)" do
81
+ subject.redirect_uri = "com.example.app:/oauth/callback"
82
+ expect(subject).to be_valid
83
+ end
84
+
85
+ it "accepts custom scheme redirect uri (as per rfc8252 section 7.1) #2" do
86
+ subject.redirect_uri = "com.example.app:/test"
87
+ expect(subject).to be_valid
88
+ end
89
+
90
+ it "accepts custom scheme redirect uri (common misconfiguration we have decided to allow)" do
91
+ subject.redirect_uri = "com.example.app://oauth/callback"
67
92
  expect(subject).to be_valid
68
93
  end
69
94
 
70
- it "accepts app redirect uri" do
71
- subject.redirect_uri = "some-awesome-app://oauth/callback"
95
+ it "accepts custom scheme redirect uri (common misconfiguration we have decided to allow) #2" do
96
+ subject.redirect_uri = "com.example.app://test"
72
97
  expect(subject).to be_valid
73
98
  end
74
99
 
75
100
  it "accepts a non secured protocol when disabled" do
76
101
  subject.redirect_uri = "http://example.com/callback"
77
102
  allow(Doorkeeper.configuration).to receive(
78
- :force_ssl_in_redirect_uri
103
+ :force_ssl_in_redirect_uri,
79
104
  ).and_return(false)
80
105
  expect(subject).to be_valid
81
106
  end
@@ -118,7 +143,7 @@ describe RedirectUriValidator do
118
143
  subject.redirect_uri = "http://example.com/callback"
119
144
  expect(subject).not_to be_valid
120
145
  error = subject.errors[:redirect_uri].first
121
- expect(error).to eq("must be an HTTPS/SSL URI.")
146
+ expect(error).to eq(I18n.t("activerecord.errors.models.doorkeeper/application.attributes.redirect_uri.secured_uri"))
122
147
  end
123
148
  end
124
149