doorkeeper 5.3.0 → 5.4.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.
Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +0 -14
  3. data/CHANGELOG.md +44 -1
  4. data/Dangerfile +7 -7
  5. data/Dockerfile +2 -2
  6. data/Gemfile +9 -9
  7. data/README.md +6 -4
  8. data/app/controllers/doorkeeper/applications_controller.rb +4 -4
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +2 -2
  11. data/app/controllers/doorkeeper/tokens_controller.rb +57 -20
  12. data/app/views/doorkeeper/applications/show.html.erb +19 -2
  13. data/bin/console +14 -0
  14. data/config/locales/en.yml +3 -1
  15. data/doorkeeper.gemspec +1 -1
  16. data/gemfiles/rails_5_0.gemfile +8 -7
  17. data/gemfiles/rails_5_1.gemfile +8 -7
  18. data/gemfiles/rails_5_2.gemfile +8 -7
  19. data/gemfiles/rails_6_0.gemfile +8 -7
  20. data/gemfiles/rails_master.gemfile +8 -7
  21. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  22. data/lib/doorkeeper/config/option.rb +28 -14
  23. data/lib/doorkeeper/config.rb +41 -17
  24. data/lib/doorkeeper/grape/helpers.rb +1 -1
  25. data/lib/doorkeeper/models/access_grant_mixin.rb +9 -11
  26. data/lib/doorkeeper/models/access_token_mixin.rb +102 -42
  27. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  28. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  29. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  30. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  31. data/lib/doorkeeper/oauth/authorization/code.rb +14 -5
  32. data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
  33. data/lib/doorkeeper/oauth/authorization/token.rb +7 -11
  34. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  35. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
  36. data/lib/doorkeeper/oauth/base_request.rb +11 -19
  37. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  38. data/lib/doorkeeper/oauth/client.rb +1 -1
  39. data/lib/doorkeeper/oauth/client_credentials/creator.rb +25 -7
  40. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  41. data/lib/doorkeeper/oauth/client_credentials/validator.rb +1 -1
  42. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  43. data/lib/doorkeeper/oauth/code_request.rb +1 -1
  44. data/lib/doorkeeper/oauth/code_response.rb +6 -2
  45. data/lib/doorkeeper/oauth/error_response.rb +2 -4
  46. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
  47. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  48. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  49. data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -5
  50. data/lib/doorkeeper/oauth/pre_authorization.rb +32 -27
  51. data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
  52. data/lib/doorkeeper/oauth/token.rb +1 -1
  53. data/lib/doorkeeper/oauth/token_introspection.rb +3 -3
  54. data/lib/doorkeeper/oauth/token_request.rb +2 -2
  55. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  56. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +7 -2
  57. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +6 -2
  58. data/lib/doorkeeper/orm/active_record/mixins/application.rb +6 -2
  59. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  60. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  61. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  62. data/lib/doorkeeper/rails/routes.rb +13 -17
  63. data/lib/doorkeeper/request/strategy.rb +2 -2
  64. data/lib/doorkeeper/server.rb +3 -3
  65. data/lib/doorkeeper/version.rb +2 -2
  66. data/lib/doorkeeper.rb +106 -79
  67. data/lib/generators/doorkeeper/confidential_applications_generator.rb +1 -1
  68. data/lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb +39 -0
  69. data/lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb +2 -0
  70. data/lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb +2 -0
  71. data/lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb +2 -0
  72. data/lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb +17 -0
  73. data/lib/generators/doorkeeper/templates/initializer.rb +47 -3
  74. data/lib/generators/doorkeeper/templates/migration.rb.erb +2 -0
  75. data/spec/controllers/applications_controller_spec.rb +2 -2
  76. data/spec/controllers/authorizations_controller_spec.rb +165 -30
  77. data/spec/controllers/tokens_controller_spec.rb +6 -5
  78. data/spec/dummy/app/helpers/application_helper.rb +1 -1
  79. data/spec/dummy/app/models/user.rb +5 -1
  80. data/spec/dummy/config/application.rb +6 -4
  81. data/spec/dummy/config/boot.rb +4 -4
  82. data/spec/dummy/config/environment.rb +1 -1
  83. data/spec/dummy/config/routes.rb +4 -4
  84. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +2 -2
  85. data/spec/dummy/db/schema.rb +3 -1
  86. data/spec/factories.rb +1 -1
  87. data/spec/generators/enable_polymorphic_resource_owner_generator_spec.rb +47 -0
  88. data/spec/lib/config_spec.rb +30 -11
  89. data/spec/lib/models/revocable_spec.rb +2 -3
  90. data/spec/lib/models/scopes_spec.rb +8 -0
  91. data/spec/lib/oauth/authorization_code_request_spec.rb +25 -15
  92. data/spec/lib/oauth/base_request_spec.rb +6 -20
  93. data/spec/lib/oauth/client_credentials/creator_spec.rb +90 -89
  94. data/spec/lib/oauth/client_credentials/issuer_spec.rb +84 -86
  95. data/spec/lib/oauth/client_credentials/validation_spec.rb +38 -40
  96. data/spec/lib/oauth/client_credentials_request_spec.rb +5 -4
  97. data/spec/lib/oauth/code_request_spec.rb +1 -1
  98. data/spec/lib/oauth/code_response_spec.rb +5 -1
  99. data/spec/lib/oauth/error_response_spec.rb +1 -1
  100. data/spec/lib/oauth/password_access_token_request_spec.rb +24 -13
  101. data/spec/lib/oauth/pre_authorization_spec.rb +13 -18
  102. data/spec/lib/oauth/refresh_token_request_spec.rb +19 -30
  103. data/spec/lib/oauth/token_request_spec.rb +14 -7
  104. data/spec/lib/option_spec.rb +51 -0
  105. data/spec/lib/stale_records_cleaner_spec.rb +18 -5
  106. data/spec/models/doorkeeper/access_grant_spec.rb +18 -4
  107. data/spec/models/doorkeeper/access_token_spec.rb +507 -479
  108. data/spec/models/doorkeeper/application_spec.rb +338 -300
  109. data/spec/requests/endpoints/token_spec.rb +5 -1
  110. data/spec/requests/flows/authorization_code_errors_spec.rb +4 -1
  111. data/spec/requests/flows/authorization_code_spec.rb +6 -1
  112. data/spec/requests/flows/client_credentials_spec.rb +41 -0
  113. data/spec/requests/flows/refresh_token_spec.rb +16 -8
  114. data/spec/requests/flows/revoke_token_spec.rb +143 -104
  115. data/spec/support/helpers/access_token_request_helper.rb +1 -0
  116. data/spec/support/helpers/authorization_request_helper.rb +4 -4
  117. data/spec/support/helpers/config_helper.rb +1 -1
  118. data/spec/support/shared/controllers_shared_context.rb +2 -2
  119. data/spec/support/shared/models_shared_examples.rb +6 -4
  120. metadata +15 -4
