doorkeeper 5.2.0.rc1 → 5.2.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.
Potentially problematic release.
This version of doorkeeper might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/Appraisals +1 -1
- data/CHANGELOG.md +33 -2
- data/CONTRIBUTING.md +7 -0
- data/Dangerfile +1 -1
- data/Dockerfile +29 -0
- data/Gemfile +1 -1
- data/README.md +9 -1
- data/app/controllers/doorkeeper/application_controller.rb +1 -1
- data/app/controllers/doorkeeper/application_metal_controller.rb +2 -1
- data/app/controllers/doorkeeper/authorizations_controller.rb +14 -7
- data/app/controllers/doorkeeper/tokens_controller.rb +14 -1
- data/config/locales/en.yml +5 -1
- data/doorkeeper.gemspec +8 -0
- data/gemfiles/rails_6_0.gemfile +1 -1
- data/lib/doorkeeper/config.rb +64 -9
- data/lib/doorkeeper/errors.rb +13 -18
- data/lib/doorkeeper/helpers/controller.rb +6 -2
- data/lib/doorkeeper/models/access_token_mixin.rb +43 -2
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -5
- data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -9
- data/lib/doorkeeper/oauth/base_request.rb +2 -0
- data/lib/doorkeeper/oauth/client_credentials/creator.rb +14 -0
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +8 -0
- data/lib/doorkeeper/oauth/code_request.rb +5 -11
- data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +70 -37
- data/lib/doorkeeper/oauth/refresh_token_request.rb +5 -2
- data/lib/doorkeeper/oauth/token_introspection.rb +16 -7
- data/lib/doorkeeper/oauth/token_request.rb +4 -18
- data/lib/doorkeeper/orm/active_record/application.rb +1 -1
- data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
- data/lib/doorkeeper/orm/active_record.rb +2 -2
- data/lib/doorkeeper/request/authorization_code.rb +2 -0
- data/lib/doorkeeper/request.rb +6 -11
- data/lib/doorkeeper/server.rb +2 -6
- data/lib/doorkeeper/version.rb +1 -1
- data/lib/doorkeeper.rb +1 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +88 -43
- data/lib/generators/doorkeeper/templates/migration.rb.erb +1 -1
- data/spec/controllers/authorizations_controller_spec.rb +140 -61
- data/spec/controllers/protected_resources_controller_spec.rb +3 -3
- data/spec/controllers/tokens_controller_spec.rb +140 -40
- data/spec/dummy/config/initializers/doorkeeper.rb +47 -20
- data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +1 -1
- data/spec/lib/config_spec.rb +32 -1
- data/spec/lib/oauth/authorization_code_request_spec.rb +11 -1
- data/spec/lib/oauth/base_request_spec.rb +33 -16
- data/spec/lib/oauth/client_credentials/creator_spec.rb +3 -0
- data/spec/lib/oauth/code_request_spec.rb +27 -28
- data/spec/lib/oauth/invalid_request_response_spec.rb +75 -0
- data/spec/lib/oauth/pre_authorization_spec.rb +80 -55
- data/spec/lib/oauth/refresh_token_request_spec.rb +1 -0
- data/spec/lib/oauth/token_request_spec.rb +20 -17
- data/spec/lib/server_spec.rb +0 -12
- data/spec/requests/endpoints/authorization_spec.rb +21 -5
- data/spec/requests/endpoints/token_spec.rb +1 -1
- data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
- data/spec/requests/flows/authorization_code_spec.rb +77 -23
- data/spec/requests/flows/client_credentials_spec.rb +38 -0
- data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
- data/spec/requests/flows/implicit_grant_spec.rb +9 -8
- data/spec/requests/flows/password_spec.rb +37 -0
- data/spec/requests/flows/refresh_token_spec.rb +1 -1
- data/spec/support/helpers/request_spec_helper.rb +14 -2
- data/spec/validators/redirect_uri_validator_spec.rb +1 -1
- metadata +15 -6
- data/app/validators/redirect_uri_validator.rb +0 -60
@@ -3,31 +3,139 @@
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
5
|
describe Doorkeeper::TokensController do
|
6
|
-
|
7
|
-
|
6
|
+
let(:client) { FactoryBot.create :application }
|
7
|
+
let!(:user) { User.create!(name: "Joe", password: "sekret") }
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
before do
|
10
|
+
Doorkeeper.configure do
|
11
|
+
resource_owner_from_credentials do
|
12
|
+
User.first
|
13
|
+
end
|
14
|
+
end
|
11
15
|
|
12
|
-
|
16
|
+
allow(Doorkeeper.configuration).to receive(:grant_flows).and_return(["password"])
|
17
|
+
end
|
13
18
|
|
14
|
-
|
19
|
+
subject { JSON.parse(response.body) }
|
20
|
+
|
21
|
+
describe "POST #create" do
|
22
|
+
before do
|
23
|
+
post :create, params: {
|
24
|
+
client_id: client.uid,
|
25
|
+
client_secret: client.secret,
|
26
|
+
grant_type: "password",
|
27
|
+
}
|
28
|
+
end
|
29
|
+
|
30
|
+
it "responds after authorization" do
|
31
|
+
expect(response).to be_successful
|
32
|
+
end
|
33
|
+
|
34
|
+
it "includes access token in response" do
|
35
|
+
expect(subject["access_token"]).to eq(Doorkeeper::AccessToken.first.token)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "includes token type in response" do
|
39
|
+
expect(subject["token_type"]).to eq("Bearer")
|
40
|
+
end
|
41
|
+
|
42
|
+
it "includes token expiration in response" do
|
43
|
+
expect(subject["expires_in"].to_i).to eq(Doorkeeper.configuration.access_token_expires_in)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "issues the token for the current client" do
|
47
|
+
expect(Doorkeeper::AccessToken.first.application_id).to eq(client.id)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "issues the token for the current resource owner" do
|
51
|
+
expect(Doorkeeper::AccessToken.first.resource_owner_id).to eq(user.id)
|
15
52
|
end
|
16
53
|
end
|
17
54
|
|
18
|
-
describe "
|
19
|
-
|
20
|
-
|
21
|
-
|
55
|
+
describe "POST #create with errors" do
|
56
|
+
before do
|
57
|
+
post :create, params: {
|
58
|
+
client_id: client.uid,
|
59
|
+
client_secret: "invalid",
|
60
|
+
grant_type: "password",
|
61
|
+
}
|
62
|
+
end
|
22
63
|
|
23
|
-
|
64
|
+
it "responds after authorization" do
|
65
|
+
expect(response).to be_unauthorized
|
66
|
+
end
|
24
67
|
|
25
|
-
|
26
|
-
expect(
|
68
|
+
it "include error in response" do
|
69
|
+
expect(subject["error"]).to eq("invalid_client")
|
70
|
+
end
|
71
|
+
|
72
|
+
it "include error_description in response" do
|
73
|
+
expect(subject["error_description"]).to be
|
74
|
+
end
|
75
|
+
|
76
|
+
it "does not include access token in response" do
|
77
|
+
expect(subject["access_token"]).to be_nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it "does not include token type in response" do
|
81
|
+
expect(subject["token_type"]).to be_nil
|
82
|
+
end
|
83
|
+
|
84
|
+
it "does not include token expiration in response" do
|
85
|
+
expect(subject["expires_in"]).to be_nil
|
86
|
+
end
|
87
|
+
|
88
|
+
it "does not issue any access token" do
|
89
|
+
expect(Doorkeeper::AccessToken.all).to be_empty
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "POST #create with callbacks" do
|
94
|
+
after do
|
95
|
+
client.update_attribute :redirect_uri, "urn:ietf:wg:oauth:2.0:oob"
|
96
|
+
end
|
97
|
+
|
98
|
+
describe "when successful" do
|
99
|
+
after do
|
100
|
+
post :create, params: {
|
101
|
+
client_id: client.uid,
|
102
|
+
client_secret: client.secret,
|
103
|
+
grant_type: "password",
|
104
|
+
}
|
105
|
+
end
|
106
|
+
|
107
|
+
it "should call :before_successful_authorization callback" do
|
108
|
+
expect(Doorkeeper.configuration)
|
109
|
+
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
|
110
|
+
end
|
111
|
+
|
112
|
+
it "should call :after_successful_authorization callback" do
|
113
|
+
expect(Doorkeeper.configuration)
|
114
|
+
.to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "with errors" do
|
119
|
+
after do
|
120
|
+
post :create, params: {
|
121
|
+
client_id: client.uid,
|
122
|
+
client_secret: "invalid",
|
123
|
+
grant_type: "password",
|
124
|
+
}
|
125
|
+
end
|
126
|
+
|
127
|
+
it "should call :before_successful_authorization callback" do
|
128
|
+
expect(Doorkeeper.configuration)
|
129
|
+
.to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should not call :after_successful_authorization callback" do
|
133
|
+
expect(Doorkeeper.configuration).not_to receive(:after_successful_authorization)
|
134
|
+
end
|
27
135
|
end
|
28
136
|
end
|
29
137
|
|
30
|
-
describe "
|
138
|
+
describe "POST #create with custom error" do
|
31
139
|
it "returns the error response with a custom message" do
|
32
140
|
# I18n looks for `doorkeeper.errors.messages.custom_message` in locale files
|
33
141
|
custom_message = "my_message"
|
@@ -58,7 +166,7 @@ describe Doorkeeper::TokensController do
|
|
58
166
|
end
|
59
167
|
|
60
168
|
# http://tools.ietf.org/html/rfc7009#section-2.2
|
61
|
-
describe "
|
169
|
+
describe "POST #revoke" do
|
62
170
|
let(:client) { FactoryBot.create(:application) }
|
63
171
|
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
64
172
|
|
@@ -117,21 +225,7 @@ describe Doorkeeper::TokensController do
|
|
117
225
|
end
|
118
226
|
end
|
119
227
|
|
120
|
-
describe "
|
121
|
-
it "memoizes the result of the authorization" do
|
122
|
-
strategy = double(:strategy, authorize: true)
|
123
|
-
expect(strategy).to receive(:authorize).once
|
124
|
-
allow(controller).to receive(:strategy) { strategy }
|
125
|
-
allow(controller).to receive(:create) do
|
126
|
-
2.times { controller.send :authorize_response }
|
127
|
-
controller.render json: {}, status: :ok
|
128
|
-
end
|
129
|
-
|
130
|
-
post :create
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
describe "when requested token introspection" do
|
228
|
+
describe "POST #introspect" do
|
135
229
|
let(:client) { FactoryBot.create(:application) }
|
136
230
|
let(:access_token) { FactoryBot.create(:access_token, application: client) }
|
137
231
|
let(:token_for_introspection) { FactoryBot.create(:access_token, application: client) }
|
@@ -167,13 +261,15 @@ describe Doorkeeper::TokensController do
|
|
167
261
|
end
|
168
262
|
end
|
169
263
|
|
170
|
-
it "responds with
|
264
|
+
it "responds with invalid_token error" do
|
171
265
|
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
172
266
|
|
173
267
|
post :introspect, params: { token: token_for_introspection.token }
|
174
268
|
|
175
|
-
|
176
|
-
|
269
|
+
response_status_should_be 401
|
270
|
+
|
271
|
+
should_not_have_json "active"
|
272
|
+
should_have_json "error", "invalid_token"
|
177
273
|
end
|
178
274
|
end
|
179
275
|
|
@@ -268,15 +364,17 @@ describe Doorkeeper::TokensController do
|
|
268
364
|
expect(json_response).to include("client_id", "token_type", "exp", "iat")
|
269
365
|
end
|
270
366
|
|
271
|
-
it "responds with
|
367
|
+
it "responds with invalid_token error if authorized token doesn't have introspection scope" do
|
272
368
|
access_token.update(scopes: "read write")
|
273
369
|
|
274
370
|
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
275
371
|
|
276
372
|
post :introspect, params: { token: token_for_introspection.token }
|
277
373
|
|
278
|
-
|
279
|
-
|
374
|
+
response_status_should_be 401
|
375
|
+
|
376
|
+
should_not_have_json "active"
|
377
|
+
should_have_json "error", "invalid_token"
|
280
378
|
end
|
281
379
|
end
|
282
380
|
|
@@ -285,7 +383,7 @@ describe Doorkeeper::TokensController do
|
|
285
383
|
FactoryBot.create(:access_token, application: client, revoked_at: 1.day.ago)
|
286
384
|
end
|
287
385
|
|
288
|
-
it "responds with
|
386
|
+
it "responds with invalid_token error" do
|
289
387
|
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
290
388
|
|
291
389
|
post :introspect, params: { token: token_for_introspection.token }
|
@@ -340,13 +438,15 @@ describe Doorkeeper::TokensController do
|
|
340
438
|
end
|
341
439
|
|
342
440
|
context "authorized using valid Bearer token" do
|
343
|
-
it "responds with
|
441
|
+
it "responds with invalid_token error" do
|
344
442
|
request.headers["Authorization"] = "Bearer #{access_token.token}"
|
345
443
|
|
346
444
|
post :introspect, params: { token: SecureRandom.hex(16) }
|
347
445
|
|
348
|
-
|
349
|
-
|
446
|
+
response_status_should_be 401
|
447
|
+
|
448
|
+
should_not_have_json "active"
|
449
|
+
should_have_json "error", "invalid_token"
|
350
450
|
end
|
351
451
|
end
|
352
452
|
end
|
@@ -107,32 +107,59 @@ Doorkeeper.configure do
|
|
107
107
|
# client.superapp? or resource_owner.admin?
|
108
108
|
# end
|
109
109
|
|
110
|
-
#
|
111
|
-
#
|
112
|
-
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
#
|
116
|
-
#
|
117
|
-
#
|
118
|
-
#
|
119
|
-
#
|
120
|
-
#
|
121
|
-
#
|
122
|
-
#
|
110
|
+
# Configure custom constraints for the Token Introspection request.
|
111
|
+
# By default this configuration option allows to introspect a token by another
|
112
|
+
# token of the same application, OR to introspect the token that belongs to
|
113
|
+
# authorized client (from authenticated client) OR when token doesn't
|
114
|
+
# belong to any client (public token). Otherwise requester has no access to the
|
115
|
+
# introspection and it will return response as stated in the RFC.
|
116
|
+
#
|
117
|
+
# Block arguments:
|
118
|
+
#
|
119
|
+
# @param token [Doorkeeper::AccessToken]
|
120
|
+
# token to be introspected
|
121
|
+
#
|
122
|
+
# @param authorized_client [Doorkeeper::Application]
|
123
|
+
# authorized client (if request is authorized using Basic auth with
|
124
|
+
# Client Credentials for example)
|
125
|
+
#
|
126
|
+
# @param authorized_token [Doorkeeper::AccessToken]
|
127
|
+
# Bearer token used to authorize the request
|
123
128
|
#
|
124
|
-
#
|
125
|
-
#
|
126
|
-
#
|
127
|
-
#
|
129
|
+
# In case the block returns `nil` or `false` introspection responses with 401 status code
|
130
|
+
# when using authorized token to introspect, or you'll get 200 with { "active": false } body
|
131
|
+
# when using authorized client to introspect as stated in the
|
132
|
+
# RFC 7662 section 2.2. Introspection Response.
|
128
133
|
#
|
129
|
-
#
|
130
|
-
#
|
131
|
-
#
|
134
|
+
# Using with caution:
|
135
|
+
# Keep in mind that these three parameters pass to block can be nil as following case:
|
136
|
+
# `authorized_client` is nil if and only if `authorized_token` is present, and vice versa.
|
137
|
+
# `token` will be nil if and only if `authorized_token` is present.
|
138
|
+
# So remember to use `&` or check if it is present before calling method on
|
139
|
+
# them to make sure you doesn't get NoMethodError exception.
|
140
|
+
#
|
141
|
+
# You can define your custom check:
|
142
|
+
#
|
143
|
+
# allow_token_introspection do |token, authorized_client, authorized_token|
|
144
|
+
# if authorized_token
|
145
|
+
# # customize: require `introspection` scope
|
146
|
+
# authorized_token.application == token&.application ||
|
147
|
+
# authorized_token.scopes.include?("introspection")
|
148
|
+
# elsif token.application
|
149
|
+
# # `protected_resource` is a new database boolean column, for example
|
150
|
+
# authorized_client == token.application || authorized_client.protected_resource?
|
132
151
|
# else
|
152
|
+
# # public token (when token.application is nil, token doesn't belong to any application)
|
133
153
|
# true
|
134
154
|
# end
|
135
155
|
# end
|
156
|
+
#
|
157
|
+
# Or you can completely disable any token introspection:
|
158
|
+
#
|
159
|
+
# allow_token_introspection false
|
160
|
+
#
|
161
|
+
# If you need to block the request at all, then configure your routes.rb or web-server
|
162
|
+
# like nginx to forbid the request.
|
136
163
|
|
137
164
|
# WWW-Authenticate Realm (default "Doorkeeper").
|
138
165
|
realm "Doorkeeper"
|
@@ -25,7 +25,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
|
|
25
25
|
t.text :redirect_uri, null: false
|
26
26
|
t.datetime :created_at, null: false
|
27
27
|
t.datetime :revoked_at
|
28
|
-
t.string :scopes
|
28
|
+
t.string :scopes, null: false, default: ""
|
29
29
|
end
|
30
30
|
|
31
31
|
add_index :oauth_access_grants, :token, unique: true
|
data/spec/lib/config_spec.rb
CHANGED
@@ -502,7 +502,21 @@ describe Doorkeeper, "configuration" do
|
|
502
502
|
|
503
503
|
describe "base_controller" do
|
504
504
|
context "default" do
|
505
|
-
it { expect(Doorkeeper.configuration.base_controller).to
|
505
|
+
it { expect(Doorkeeper.configuration.base_controller).to be_an_instance_of(Proc) }
|
506
|
+
|
507
|
+
it "resolves to a ApplicationController::Base in default mode" do
|
508
|
+
expect(Doorkeeper.configuration.resolve_controller(:base))
|
509
|
+
.to eq(ActionController::Base)
|
510
|
+
end
|
511
|
+
|
512
|
+
it "resolves to a ApplicationController::API in api_only mode" do
|
513
|
+
Doorkeeper.configure do
|
514
|
+
api_only
|
515
|
+
end
|
516
|
+
|
517
|
+
expect(Doorkeeper.configuration.resolve_controller(:base))
|
518
|
+
.to eq(ActionController::API)
|
519
|
+
end
|
506
520
|
end
|
507
521
|
|
508
522
|
context "custom" do
|
@@ -517,6 +531,23 @@ describe Doorkeeper, "configuration" do
|
|
517
531
|
end
|
518
532
|
end
|
519
533
|
|
534
|
+
describe "base_metal_controller" do
|
535
|
+
context "default" do
|
536
|
+
it { expect(Doorkeeper.configuration.base_metal_controller).to eq("ActionController::API") }
|
537
|
+
end
|
538
|
+
|
539
|
+
context "custom" do
|
540
|
+
before do
|
541
|
+
Doorkeeper.configure do
|
542
|
+
orm DOORKEEPER_ORM
|
543
|
+
base_metal_controller { "ApplicationController" }
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
it { expect(Doorkeeper.configuration.resolve_controller(:base_metal)).to eq(ApplicationController) }
|
548
|
+
end
|
549
|
+
end
|
550
|
+
|
520
551
|
if DOORKEEPER_ORM == :active_record
|
521
552
|
describe "active_record_options" do
|
522
553
|
let(:models) { [Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::Application] }
|
@@ -23,7 +23,7 @@ module Doorkeeper::OAuth
|
|
23
23
|
end
|
24
24
|
|
25
25
|
subject do
|
26
|
-
AuthorizationCodeRequest.new
|
26
|
+
AuthorizationCodeRequest.new(server, grant, client, params)
|
27
27
|
end
|
28
28
|
|
29
29
|
it "issues a new token for the client" do
|
@@ -65,6 +65,16 @@ module Doorkeeper::OAuth
|
|
65
65
|
subject.redirect_uri = nil
|
66
66
|
subject.validate
|
67
67
|
expect(subject.error).to eq(:invalid_request)
|
68
|
+
expect(subject.missing_param).to eq(:redirect_uri)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "invalid code_verifier param because server does not support pkce" do
|
72
|
+
allow_any_instance_of(Doorkeeper::AccessGrant).to receive(:respond_to?).with(:code_challenge).and_return(false)
|
73
|
+
|
74
|
+
subject.code_verifier = "a45a9fea-0676-477e-95b1-a40f72ac3cfb"
|
75
|
+
subject.validate
|
76
|
+
expect(subject.error).to eq(:invalid_request)
|
77
|
+
expect(subject.invalid_request_reason).to eq(:not_support_pkce)
|
68
78
|
end
|
69
79
|
|
70
80
|
it "matches the redirect_uri with grant's one" do
|
@@ -66,27 +66,44 @@ module Doorkeeper::OAuth
|
|
66
66
|
end
|
67
67
|
|
68
68
|
context "invalid" do
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
context "with error other than invalid_request" do
|
70
|
+
before do
|
71
|
+
allow(subject).to receive(:valid?).and_return(false)
|
72
|
+
allow(subject).to receive(:error).and_return(:server_error)
|
73
|
+
allow(subject).to receive(:state).and_return("hello")
|
74
|
+
end
|
75
|
+
|
76
|
+
it "returns an ErrorResponse object" do
|
77
|
+
result = subject.authorize
|
78
|
+
|
79
|
+
expect(result).to be_an_instance_of(ErrorResponse)
|
80
|
+
|
81
|
+
expect(result.body).to eq(
|
82
|
+
error: :server_error,
|
83
|
+
error_description: translated_error_message(:server_error),
|
84
|
+
state: "hello"
|
85
|
+
)
|
86
|
+
end
|
73
87
|
end
|
74
88
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
89
|
+
context "with invalid_request error" do
|
90
|
+
before do
|
91
|
+
allow(subject).to receive(:valid?).and_return(false)
|
92
|
+
allow(subject).to receive(:error).and_return(:invalid_request)
|
93
|
+
allow(subject).to receive(:state).and_return("hello")
|
94
|
+
end
|
80
95
|
|
81
|
-
|
96
|
+
it "returns an InvalidRequestResponse object" do
|
97
|
+
result = subject.authorize
|
82
98
|
|
83
|
-
|
99
|
+
expect(result).to be_an_instance_of(InvalidRequestResponse)
|
84
100
|
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
101
|
+
expect(result.body).to eq(
|
102
|
+
error: :invalid_request,
|
103
|
+
error_description: translated_invalid_request_error_message(:unknown, :unknown),
|
104
|
+
state: "hello"
|
105
|
+
)
|
106
|
+
end
|
90
107
|
end
|
91
108
|
end
|
92
109
|
end
|
@@ -55,6 +55,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
55
55
|
|
56
56
|
expect(Doorkeeper::AccessToken.count).to eq(2)
|
57
57
|
expect(result).not_to eq(existing_token)
|
58
|
+
expect(existing_token.reload).to be_revoked
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
@@ -69,6 +70,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
69
70
|
|
70
71
|
expect(Doorkeeper::AccessToken.count).to eq(2)
|
71
72
|
expect(result).not_to eq(existing_token)
|
73
|
+
expect(existing_token.reload).to be_revoked
|
72
74
|
end
|
73
75
|
end
|
74
76
|
end
|
@@ -82,6 +84,7 @@ class Doorkeeper::OAuth::ClientCredentialsRequest
|
|
82
84
|
|
83
85
|
expect(Doorkeeper::AccessToken.count).to eq(2)
|
84
86
|
expect(result).not_to eq(existing_token)
|
87
|
+
expect(existing_token.reload).to be_revoked
|
85
88
|
end
|
86
89
|
end
|
87
90
|
|
@@ -4,18 +4,23 @@ require "spec_helper"
|
|
4
4
|
|
5
5
|
module Doorkeeper::OAuth
|
6
6
|
describe CodeRequest do
|
7
|
-
let
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
7
|
+
let :pre_auth do
|
8
|
+
server = Doorkeeper.configuration
|
9
|
+
allow(server).to receive(:default_scopes).and_return(Scopes.from_string("public"))
|
10
|
+
allow(server).to receive(:grant_flows).and_return(Scopes.from_string("authorization_code"))
|
11
|
+
|
12
|
+
application = FactoryBot.create(:application, scopes: "public")
|
13
|
+
client = Doorkeeper::OAuth::Client.new(application)
|
14
|
+
|
15
|
+
attributes = {
|
16
|
+
client_id: client.uid,
|
17
|
+
response_type: "code",
|
18
|
+
redirect_uri: "https://app.com/callback",
|
19
|
+
}
|
20
|
+
|
21
|
+
pre_auth = PreAuthorization.new(server, attributes)
|
22
|
+
pre_auth.authorizable?
|
23
|
+
pre_auth
|
19
24
|
end
|
20
25
|
|
21
26
|
let(:owner) { double :owner, id: 8900 }
|
@@ -24,24 +29,18 @@ module Doorkeeper::OAuth
|
|
24
29
|
CodeRequest.new(pre_auth, owner)
|
25
30
|
end
|
26
31
|
|
27
|
-
|
28
|
-
|
29
|
-
subject.authorize
|
30
|
-
|
32
|
+
context "when pre_auth is authorized" do
|
33
|
+
it "creates an access grant and returns a code response" do
|
34
|
+
expect { subject.authorize }.to change { Doorkeeper::AccessGrant.count }.by(1)
|
35
|
+
expect(subject.authorize).to be_a(CodeResponse)
|
36
|
+
end
|
31
37
|
end
|
32
38
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
allow(pre_auth).to receive(:authorizable?).and_return(false)
|
39
|
-
expect { subject.authorize }.not_to(change { Doorkeeper::AccessGrant.count })
|
40
|
-
end
|
41
|
-
|
42
|
-
it "returns a error response" do
|
43
|
-
allow(pre_auth).to receive(:authorizable?).and_return(false)
|
44
|
-
expect(subject.authorize).to be_a(ErrorResponse)
|
39
|
+
context "when pre_auth is denied" do
|
40
|
+
it "does not create access grant and returns a error response" do
|
41
|
+
expect { subject.deny }.not_to(change { Doorkeeper::AccessGrant.count })
|
42
|
+
expect(subject.deny).to be_a(ErrorResponse)
|
43
|
+
end
|
45
44
|
end
|
46
45
|
end
|
47
46
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
|
5
|
+
module Doorkeeper::OAuth
|
6
|
+
describe InvalidRequestResponse do
|
7
|
+
describe "#name" do
|
8
|
+
it { expect(subject.name).to eq(:invalid_request) }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "#status" do
|
12
|
+
it { expect(subject.status).to eq(:bad_request) }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe :from_request do
|
16
|
+
let(:response) { InvalidRequestResponse.from_request(request) }
|
17
|
+
|
18
|
+
context "missing param" do
|
19
|
+
let(:request) { double(missing_param: "some_param") }
|
20
|
+
|
21
|
+
it "sets a description" do
|
22
|
+
expect(response.description).to eq(
|
23
|
+
I18n.t(:missing_param, scope: %i[doorkeeper errors messages invalid_request], value: "some_param")
|
24
|
+
)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "sets the reason" do
|
28
|
+
expect(response.reason).to eq(:missing_param)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "server doesn not support_pkce" do
|
33
|
+
let(:request) { double(invalid_request_reason: :not_support_pkce) }
|
34
|
+
|
35
|
+
it "sets a description" do
|
36
|
+
expect(response.description).to eq(
|
37
|
+
I18n.t(:not_support_pkce, scope: %i[doorkeeper errors messages invalid_request])
|
38
|
+
)
|
39
|
+
end
|
40
|
+
|
41
|
+
it "sets the reason" do
|
42
|
+
expect(response.reason).to eq(:not_support_pkce)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context "request is not authorized" do
|
47
|
+
let(:request) { double(invalid_request_reason: :request_not_authorized) }
|
48
|
+
|
49
|
+
it "sets a description" do
|
50
|
+
expect(response.description).to eq(
|
51
|
+
I18n.t(:request_not_authorized, scope: %i[doorkeeper errors messages invalid_request])
|
52
|
+
)
|
53
|
+
end
|
54
|
+
|
55
|
+
it "sets the reason" do
|
56
|
+
expect(response.reason).to eq(:request_not_authorized)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "unknown reason" do
|
61
|
+
let(:request) { double(invalid_request_reason: :unknown_reason) }
|
62
|
+
|
63
|
+
it "sets a description" do
|
64
|
+
expect(response.description).to eq(
|
65
|
+
I18n.t(:unknown, scope: %i[doorkeeper errors messages invalid_request])
|
66
|
+
)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "unknown reason" do
|
70
|
+
expect(response.reason).to eq(:unknown_reason)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|