doorkeeper 5.3.3 → 5.4.0.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of doorkeeper might be problematic. Click here for more details.

Files changed (120) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +0 -14
  3. data/CHANGELOG.md +35 -10
  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 +7 -7
  9. data/app/controllers/doorkeeper/authorizations_controller.rb +31 -12
  10. data/app/controllers/doorkeeper/authorized_applications_controller.rb +3 -3
  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.rb +106 -79
  22. data/lib/doorkeeper/config.rb +40 -17
  23. data/lib/doorkeeper/config/abstract_builder.rb +28 -0
  24. data/lib/doorkeeper/config/option.rb +28 -14
  25. data/lib/doorkeeper/grape/helpers.rb +1 -1
  26. data/lib/doorkeeper/models/access_grant_mixin.rb +9 -11
  27. data/lib/doorkeeper/models/access_token_mixin.rb +100 -41
  28. data/lib/doorkeeper/models/concerns/resource_ownerable.rb +47 -0
  29. data/lib/doorkeeper/models/concerns/revocable.rb +1 -1
  30. data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
  31. data/lib/doorkeeper/models/concerns/secret_storable.rb +1 -3
  32. data/lib/doorkeeper/oauth/authorization/code.rb +14 -5
  33. data/lib/doorkeeper/oauth/authorization/context.rb +2 -2
  34. data/lib/doorkeeper/oauth/authorization/token.rb +7 -11
  35. data/lib/doorkeeper/oauth/authorization/uri_builder.rb +4 -4
  36. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -8
  37. data/lib/doorkeeper/oauth/base_request.rb +11 -19
  38. data/lib/doorkeeper/oauth/client.rb +1 -1
  39. data/lib/doorkeeper/oauth/client/credentials.rb +2 -4
  40. data/lib/doorkeeper/oauth/client_credentials/creator.rb +25 -7
  41. data/lib/doorkeeper/oauth/client_credentials/issuer.rb +3 -2
  42. data/lib/doorkeeper/oauth/client_credentials/validator.rb +1 -1
  43. data/lib/doorkeeper/oauth/client_credentials_request.rb +8 -7
  44. data/lib/doorkeeper/oauth/code_request.rb +1 -1
  45. data/lib/doorkeeper/oauth/code_response.rb +6 -2
  46. data/lib/doorkeeper/oauth/error_response.rb +2 -4
  47. data/lib/doorkeeper/oauth/helpers/scope_checker.rb +1 -5
  48. data/lib/doorkeeper/oauth/hooks/context.rb +21 -0
  49. data/lib/doorkeeper/oauth/invalid_token_response.rb +2 -2
  50. data/lib/doorkeeper/oauth/password_access_token_request.rb +3 -5
  51. data/lib/doorkeeper/oauth/pre_authorization.rb +32 -27
  52. data/lib/doorkeeper/oauth/refresh_token_request.rb +18 -22
  53. data/lib/doorkeeper/oauth/token.rb +1 -1
  54. data/lib/doorkeeper/oauth/token_introspection.rb +3 -3
  55. data/lib/doorkeeper/oauth/token_request.rb +2 -2
  56. data/lib/doorkeeper/oauth/token_response.rb +1 -1
  57. data/lib/doorkeeper/orm/active_record/mixins/access_grant.rb +7 -2
  58. data/lib/doorkeeper/orm/active_record/mixins/access_token.rb +6 -2
  59. data/lib/doorkeeper/orm/active_record/mixins/application.rb +9 -64
  60. data/lib/doorkeeper/rails/routes.rb +13 -17
  61. data/lib/doorkeeper/rails/routes/abstract_router.rb +35 -0
  62. data/lib/doorkeeper/rails/routes/mapper.rb +2 -2
  63. data/lib/doorkeeper/rails/routes/registry.rb +45 -0
  64. data/lib/doorkeeper/request/strategy.rb +2 -2
  65. data/lib/doorkeeper/server.rb +3 -3
  66. data/lib/doorkeeper/version.rb +3 -3
  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 +39 -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 +15 -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 +22 -62
  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 +16 -5