@@ -5,7 +5,11 @@ require "spec_helper"
5
5
  describe "Token endpoint" do
6
6
  before do
7
7
  client_exists
8
- authorization_code_exists application: @client, scopes: "public"
8
+ create_resource_owner
9
+ authorization_code_exists application: @client,
10
+ scopes: "public",
11
+ resource_owner_id: @resource_owner.id,
12
+ resource_owner_type: @resource_owner.class.name
9
13
  end
10
14
 
11
15
  it "respond with correct headers" do
@@ -50,7 +50,10 @@ end
50
50
  describe "Authorization Code Flow Errors", "after authorization" do
51
51
  before do
52
52
  client_exists
53
- authorization_code_exists application: @client
53
+ create_resource_owner
54
+ authorization_code_exists application: @client,
55
+ resource_owner_id: @resource_owner.id,
56
+ resource_owner_type: @resource_owner.class.name
54
57
  end
55
58
 
56
59
  it "returns :invalid_grant error when posting an already revoked grant code" do
@@ -182,6 +182,7 @@ feature "Authorization Code Flow" do
182
182
  access_token_exists application: @client,
183
183
  expires_in: -100, # even expired token
184
184
  resource_owner_id: @resource_owner.id,
185
+ resource_owner_type: @resource_owner.class.name,
185
186
  scopes: "public write"
186
187
 
187
188
  visit authorization_endpoint_url(client: @client, scope: "public write")
@@ -506,8 +507,12 @@ describe "Authorization Code Flow" do
506
507
  end
507
508
 
508
509
  context "issuing a refresh token" do
510
+ let(:resource_owner) { FactoryBot.create(:resource_owner) }
511
+
509
512
  before do
510
- authorization_code_exists application: @client
513
+ authorization_code_exists application: @client,
514
+ resource_owner_id: resource_owner.id,
515
+ resource_owner_type: resource_owner.class.name
511
516
  end
512
517
 
513
518
  it "second of simultaneous client requests get an error for revoked acccess token" do
@@ -159,6 +159,47 @@ describe "Client Credentials Request" do
159
159
  end
160
160
  end
161
161
 
162
+ context "when revoke_previous_client_credentials_token is true" do
163
+ before do
164
+ allow(Doorkeeper.config).to receive(:reuse_access_token) { false }
165
+ allow(Doorkeeper.config).to receive(:revoke_previous_client_credentials_token) { true }
166
+ end
167
+
168
+ it "revokes the previous token" do
169
+ headers = authorization client.uid, client.secret
170
+ params = { grant_type: "client_credentials" }
171
+
172
+ post "/oauth/token", params: params, headers: headers
173
+ should_have_json "access_token", Doorkeeper::AccessToken.first.token
174
+
175
+ token = Doorkeeper::AccessToken.first
176
+
177
+ post "/oauth/token", params: params, headers: headers
178
+ should_have_json "access_token", Doorkeeper::AccessToken.last.token
179
+
180
+ expect(token.reload.revoked?).to be_truthy
181
+ expect(Doorkeeper::AccessToken.last.revoked?).to be_falsey
182
+ end
183
+
184
+ context "with a simultaneous request" do
185
+ let!(:access_token) { FactoryBot.create :access_token, resource_owner_id: nil }
186
+
187
+ before do
188
+ allow(Doorkeeper.config.access_token_model).to receive(:matching_token_for) { access_token }
189
+ allow(access_token).to receive(:revoked?).and_return(true)
190
+ end
191
+
192
+ it "returns an error" do
193
+ headers = authorization client.uid, client.secret
194
+ params = { grant_type: "client_credentials" }
195
+
196
+ post "/oauth/token", params: params, headers: headers
197
+ should_not_have_json "access_token"
198
+ should_have_json "error", "invalid_token_reuse"
199
+ end
200
+ end
201
+ end
202
+
162
203
  def authorization(username, password)
163
204
  credentials = ActionController::HttpAuthentication::Basic.encode_credentials username, password
164
205
  { "HTTP_AUTHORIZATION" => credentials }
@@ -12,9 +12,13 @@ describe "Refresh Token Flow" do
12
12
  client_exists
13
13
  end
14
14
 
15
+ let(:resource_owner) { FactoryBot.create(:resource_owner) }
16
+
15
17
  context "issuing a refresh token" do
16
18
  before do
17
- authorization_code_exists application: @client
19
+ authorization_code_exists application: @client,
20
+ resource_owner_id: resource_owner.id,
21
+ resource_owner_type: resource_owner.class.name
18
22
  end
19
23
 
20
24
  it "client gets the refresh token and refreshes it" do
@@ -43,7 +47,8 @@ describe "Refresh Token Flow" do
43
47
  @token = FactoryBot.create(
44
48
  :access_token,
45
49
  application: @client,
46
- resource_owner_id: 1,
50
+ resource_owner_id: resource_owner.id,
51
+ resource_owner_type: resource_owner.class.name,
47
52
  use_refresh_token: true,
48
53
  )
49
54
  end
@@ -110,7 +115,8 @@ describe "Refresh Token Flow" do
110
115
  FactoryBot.create(
111
116
  :access_token,
112
117
  application: @client,
113
- resource_owner_id: 1,
118
+ resource_owner_id: resource_owner.id,
119
+ resource_owner_type: resource_owner.class.name,
114
120
  use_refresh_token: true,
115
121
  )
116
122
  end
@@ -119,7 +125,8 @@ describe "Refresh Token Flow" do
119
125
  FactoryBot.create(
120
126
  :access_token,
121
127
  application: public_client,
122
- resource_owner_id: 1,
128
+ resource_owner_id: resource_owner.id,
129
+ resource_owner_type: resource_owner.class.name,
123
130
  use_refresh_token: true,
124
131
  )
125
132
  end
@@ -185,14 +192,15 @@ describe "Refresh Token Flow" do
185
192
  end
186
193
  create_resource_owner
187
194
  _another_token = post password_token_endpoint_url(
188
- client: @client, resource_owner: @resource_owner,
195
+ client: @client, resource_owner: resource_owner,
189
196
  )