@@ -106,12 +106,13 @@ describe Doorkeeper::TokensController do
106
106
 
107
107
  it "should call :before_successful_authorization callback" do
108
108
  expect(Doorkeeper.configuration)
109
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
109
+ .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
110
110
  end
111
111
 
112
112
  it "should call :after_successful_authorization callback" do
113
113
  expect(Doorkeeper.configuration)
114
- .to receive_message_chain(:after_successful_authorization, :call).with(instance_of(described_class))
114
+ .to receive_message_chain(:after_successful_authorization, :call)
115
+ .with(instance_of(described_class), instance_of(Doorkeeper::OAuth::Hooks::Context))
115
116
  end
116
117
  end
117
118
 
@@ -126,7 +127,7 @@ describe Doorkeeper::TokensController do
126
127
 
127
128
  it "should call :before_successful_authorization callback" do
128
129
  expect(Doorkeeper.configuration)
129
- .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class))
130
+ .to receive_message_chain(:before_successful_authorization, :call).with(instance_of(described_class), nil)
130
131
  end
131
132
 
132
133
  it "should not call :after_successful_authorization callback" do
@@ -174,13 +175,13 @@ describe Doorkeeper::TokensController do
174
175
  let(:client) { FactoryBot.create(:application, confidential: false) }
175
176
 
176
177
  it "returns 200" do
177
- post :revoke, params: { token: access_token.token }
178
+ post :revoke, params: { client_id: client.uid, token: access_token.token }
178
179
 
179
180
  expect(response.status).to eq 200
180
181
  end
181
182
 
182
183
  it "revokes the access token" do
183
- post :revoke, params: { token: access_token.token }
184
+ post :revoke, params: { client_id: client.uid, token: access_token.token }
184
185
 
185
186
  expect(access_token.reload).to have_attributes(revoked?: true)
186
187
  end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module ApplicationHelper
4
4
  def current_user
5
- @current_user ||= User.find_by_id(session[:user_id])
5
+ @current_user ||= User.find_by(id: session[:user_id])
6
6
  end
7
7
  end
@@ -1,6 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- class User < ActiveRecord::Base
3
+ class ApplicationRecord < ::ActiveRecord::Base
4
+ self.abstract_class = true
5
+ end
6
+
7
+ class User < ApplicationRecord
4
8
  def self.authenticate!(name, password)
5
9
  User.where(name: name, password: password).first
6
10
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path('boot', __dir__)
1
+ require File.expand_path("boot", __dir__)
2
2
 
3
3
  require "rails"
4
4
 
@@ -17,7 +17,7 @@ end
17
17
 
18
18
  Bundler.require(*Rails.groups)
19
19
 
20
- require 'yaml'
20
+ require "yaml"
21
21
 
22
22
  orm = if DOORKEEPER_ORM =~ /mongoid/
23
23
  Mongoid.load!(File.join(File.dirname(File.expand_path(__FILE__)), "#{DOORKEEPER_ORM}.yml"))
@@ -29,13 +29,15 @@ require "#{orm}/railtie"
29
29
 
30
30
  module Dummy
31
31
  class Application < Rails::Application
32
- if Rails.gem_version < Gem::Version.new('5.1')
32
+ if Rails.gem_version < Gem::Version.new("5.1")
33
33
  config.action_controller.per_form_csrf_tokens = true
34
34
  config.action_controller.forgery_protection_origin_check = true
35
35
 
36
36
  ActiveSupport.to_time_preserves_timezone = true
37
37
 
38
- config.active_record.belongs_to_required_by_default = true
38
+ if DOORKEEPER_ORM =~ /active_record/
39
+ config.active_record.belongs_to_required_by_default = true
40
+ end
39
41
 
40
42
  config.ssl_options = { hsts: { subdomains: true } }
41
43
  else
@@ -1,7 +1,7 @@
1
- require 'rubygems'
2
- require 'bundler/setup'
1
+ require "rubygems"
2
+ require "bundler/setup"
3
3
 