190
- last_token.update_attribute :created_at, 5.seconds.ago
197
+ last_token.update(created_at: 5.seconds.ago)
191
198
 
192
199
  @token = FactoryBot.create(
193
200
  :access_token,
194
201
  application: @client,
195
- resource_owner_id: @resource_owner.id,
202
+ resource_owner_id: resource_owner.id,
203
+ resource_owner_type: resource_owner.class.name,
196
204
  use_refresh_token: true,
197
205
  )
198
206
  @token.update_attribute :expires_in, -100
@@ -226,7 +234,7 @@ describe "Refresh Token Flow" do
226
234
 
227
235
  def last_token
228
236
  Doorkeeper::AccessToken.last_authorized_token_for(
229
- @client.id, @resource_owner.id,
237
+ @client.id, resource_owner,
230
238
  )
231
239
  end
232
240
  end
@@ -7,151 +7,190 @@ describe "Revoke Token Flow" do
7
7
  Doorkeeper.configure { orm DOORKEEPER_ORM }
8
8
  end
9
9
 
10
- context "with default parameters" do
11
- let(:client_application) { FactoryBot.create :application }
12
- let(:resource_owner) { User.create!(name: "John", password: "sekret") }
10
+ let(:private_client_application) { FactoryBot.create :application }
11
+ let(:public_client_application) { FactoryBot.create :application, confidential: false }
12
+ let(:resource_owner) { User.create!(name: "John", password: "sekret") }
13
+
14
+ context "with authenticated, confidential OAuth 2.0 client/application" do
13
15
  let(:access_token) do
14
16
  FactoryBot.create(
15
17
  :access_token,
16
- application: client_application,
18
+ application: private_client_application,
17
19
  resource_owner_id: resource_owner.id,
20
+ resource_owner_type: resource_owner.class.name,
18
21
  use_refresh_token: true,
19
22
  )
20
23
  end
21
24
 
22
- context "with authenticated, confidential OAuth 2.0 client/application" do
25
+ let(:headers) do
26
+ client_id = private_client_application.uid
27
+ client_secret = private_client_application.secret
28
+ credentials = Base64.encode64("#{client_id}:#{client_secret}")
29
+ { "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
30
+ end
31
+
32
+ it "should revoke the access token provided" do
33
+ post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
34
+
35
+ expect(response).to be_successful
36
+ expect(access_token.reload.revoked?).to be_truthy
37
+ end
38
+
39
+ it "should revoke the refresh token provided" do
40
+ post revocation_token_endpoint_url, params: { token: access_token.refresh_token }, headers: headers
41
+
42
+ expect(response).to be_successful
43
+ expect(access_token.reload.revoked?).to be_truthy
44
+ end
45
+
46
+ context "with invalid token to revoke" do
47
+ it "should not revoke any tokens and must respond with success" do
48
+ expect do
49
+ post revocation_token_endpoint_url,
50
+ params: { token: "I_AM_AN_INVALID_TOKEN" },
51
+ headers: headers
52
+ end.not_to(change { Doorkeeper::AccessToken.where(revoked_at: nil).count })
53
+
54
+ expect(response).to be_successful
55
+ end
56
+ end
57
+
58
+ context "with bad credentials and a valid token" do
23
59
  let(:headers) do
24
- client_id = client_application.uid
25
- client_secret = client_application.secret
26
- credentials = Base64.encode64("#{client_id}:#{client_secret}")
60
+ client_id = private_client_application.uid
61
+ credentials = Base64.encode64("#{client_id}:poop")
27
62
  { "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
28
63
  end
29
64
 
30
- it "should revoke the access token provided" do
65
+ it "should not revoke any tokens and respond with forbidden" do
31
66
  post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
32
67
 
33
- expect(response).to be_successful
34
- expect(access_token.reload.revoked?).to be_truthy
68
+ expect(response).to be_forbidden
69
+ expect(response.body).to include("unauthorized_client")
70
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
71
+ expect(access_token.reload.revoked?).to be_falsey
35
72
  end
73
+ end
36
74
 
37
- it "should revoke the refresh token provided" do
38
- post revocation_token_endpoint_url, params: { token: access_token.refresh_token }, headers: headers
75
+ context "with no credentials and a valid token" do
76
+ it "should not revoke any tokens and respond with forbidden" do
77
+ post revocation_token_endpoint_url, params: { token: access_token.token }
39
78
 
40
- expect(response).to be_successful
41
- expect(access_token.reload.revoked?).to be_truthy
79
+ expect(response).to be_forbidden
80
+ expect(response.body).to include("unauthorized_client")
81
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
82
+ expect(access_token.reload.revoked?).to be_falsey
42
83
  end
84
+ end
43
85
 
44
- context "with invalid token to revoke" do
45
- it "should not revoke any tokens and respond with forbidden" do
46
- expect do
47
- post revocation_token_endpoint_url,
48
- params: { token: "I_AM_AN_INVALID_TOKEN" },
49
- headers: headers
50
- end.not_to(change { Doorkeeper::AccessToken.where(revoked_at: nil).count })
51
-
52
- expect(response).to be_forbidden
53
- end
86
+ context "with valid token for another client application" do
87
+ let(:other_client_application) { FactoryBot.create :application }
88
+ let(:headers) do
89
+ client_id = other_client_application.uid
90
+ client_secret = other_client_application.secret
91
+ credentials = Base64.encode64("#{client_id}:#{client_secret}")
92
+ { "HTTP_AUTHORIZATION" => "Basic #{credentials}" }
54
93
  end
55
94
 
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 with forbidden" do
63
- post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
64
-
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"))
68
- expect(access_token.reload.revoked?).to be_falsey
69
- end
95
+ it "should not revoke the token as it's unauthorized" do
96
+ post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
97
+
98
+ expect(response).to be_forbidden
99
+ expect(response.body).to include("unauthorized_client")
100
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
101
+ expect(access_token.reload.revoked?).to be_falsey
70
102
  end
103
+ end
104
+ end
105
+
106
+ context "with authenticated public OAuth 2.0 client/application" do
107
+ let(:access_token) do
108
+ FactoryBot.create(
109
+ :access_token,
110
+ application: nil,
111
+ resource_owner_id: resource_owner.id,
112
+ resource_owner_type: resource_owner.class.name,
113
+ use_refresh_token: true,
114
+ )
115
+ end
71
116
 
72
- context "with no credentials and a valid token" do
73
- it "should not revoke any tokens and respond with forbidden" do
74
- post revocation_token_endpoint_url, params: { token: access_token.token }
117
+ it "should revoke the access token provided" do
118
+ post revocation_token_endpoint_url,
119
+ params: { client_id: public_client_application.uid, token: access_token.token },
120
+ headers: headers
75
121
 
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"))
79
- expect(access_token.reload.revoked?).to be_falsey
80
- end
81
- end
122
+ expect(response).to be_successful
123
+ expect(access_token.reload.revoked?).to be_truthy
124
+ end
82
125
 
83
- context "with valid token for another client application" do
84
- let(:other_client_application) { FactoryBot.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
-
92
- it "should not revoke the token as its unauthorized" do
93
- post revocation_token_endpoint_url, params: { token: access_token.token }, headers: headers
94
-
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"))
98
- expect(access_token.reload.revoked?).to be_falsey
99
- end
100
- end
126
+ it "should revoke the refresh token provided" do
127
+ post revocation_token_endpoint_url,
128
+ params: { client_id: public_client_application.uid, token: access_token.refresh_token },
129
+ headers: headers
130
+
131
+ expect(response).to be_successful
132
+ expect(access_token.reload.revoked?).to be_truthy
101
133
  end
102
134
 
103
- context "with public OAuth 2.0 client/application" do
135
+ it "should response with success even for invalid token" do
136
+ post revocation_token_endpoint_url,
137
+ params: { client_id: public_client_application.uid, token: "dont_exist" },
138
+ headers: headers
139
+
140
+ expect(response).to be_successful
141
+ end
142
+
143
+ context "with a valid token issued for a confidential client" do
104
144
  let(:access_token) do
105
145
  FactoryBot.create(
106
146
  :access_token,
107
- application: nil,
147
+ application: private_client_application,
108
148
  resource_owner_id: resource_owner.id,
149
+ resource_owner_type: resource_owner.class.name,
109
150
  use_refresh_token: true,
110
151
  )
111
152
  end
112
153
 
113
- it "should revoke the access token provided" do
114
- post revocation_token_endpoint_url, params: { token: access_token.token }
154
+ it "should not revoke the access token provided" do
155
+ post revocation_token_endpoint_url,
156
+ params: { client_id: public_client_application.uid, token: access_token.token }
115
157
 
116
- expect(response).to be_successful
117
- expect(access_token.reload.revoked?).to be_truthy
158
+ expect(response).to be_forbidden
159
+ expect(response.body).to include("unauthorized_client")
160
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
161
+ expect(access_token.reload.revoked?).to be_falsey
118
162
  end
119
163
 
120
- it "should revoke the refresh token provided" do
121
- post revocation_token_endpoint_url, params: { token: access_token.refresh_token }
164
+ it "should not revoke the refresh token provided" do
165
+ post revocation_token_endpoint_url,
166
+ params: { client_id: public_client_application.uid, token: access_token.token }
122
167
 
123
- expect(response).to be_successful
124
- expect(access_token.reload.revoked?).to be_truthy
168
+ expect(response).to be_forbidden
169
+ expect(response.body).to include("unauthorized_client")
170
+ expect(response.body).to include(I18n.t("doorkeeper.errors.messages.revoke.unauthorized"))
171
+ expect(access_token.reload.revoked?).to be_falsey
125
172
  end
173
+ end
174
+ end
126
175
 
127
- context "with a valid token issued for a confidential client" do
128
- let(:access_token) do
129
- FactoryBot.create(
130
- :access_token,
131
- application: client_application,
132
- resource_owner_id: resource_owner.id,
133
- use_refresh_token: true,
134
- )
135
- end
136
-
137
- it "should not revoke the access token provided" do
138
- post revocation_token_endpoint_url, params: { token: access_token.token }
139
-
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"))
143
- expect(access_token.reload.revoked?).to be_falsey
144
- end
145
-
146
- it "should not revoke the refresh token provided" do
147
- post revocation_token_endpoint_url, params: { token: access_token.token }
148
-
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"))
152
- expect(access_token.reload.revoked?).to be_falsey
153
- end
154
- end
176
+ context "without client authentication" do
177
+ let(:access_token) do
178
+ FactoryBot.create(
179
+ :access_token,
180
+ application: nil,
181
+ resource_owner_id: resource_owner.id,
182
+ resource_owner_type: resource_owner.class.name,
183
+ use_refresh_token: true,
184
+ )
185
+ end
186
+
187
+ it "shouldn't remove the token and must response with an error" do
188
+ post revocation_token_endpoint_url,
189
+ params: { token: access_token.token },
190
+ headers: headers
191
+
192
+ expect(response).not_to be_successful
193
+ expect(access_token.reload.revoked?).to be_falsey
155
194
  end
156
195
  end
157
196
  end
@@ -5,6 +5,7 @@ module AccessTokenRequestHelper
5
5
  attributes = {
6
6
  application: client,
7
7
  resource_owner_id: resource_owner.id,
8
+ resource_owner_type: resource_owner.class.name,
8
9
  }.merge(access_token_attributes)
9
10
  FactoryBot.create(:access_token, attributes)
10
11
  end
@@ -3,19 +3,19 @@
3
3
  module AuthorizationRequestHelper
4
4
  def resource_owner_is_authenticated(resource_owner = nil)
5
5
  resource_owner ||= User.create!(name: "Joe", password: "sekret")
6
- Doorkeeper.configuration.instance_variable_set(:@authenticate_resource_owner, proc { resource_owner })
6
+ Doorkeeper.config.instance_variable_set(:@authenticate_resource_owner, proc { resource_owner })
7
7
  end
8
8
 
9
9
  def resource_owner_is_not_authenticated
10
- Doorkeeper.configuration.instance_variable_set(:@authenticate_resource_owner, proc { redirect_to("/sign_in") })
10
+ Doorkeeper.config.instance_variable_set(:@authenticate_resource_owner, proc { redirect_to("/sign_in") })
11
11
  end
12
12
 
13
13
  def default_scopes_exist(*scopes)
14
- Doorkeeper.configuration.instance_variable_set(:@default_scopes, Doorkeeper::OAuth::Scopes.from_array(scopes))
14
+ Doorkeeper.config.instance_variable_set(:@default_scopes, Doorkeeper::OAuth::Scopes.from_array(scopes))
15
15
  end
16
16
 
17
17
  def optional_scopes_exist(*scopes)
18
- Doorkeeper.configuration.instance_variable_set(:@optional_scopes, Doorkeeper::OAuth::Scopes.from_array(scopes))
18
+ Doorkeeper.config.instance_variable_set(:@optional_scopes, Doorkeeper::OAuth::Scopes.from_array(scopes))
19
19
  end
20
20
 
21
21
  def client_should_be_authorized(client)
@@ -4,7 +4,7 @@ module ConfigHelper
4
4
  def config_is_set(setting, value = nil, &block)
5
5
  setting_ivar = "@#{setting}"
6
6
  value = block_given? ? block : value
7
- Doorkeeper.configuration.instance_variable_set(setting_ivar, value)
7
+ Doorkeeper.config.instance_variable_set(setting_ivar, value)
8
8
  end
9
9
  end
10
10
 
@@ -40,13 +40,13 @@ end
40
40
  shared_context "authenticated resource owner" do
41
41
  before do
42
42
  user = double(:resource, id: 1)
43
- allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { user } }
43
+ allow(Doorkeeper.config).to receive(:authenticate_resource_owner) { proc { user } }
44
44
  end
45
45
  end
46
46
 
47
47
  shared_context "not authenticated resource owner" do
48
48
  before do
49
- allow(Doorkeeper.configuration).to receive(:authenticate_resource_owner) { proc { redirect_to "/" } }
49
+ allow(Doorkeeper.config).to receive(:authenticate_resource_owner) { proc { redirect_to "/" } }
50
50
  end
51
51
  end
52
52
 
@@ -31,20 +31,22 @@ end
31
31
 
32
32
  shared_examples "a unique token" do
33
33
  describe :token do
34
+ let(:owner) { FactoryBot.create(:resource_owner) }
35
+
34
36
  it "is generated before validation" do
35
37
  expect { subject.valid? }.to change { subject.token }.from(nil)
36
38
  end
37
39
 
38
40
  it "is not valid if token exists" do
39
- token1 = FactoryBot.create factory_name
40
- token2 = FactoryBot.create factory_name
41
+ token1 = FactoryBot.create factory_name, resource_owner_id: owner.id, resource_owner_type: owner.class.name
42
+ token2 = FactoryBot.create factory_name, resource_owner_id: owner.id, resource_owner_type: owner.class.name
41
43
  token2.token = token1.token
42
44
  expect(token2).not_to be_valid
43
45
  end
44
46
 
45
47
  it "expects database to throw an error when tokens are the same" do
46
- token1 = FactoryBot.create factory_name
47
- token2 = FactoryBot.create factory_name
48
+ token1 = FactoryBot.create factory_name, resource_owner_id: owner.id, resource_owner_type: owner.class.name
49
+ token2 = FactoryBot.create factory_name, resource_owner_id: owner.id, resource_owner_type: owner.class.name
48
50
  token2.token = token1.token
49
51
  expect do
50
52
  token2.save!(validate: false)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doorkeeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.0
4
+ version: 5.4.0.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felipe Elias Philipp
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2020-01-29 00:00:00.000000000 Z
14
+ date: 2020-04-08 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: railties
@@ -221,6 +221,7 @@ files:
221
221
  - gemfiles/rails_master.gemfile
222
222
  - lib/doorkeeper.rb
223
223
  - lib/doorkeeper/config.rb
224
+ - lib/doorkeeper/config/abstract_builder.rb
224
225
  - lib/doorkeeper/config/option.rb
225
226
  - lib/doorkeeper/engine.rb
226
227
  - lib/doorkeeper/errors.rb
@@ -234,6 +235,7 @@ files:
234
235
  - lib/doorkeeper/models/concerns/expirable.rb
235
236
  - lib/doorkeeper/models/concerns/orderable.rb
236
237
  - lib/doorkeeper/models/concerns/ownership.rb
238
+ - lib/doorkeeper/models/concerns/resource_ownerable.rb
237
239
  - lib/doorkeeper/models/concerns/reusable.rb
238
240
  - lib/doorkeeper/models/concerns/revocable.rb
239
241
  - lib/doorkeeper/models/concerns/scopes.rb
@@ -260,6 +262,7 @@ files:
260
262
  - lib/doorkeeper/oauth/helpers/scope_checker.rb
261
263
  - lib/doorkeeper/oauth/helpers/unique_token.rb
262
264
  - lib/doorkeeper/oauth/helpers/uri_checker.rb
265
+ - lib/doorkeeper/oauth/hooks/context.rb
263
266
  - lib/doorkeeper/oauth/invalid_request_response.rb
264
267
  - lib/doorkeeper/oauth/invalid_token_response.rb
265
268
  - lib/doorkeeper/oauth/nonstandard.rb
@@ -282,8 +285,10 @@ files:
282
285
  - lib/doorkeeper/orm/active_record/stale_records_cleaner.rb
283
286
  - lib/doorkeeper/rails/helpers.rb
284
287
  - lib/doorkeeper/rails/routes.rb
288
+ - lib/doorkeeper/rails/routes/abstract_router.rb
285
289
  - lib/doorkeeper/rails/routes/mapper.rb
286
290
  - lib/doorkeeper/rails/routes/mapping.rb
291
+ - lib/doorkeeper/rails/routes/registry.rb
287
292
  - lib/doorkeeper/rake.rb
288
293
  - lib/doorkeeper/rake/db.rake
289
294
  - lib/doorkeeper/rake/setup.rake
@@ -305,6 +310,7 @@ files:
305
310
  - lib/doorkeeper/version.rb
306
311
  - lib/generators/doorkeeper/application_owner_generator.rb
307
312
  - lib/generators/doorkeeper/confidential_applications_generator.rb
313
+ - lib/generators/doorkeeper/enable_polymorphic_resource_owner_generator.rb
308
314
  - lib/generators/doorkeeper/install_generator.rb
309
315
  - lib/generators/doorkeeper/migration_generator.rb
310
316
  - lib/generators/doorkeeper/pkce_generator.rb
@@ -314,6 +320,7 @@ files:
314
320
  - lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb
315
321
  - lib/generators/doorkeeper/templates/add_previous_refresh_token_to_access_tokens.rb.erb
316
322
  - lib/generators/doorkeeper/templates/enable_pkce_migration.rb.erb
323
+ - lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb
317
324
  - lib/generators/doorkeeper/templates/initializer.rb
318
325
  - lib/generators/doorkeeper/templates/migration.rb.erb
319
326
  - lib/generators/doorkeeper/views_generator.rb
@@ -366,6 +373,7 @@ files:
366
373
  - spec/factories.rb
367
374
  - spec/generators/application_owner_generator_spec.rb
368
375
  - spec/generators/confidential_applications_generator_spec.rb
376
+ - spec/generators/enable_polymorphic_resource_owner_generator_spec.rb
369
377
  - spec/generators/install_generator_spec.rb
370
378
  - spec/generators/migration_generator_spec.rb
371
379
  - spec/generators/pkce_generator_spec.rb
@@ -409,6 +417,7 @@ files:
409
417
  - spec/lib/oauth/token_request_spec.rb
410
418
  - spec/lib/oauth/token_response_spec.rb
411
419
  - spec/lib/oauth/token_spec.rb
420
+ - spec/lib/option_spec.rb
412
421
  - spec/lib/request/strategy_spec.rb
413
422
  - spec/lib/secret_storing/base_spec.rb
414
423
  - spec/lib/secret_storing/bcrypt_spec.rb
@@ -474,9 +483,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
474
483
  version: '2.4'
475
484
  required_rubygems_version: !ruby/object:Gem::Requirement
476
485
  requirements:
477
- - - ">="
486
+ - - ">"
478
487
  - !ruby/object:Gem::Version
479
- version: '0'
488
+ version: 1.3.1
480
489
  requirements: []
481
490
  rubygems_version: 3.0.2
482
491
  signing_key:
@@ -532,6 +541,7 @@ test_files:
532
541
  - spec/factories.rb
533
542
  - spec/generators/application_owner_generator_spec.rb
534
543
  - spec/generators/confidential_applications_generator_spec.rb
544
+ - spec/generators/enable_polymorphic_resource_owner_generator_spec.rb
535
545
  - spec/generators/install_generator_spec.rb
536
546
  - spec/generators/migration_generator_spec.rb
537
547
  - spec/generators/pkce_generator_spec.rb
@@ -575,6 +585,7 @@ test_files:
575
585
  - spec/lib/oauth/token_request_spec.rb
576
586
  - spec/lib/oauth/token_response_spec.rb
577
587
  - spec/lib/oauth/token_spec.rb
588
+ - spec/lib/option_spec.rb
578
589
  - spec/lib/request/strategy_spec.rb
579
590
  - spec/lib/secret_storing/base_spec.rb
580
591
  - spec/lib/secret_storing/bcrypt_spec.rb