4
- orm = ENV['BUNDLE_GEMFILE'].match(/Gemfile\.(.+)\.rb/)
4
+ orm = ENV["BUNDLE_GEMFILE"].match(/Gemfile\.(.+)\.rb/)
5
5
  DOORKEEPER_ORM = (orm && orm[1]) || :active_record unless defined?(DOORKEEPER_ORM)
6
6
 
7
- $LOAD_PATH.unshift File.expand_path('../../../lib', __dir__)
7
+ $LOAD_PATH.unshift File.expand_path("../../../lib", __dir__)
@@ -1,5 +1,5 @@
1
1
  # Load the rails application
2
- require File.expand_path('application', __dir__)
2
+ require File.expand_path("application", __dir__)
3
3
 
4
4
  # Initialize the rails application
5
5
  Rails.application.initialize!
@@ -4,10 +4,10 @@ Rails.application.routes.draw do
4
4
  resources :semi_protected_resources
5
5
  resources :full_protected_resources
6
6
 
7
- get 'metal.json' => 'metal#index'
7
+ get "metal.json" => "metal#index"
8
8
 
9
- get '/callback', to: 'home#callback'
10
- get '/sign_in', to: 'home#sign_in'
9
+ get "/callback", to: "home#callback"
10
+ get "/sign_in", to: "home#sign_in"
11
11
 
12
- root to: 'home#index'
12
+ root to: "home#index"
13
13
  end
@@ -18,7 +18,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
18
18
  add_index :oauth_applications, :uid, unique: true
19
19
 
20
20
  create_table :oauth_access_grants do |t|
21
- t.references :resource_owner, null: false
21
+ t.references :resource_owner, null: false, polymorphic: true
22
22
  t.references :application, null: false
23
23
  t.string :token, null: false
24
24
  t.integer :expires_in, null: false
@@ -36,7 +36,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration[4.2]
36
36
  )
37
37
 
38
38
  create_table :oauth_access_tokens do |t|
39
- t.references :resource_owner, index: true
39
+ t.references :resource_owner, index: true, polymorphic: true
40
40
  t.references :application, null: false
41
41
 
42
42
  # If you use a custom token generator you may need to change this column
@@ -14,6 +14,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
14
14
 
15
15
  create_table "oauth_access_grants", force: :cascade do |t|
16
16
  t.integer "resource_owner_id", null: false
17
+ t.string "resource_owner_type" # [NOTE] null: false skipped to allow test pass
17
18
  t.integer "application_id", null: false
18
19
  t.string "token", null: false
19
20
  t.integer "expires_in", null: false
@@ -21,7 +22,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
21
22
  t.datetime "created_at", null: false
22
23
  t.datetime "revoked_at"
23
24
  t.string "scopes"
24
- unless ENV['WITHOUT_PKCE']
25
+ unless ENV["WITHOUT_PKCE"]
25
26
  t.string "code_challenge"
26
27
  t.string "code_challenge_method"
27
28
  end
@@ -30,6 +31,7 @@ ActiveRecord::Schema.define(version: 20180210183654) do
30
31
 
31
32
  create_table "oauth_access_tokens", force: :cascade do |t|
32
33
  t.integer "resource_owner_id"
34
+ t.string "resource_owner_type"
33
35
  t.integer "application_id"
34
36
  t.string "token", null: false
35
37
  t.string "refresh_token"
@@ -26,5 +26,5 @@ FactoryBot.define do
26
26
 
27
27
  # do not name this factory :user, otherwise it will conflict with factories
28
28
  # from applications that use doorkeeper factories in their own tests
29
- factory :doorkeeper_testing_user, class: :user
29
+ factory :doorkeeper_testing_user, class: :user, aliases: [:resource_owner]
30
30
  end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+ require "generators/doorkeeper/enable_polymorphic_resource_owner_generator"
5
+
6
+ describe "Doorkeeper::EnablePolymorphicResourceOwnerGenerator" do
7
+ include GeneratorSpec::TestCase
8
+
9
+ tests Doorkeeper::EnablePolymorphicResourceOwnerGenerator
10
+ destination ::File.expand_path("../tmp/dummy", __FILE__)
11
+
12
+ describe "after running the generator" do
13
+ before :each do
14
+ prepare_destination
15
+ FileUtils.mkdir_p(::File.expand_path("config/initializers", Pathname(destination_root)))
16
+ FileUtils.copy_file(
17
+ ::File.expand_path("../../lib/generators/doorkeeper/templates/initializer.rb", __dir__),
18
+ ::File.expand_path("config/initializers/doorkeeper.rb", Pathname.new(destination_root)),
19
+ )
20
+ end
21
+
22
+ it "creates a migration with a version specifier and changes the initializer" do
23
+ stub_const("ActiveRecord::VERSION::MAJOR", 5)
24
+ stub_const("ActiveRecord::VERSION::MINOR", 0)
25
+
26
+ run_generator
27
+
28
+ assert_migration "db/migrate/enable_polymorphic_resource_owner.rb" do |migration|
29
+ assert migration.include?("ActiveRecord::Migration[5.0]\n")
30
+ end
31
+
32
+ # generator_spec gem requires such block definition :(
33
+ #
34
+ # rubocop:disable Style/BlockDelimiters
35
+ expect(destination_root).to(have_structure {
36
+ directory "config" do
37
+ directory "initializers" do
38
+ file "doorkeeper.rb" do
39
+ contains " use_polymorphic_resource_owner"
40
+ end
41
+ end
42
+ end
43
+ })
44
+ # rubocop:enable Style/BlockDelimiters
45
+ end
46
+ end
47
+ end
@@ -3,7 +3,7 @@
3
3
  require "spec_helper"
4
4
 
5
5
  describe Doorkeeper, "configuration" do
6
- subject { Doorkeeper.configuration }
6
+ subject { Doorkeeper.config }
7
7
 
8
8
  describe "resource_owner_authenticator" do
9
9
  it "sets the block that is accessible via authenticate_resource_owner" do
@@ -328,7 +328,7 @@ describe Doorkeeper, "configuration" do
328
328
 
329
329
  describe "enable_application_owner" do
330
330
  it "is disabled by default" do
331
- expect(Doorkeeper.configuration.enable_application_owner?).not_to eq(true)
331
+ expect(Doorkeeper.config.enable_application_owner?).not_to eq(true)
332
332
  end
333
333
 
334
334
  context "when enabled without confirmation" do
@@ -344,7 +344,7 @@ describe Doorkeeper, "configuration" do
344
344
  end
345
345
 
346
346
  it "Doorkeeper.configuration.confirm_application_owner? returns false" do
347
- expect(Doorkeeper.configuration.confirm_application_owner?).not_to eq(true)
347
+ expect(Doorkeeper.config.confirm_application_owner?).not_to eq(true)
348
348
  end
349
349
  end
350
350
 
@@ -361,14 +361,14 @@ describe Doorkeeper, "configuration" do
361
361
  end
362
362
 
363
363
  it "Doorkeeper.configuration.confirm_application_owner? returns true" do
364
- expect(Doorkeeper.configuration.confirm_application_owner?).to eq(true)
364
+ expect(Doorkeeper.config.confirm_application_owner?).to eq(true)
365
365
  end
366
366
  end
367
367
  end
368
368
 
369
369
  describe "realm" do
370
370
  it "is 'Doorkeeper' by default" do
371
- expect(Doorkeeper.configuration.realm).to eq("Doorkeeper")
371
+ expect(Doorkeeper.config.realm).to eq("Doorkeeper")
372
372
  end
373
373
 
374
374
  it "can change the value" do
@@ -383,7 +383,7 @@ describe Doorkeeper, "configuration" do
383
383
 
384
384
  describe "grant_flows" do
385
385
  it "is set to all grant flows by default" do
386
- expect(Doorkeeper.configuration.grant_flows)
386
+ expect(Doorkeeper.config.grant_flows)
387
387
  .to eq(%w[authorization_code client_credentials])
388
388
  end
389
389
 
@@ -454,13 +454,13 @@ describe Doorkeeper, "configuration" do
454
454
  end
455
455
 
456
456
  it "raises an exception when configuration is not set" do
457
- old_config = Doorkeeper.configuration
457
+ old_config = Doorkeeper.config
458
458
  Doorkeeper.module_eval do
459
459
  @config = nil
460
460
  end
461
461
 
462
462
  expect do
463
- Doorkeeper.configuration
463
+ Doorkeeper.config
464
464
  end.to raise_error Doorkeeper::MissingConfiguration
465
465
 
466
466
  Doorkeeper.module_eval do
@@ -527,13 +527,13 @@ describe Doorkeeper, "configuration" do
527
527
  end
528
528
  end
529
529
 
530
- it { expect(Doorkeeper.configuration.base_controller).to eq("ApplicationController") }
530
+ it { expect(Doorkeeper.config.base_controller).to eq("ApplicationController") }
531
531
  end
532
532
  end
533
533
 
534
534
  describe "base_metal_controller" do
535
535
  context "default" do
536
- it { expect(Doorkeeper.configuration.base_metal_controller).to eq("ActionController::API") }
536
+ it { expect(Doorkeeper.config.base_metal_controller).to eq("ActionController::API") }
537
537
  end
538
538
 
539
539
  context "custom" do
@@ -565,6 +565,10 @@ describe Doorkeeper, "configuration" do
565
565
  expect(model).to receive(:establish_connection)
566
566
  end
567
567
 
568
+ expect(Kernel).to receive(:warn).with(
569
+ /\[DOORKEEPER\] active_record_options has been deprecated and will soon be removed/,
570
+ )
571
+
568
572
  Doorkeeper.configure do
569
573
  orm DOORKEEPER_ORM
570
574
  active_record_options(
@@ -673,7 +677,7 @@ describe Doorkeeper, "configuration" do
673
677
 
674
678
  describe "handle_auth_errors" do
675
679
  it "is set to render by default" do
676
- expect(Doorkeeper.configuration.handle_auth_errors).to eq(:render)
680
+ expect(Doorkeeper.config.handle_auth_errors).to eq(:render)
677
681
  end
678
682
  it "can change the value" do
679
683
  Doorkeeper.configure do
@@ -13,7 +13,7 @@ describe "Revocable" do
13
13
  it "updates :revoked_at attribute with current time" do
14
14
  utc = double utc: double
15
15
  clock = double now: utc
16
- expect(subject).to receive(:update_attribute).with(:revoked_at, clock.now.utc)
16
+ expect(subject).to receive(:update_column).with(:revoked_at, clock.now.utc)
17
17
  subject.revoke(clock)
18
18
  end
19
19
  end
@@ -36,8 +36,7 @@ describe "Revocable" do
36
36
  end
37
37
 
38
38
  describe :revoke_previous_refresh_token! do
39
- it "revokes the previous token if existing, and resets the
40
- `previous_refresh_token` attribute" do
39
+ it "revokes the previous token if exists and resets the `previous_refresh_token` attribute" do
41
40
  previous_token = FactoryBot.create(
42
41
  :access_token,
43
42
  refresh_token: "refresh_token",
@@ -33,6 +33,14 @@ describe "Doorkeeper::Models::Scopes" do
33
33
  subject.scopes = %w[private admin]
34
34
  expect(subject.scopes_string).to eq("private admin")
35
35
  end
36
+
37
+ it "ignores duplicated scopes" do
38
+ subject.scopes = %w[private admin admin]
39
+ expect(subject.scopes_string).to eq("private admin")
40
+
41
+ subject.scopes = "private admin admin"
42
+ expect(subject.scopes_string).to eq("private admin")
43
+ end
36
44
  end
37
45
 
38
46
  describe :scopes_string do
@@ -12,7 +12,12 @@ describe Doorkeeper::OAuth::AuthorizationCodeRequest do
12
12
  }
13
13
  end
14
14
 
15
- let(:grant) { FactoryBot.create :access_grant }
15
+ let(:resource_owner) { FactoryBot.create :resource_owner }
16
+ let(:grant) do
17
+ FactoryBot.create :access_grant,
18
+ resource_owner_id: resource_owner.id,
19
+ resource_owner_type: resource_owner.class.name
20
+ end
16
21
  let(:client) { grant.application }
17
22
  let(:redirect_uri) { client.redirect_uri }
18
23
  let(:params) { { redirect_uri: redirect_uri } }
@@ -49,43 +54,42 @@ describe Doorkeeper::OAuth::AuthorizationCodeRequest do
49
54
  end
50
55
 
51
56
  it "requires the grant" do
52
- subject.grant = nil
57
+ subject = described_class.new(server, nil, client, params)
53
58
  subject.validate
54
59
  expect(subject.error).to eq(:invalid_grant)
55
60
  end
56
61
 
57
62
  it "requires the client" do
58
- subject.client = nil
63
+ subject = described_class.new(server, grant, nil, params)
59
64
  subject.validate
60
65
  expect(subject.error).to eq(:invalid_client)
61
66
  end
62
67
 
63
68
  it "requires the redirect_uri" do
64
- subject.redirect_uri = nil
69
+ subject = described_class.new(server, grant, nil, params.except(:redirect_uri))
65
70
  subject.validate
66
71
  expect(subject.error).to eq(:invalid_request)
67
72
  expect(subject.missing_param).to eq(:redirect_uri)
68
73
  end
69
74
 
70
75
  it "invalid code_verifier param because server does not support pkce" do
71
- # Some other ORMs work relies on #respond_to? so it's not a good idea to stub it :\
72
- allow_any_instance_of(Doorkeeper::AccessGrant).to receive(:respond_to?).with(anything).and_call_original
73
- allow_any_instance_of(Doorkeeper::AccessGrant).to receive(:respond_to?).with(:code_challenge).and_return(false)
74
-
75
- subject.code_verifier = "a45a9fea-0676-477e-95b1-a40f72ac3cfb"
76
+ allow(Doorkeeper::AccessGrant).to receive(:pkce_supported?).and_return(false)
77
+ code_verifier = "a45a9fea-0676-477e-95b1-a40f72ac3cfb"
78
+ subject = described_class.new(server, grant, client, params.merge(code_verifier: code_verifier))
76
79
  subject.validate
77
80
  expect(subject.error).to eq(:invalid_request)
78
81
  expect(subject.invalid_request_reason).to eq(:not_support_pkce)
79
82
  end
80
83
 
81
84
  it "matches the redirect_uri with grant's one" do
82
- subject.redirect_uri = "http://other.com"
85
+ subject = described_class.new(server, grant, client, params.merge(redirect_uri: "http://other.com"))
83
86
  subject.validate
84
87
  expect(subject.error).to eq(:invalid_grant)
85
88
  end
86
89
 
87
90
  it "matches the client with grant's one" do
88
- subject.client = FactoryBot.create :application
91
+ other_client = FactoryBot.create :application
92
+ subject = described_class.new(server, grant, other_client, params)
89
93
  subject.validate
90
94
  expect(subject.error).to eq(:invalid_grant)
91
95
  end
@@ -100,8 +104,11 @@ describe Doorkeeper::OAuth::AuthorizationCodeRequest do
100
104
  end
101
105
 
102
106
  FactoryBot.create(
103
- :access_token, application_id: client.id,
104
- resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s,
107
+ :access_token,
108
+ application_id: client.id,
109
+ resource_owner_id: grant.resource_owner_id,
110
+ resource_owner_type: grant.resource_owner_type,
111
+ scopes: grant.scopes.to_s,
105
112
  )
106
113
 
107
114
  expect { subject.authorize }.to_not(change { Doorkeeper::AccessToken.count })
@@ -117,8 +124,11 @@ describe Doorkeeper::OAuth::AuthorizationCodeRequest do
117
124
  end
118
125
 
119
126
  FactoryBot.create(
120
- :access_token, application_id: client.id,
121
- resource_owner_id: grant.resource_owner_id, scopes: grant.scopes.to_s,
127
+ :access_token,
128
+ application_id: client.id,
129
+ resource_owner_id: grant.resource_owner_id,
130
+ resource_owner_type: grant.resource_owner_type,
131
+ scopes: grant.scopes.to_s,
122
132
  )
123
133
 
124
134
  allow_any_instance_of(Doorkeeper::AccessToken).to receive(:reusable?).and_return(false)