doorkeeper 5.0.2 → 5.1.0.rc2
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.
- checksums.yaml +5 -5
- data/.travis.yml +17 -4
- data/Appraisals +29 -3
- data/Dangerfile +5 -2
- data/Gemfile +14 -4
- data/NEWS.md +64 -19
- data/README.md +68 -487
- data/app/controllers/doorkeeper/token_info_controller.rb +1 -1
- data/app/controllers/doorkeeper/tokens_controller.rb +7 -7
- data/app/views/doorkeeper/applications/show.html.erb +1 -1
- data/app/views/layouts/doorkeeper/admin.html.erb +5 -3
- data/bin/console +15 -0
- data/doorkeeper.gemspec +3 -2
- data/gemfiles/rails_4_2.gemfile +8 -4
- data/gemfiles/rails_5_0.gemfile +9 -5
- data/gemfiles/rails_5_1.gemfile +9 -5
- data/gemfiles/rails_5_2.gemfile +9 -5
- data/gemfiles/rails_6_0.gemfile +16 -0
- data/gemfiles/rails_master.gemfile +8 -9
- data/lib/doorkeeper/config.rb +164 -11
- data/lib/doorkeeper/helpers/controller.rb +3 -2
- data/lib/doorkeeper/models/access_grant_mixin.rb +16 -1
- data/lib/doorkeeper/models/access_token_mixin.rb +54 -10
- data/lib/doorkeeper/models/application_mixin.rb +42 -1
- data/lib/doorkeeper/models/concerns/expirable.rb +3 -2
- data/lib/doorkeeper/models/concerns/reusable.rb +19 -0
- data/lib/doorkeeper/models/concerns/scopes.rb +5 -1
- data/lib/doorkeeper/models/concerns/secret_storable.rb +106 -0
- data/lib/doorkeeper/oauth/authorization/code.rb +1 -1
- data/lib/doorkeeper/oauth/authorization/token.rb +4 -2
- data/lib/doorkeeper/oauth/authorization_code_request.rb +1 -1
- data/lib/doorkeeper/oauth/client.rb +1 -1
- data/lib/doorkeeper/oauth/client_credentials/validation.rb +4 -3
- data/lib/doorkeeper/oauth/code_response.rb +2 -2
- data/lib/doorkeeper/oauth/error_response.rb +5 -1
- data/lib/doorkeeper/oauth/helpers/scope_checker.rb +23 -8
- data/lib/doorkeeper/oauth/helpers/unique_token.rb +12 -1
- data/lib/doorkeeper/oauth/helpers/uri_checker.rb +32 -0
- data/lib/doorkeeper/oauth/invalid_token_response.rb +4 -0
- data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
- data/lib/doorkeeper/oauth/pre_authorization.rb +8 -3
- data/lib/doorkeeper/oauth/refresh_token_request.rb +4 -1
- data/lib/doorkeeper/oauth/token_introspection.rb +72 -6
- data/lib/doorkeeper/oauth/token_response.rb +2 -2
- data/lib/doorkeeper/orm/active_record/access_grant.rb +23 -2
- data/lib/doorkeeper/orm/active_record/application.rb +20 -2
- data/lib/doorkeeper/secret_storing/base.rb +63 -0
- data/lib/doorkeeper/secret_storing/bcrypt.rb +59 -0
- data/lib/doorkeeper/secret_storing/plain.rb +33 -0
- data/lib/doorkeeper/secret_storing/sha256_hash.rb +25 -0
- data/lib/doorkeeper/version.rb +3 -3
- data/lib/doorkeeper.rb +7 -0
- data/lib/generators/doorkeeper/templates/initializer.rb +90 -8
- data/spec/controllers/application_metal_controller_spec.rb +18 -4
- data/spec/controllers/authorizations_controller_spec.rb +3 -3
- data/spec/controllers/token_info_controller_spec.rb +1 -1
- data/spec/controllers/tokens_controller_spec.rb +85 -41
- data/spec/dummy/app/controllers/application_controller.rb +1 -1
- data/spec/dummy/config/application.rb +12 -1
- data/spec/factories.rb +3 -3
- data/spec/lib/config_spec.rb +168 -0
- data/spec/lib/models/expirable_spec.rb +12 -0
- data/spec/lib/models/reusable_spec.rb +40 -0
- data/spec/lib/models/scopes_spec.rb +13 -1
- data/spec/lib/models/secret_storable_spec.rb +113 -0
- data/spec/lib/oauth/authorization_code_request_spec.rb +18 -1
- data/spec/lib/oauth/base_request_spec.rb +7 -7
- data/spec/lib/oauth/client_credentials/creator_spec.rb +51 -7
- data/spec/lib/oauth/client_credentials/validation_spec.rb +3 -0
- data/spec/lib/oauth/error_response_spec.rb +7 -1
- data/spec/lib/oauth/helpers/scope_checker_spec.rb +52 -17
- data/spec/lib/oauth/helpers/uri_checker_spec.rb +20 -2
- data/spec/lib/oauth/password_access_token_request_spec.rb +43 -12
- data/spec/lib/oauth/pre_authorization_spec.rb +24 -0
- data/spec/lib/oauth/token_request_spec.rb +16 -1
- data/spec/lib/oauth/token_response_spec.rb +13 -13
- data/spec/lib/oauth/token_spec.rb +14 -0
- data/spec/lib/secret_storing/base_spec.rb +60 -0
- data/spec/lib/secret_storing/bcrypt_spec.rb +49 -0
- data/spec/lib/secret_storing/plain_spec.rb +44 -0
- data/spec/lib/secret_storing/sha256_hash_spec.rb +48 -0
- data/spec/models/doorkeeper/access_grant_spec.rb +61 -0
- data/spec/models/doorkeeper/access_token_spec.rb +123 -0
- data/spec/models/doorkeeper/application_spec.rb +56 -0
- data/spec/requests/flows/authorization_code_spec.rb +41 -1
- data/spec/requests/flows/client_credentials_spec.rb +2 -2
- data/spec/requests/flows/implicit_grant_spec.rb +1 -1
- data/spec/requests/flows/password_spec.rb +7 -5
- data/spec/requests/flows/revoke_token_spec.rb +14 -30
- data/spec/routing/custom_controller_routes_spec.rb +4 -0
- data/spec/spec_helper.rb +2 -1
- data/spec/support/ruby_2_6_rails_4_2_patch.rb +14 -0
- data/spec/support/shared/hashing_shared_context.rb +36 -0
- metadata +59 -22
|
@@ -17,9 +17,11 @@
|
|
|
17
17
|
<li class="nav-item <%= 'active' if request.path == oauth_applications_path %>">
|
|
18
18
|
<%= link_to t('doorkeeper.layouts.admin.nav.applications'), oauth_applications_path, class: 'nav-link' %>
|
|
19
19
|
</li>
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
<% if respond_to?(:root_path) %>
|
|
21
|
+
<li class="nav-item">
|
|
22
|
+
<%= link_to t('doorkeeper.layouts.admin.nav.home'), root_path, class: 'nav-link' %>
|
|
23
|
+
</li>
|
|
24
|
+
<% end %>
|
|
23
25
|
</ul>
|
|
24
26
|
</div>
|
|
25
27
|
</nav>
|
data/bin/console
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'bundler/setup'
|
|
4
|
+
require 'rails/all'
|
|
5
|
+
require 'doorkeeper'
|
|
6
|
+
|
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
|
9
|
+
|
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
|
11
|
+
# require "pry"
|
|
12
|
+
# Pry.start
|
|
13
|
+
|
|
14
|
+
require 'irb'
|
|
15
|
+
IRB.start(__FILE__)
|
data/doorkeeper.gemspec
CHANGED
|
@@ -19,13 +19,14 @@ Gem::Specification.new do |gem|
|
|
|
19
19
|
gem.add_dependency 'railties', '>= 4.2'
|
|
20
20
|
gem.required_ruby_version = '>= 2.1'
|
|
21
21
|
|
|
22
|
-
gem.add_development_dependency '
|
|
22
|
+
gem.add_development_dependency 'appraisal'
|
|
23
|
+
gem.add_development_dependency 'capybara'
|
|
23
24
|
gem.add_development_dependency 'coveralls'
|
|
24
25
|
gem.add_development_dependency 'danger', '~> 5.0'
|
|
25
|
-
gem.add_development_dependency 'grape'
|
|
26
26
|
gem.add_development_dependency 'database_cleaner', '~> 1.6'
|
|
27
27
|
gem.add_development_dependency 'factory_bot', '~> 4.8'
|
|
28
28
|
gem.add_development_dependency 'generator_spec', '~> 0.9.3'
|
|
29
|
+
gem.add_development_dependency 'grape'
|
|
29
30
|
gem.add_development_dependency 'rake', '>= 11.3.0'
|
|
30
31
|
gem.add_development_dependency 'rspec-rails'
|
|
31
32
|
end
|
data/gemfiles/rails_4_2.gemfile
CHANGED
|
@@ -3,11 +3,15 @@
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
5
|
gem "rails", "~> 4.2.0"
|
|
6
|
-
gem "
|
|
6
|
+
gem "rspec-core", git: "https://github.com/rspec/rspec-core.git"
|
|
7
|
+
gem "rspec-expectations", git: "https://github.com/rspec/rspec-expectations.git"
|
|
8
|
+
gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
|
+
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
|
10
|
+
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
|
11
|
+
gem "bcrypt", "~> 3.1", require: false
|
|
7
12
|
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
|
8
|
-
gem "sqlite3", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
13
|
+
gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
9
14
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
10
|
-
|
|
11
|
-
gem "grape", '~> 0.16', '< 0.19.2'
|
|
15
|
+
gem "grape", "~> 0.16", "< 0.19.2"
|
|
12
16
|
|
|
13
17
|
gemspec path: "../"
|
data/gemfiles/rails_5_0.gemfile
CHANGED
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "rails", "~> 5.0.0"
|
|
6
|
-
gem "
|
|
7
|
-
gem "
|
|
8
|
-
gem "
|
|
5
|
+
gem "rails", "~> 5.0.0", ">= 5.0.7.2"
|
|
6
|
+
gem "rspec-core", git: "https://github.com/rspec/rspec-core.git"
|
|
7
|
+
gem "rspec-expectations", git: "https://github.com/rspec/rspec-expectations.git"
|
|
8
|
+
gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
|
+
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
|
10
|
+
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
|
11
|
+
gem "bcrypt", "~> 3.1", require: false
|
|
12
|
+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
|
13
|
+
gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
9
14
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
10
|
-
gem "rspec-rails", "~> 3.5"
|
|
11
15
|
|
|
12
16
|
gemspec path: "../"
|
data/gemfiles/rails_5_1.gemfile
CHANGED
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "rails", "~> 5.1.0"
|
|
6
|
-
gem "
|
|
7
|
-
gem "
|
|
8
|
-
gem "
|
|
5
|
+
gem "rails", "~> 5.1.0", ">= 5.1.6.2"
|
|
6
|
+
gem "rspec-core", git: "https://github.com/rspec/rspec-core.git"
|
|
7
|
+
gem "rspec-expectations", git: "https://github.com/rspec/rspec-expectations.git"
|
|
8
|
+
gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
|
+
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
|
10
|
+
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
|
11
|
+
gem "bcrypt", "~> 3.1", require: false
|
|
12
|
+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
|
13
|
+
gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
9
14
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
10
|
-
gem "rspec-rails", "~> 3.7"
|
|
11
15
|
|
|
12
16
|
gemspec path: "../"
|
data/gemfiles/rails_5_2.gemfile
CHANGED
|
@@ -2,11 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "rails", "5.2.
|
|
6
|
-
gem "
|
|
7
|
-
gem "
|
|
8
|
-
gem "
|
|
5
|
+
gem "rails", "~> 5.2.2", ">= 5.2.2.1"
|
|
6
|
+
gem "rspec-core", git: "https://github.com/rspec/rspec-core.git"
|
|
7
|
+
gem "rspec-expectations", git: "https://github.com/rspec/rspec-expectations.git"
|
|
8
|
+
gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
|
+
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
|
10
|
+
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
|
11
|
+
gem "bcrypt", "~> 3.1", require: false
|
|
12
|
+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
|
13
|
+
gem "sqlite3", "~> 1.3", "< 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
9
14
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
10
|
-
gem "rspec-rails", "~> 3.7"
|
|
11
15
|
|
|
12
16
|
gemspec path: "../"
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# This file was generated by Appraisal
|
|
2
|
+
|
|
3
|
+
source "https://rubygems.org"
|
|
4
|
+
|
|
5
|
+
gem "rails", "~> 6.0.0.beta3"
|
|
6
|
+
gem "rspec-core", git: "https://github.com/rspec/rspec-core.git"
|
|
7
|
+
gem "rspec-expectations", git: "https://github.com/rspec/rspec-expectations.git"
|
|
8
|
+
gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
|
+
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
|
10
|
+
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
|
11
|
+
gem "bcrypt", "~> 3.1", require: false
|
|
12
|
+
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
|
13
|
+
gem "sqlite3", "~> 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
14
|
+
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
15
|
+
|
|
16
|
+
gemspec path: "../"
|
|
@@ -2,16 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
source "https://rubygems.org"
|
|
4
4
|
|
|
5
|
-
gem "rails", git:
|
|
6
|
-
gem "
|
|
7
|
-
|
|
8
|
-
gem "
|
|
5
|
+
gem "rails", git: "https://github.com/rails/rails"
|
|
6
|
+
gem "rspec-core", git: "https://github.com/rspec/rspec-core.git"
|
|
7
|
+
gem "rspec-expectations", git: "https://github.com/rspec/rspec-expectations.git"
|
|
8
|
+
gem "rspec-mocks", git: "https://github.com/rspec/rspec-mocks.git"
|
|
9
|
+
gem "rspec-rails", branch: "4-0-dev", git: "https://github.com/rspec/rspec-rails.git"
|
|
10
|
+
gem "rspec-support", git: "https://github.com/rspec/rspec-support.git"
|
|
11
|
+
gem "bcrypt", "~> 3.1", require: false
|
|
9
12
|
gem "activerecord-jdbcsqlite3-adapter", platform: :jruby
|
|
10
|
-
gem "sqlite3", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
13
|
+
gem "sqlite3", "~> 1.4", platform: [:ruby, :mswin, :mingw, :x64_mingw]
|
|
11
14
|
gem "tzinfo-data", platforms: [:mingw, :mswin, :x64_mingw]
|
|
12
15
|
|
|
13
|
-
%w[rspec-core rspec-expectations rspec-mocks rspec-rails rspec-support].each do |lib|
|
|
14
|
-
gem lib, git: "https://github.com/rspec/#{lib}.git", branch: 'master'
|
|
15
|
-
end
|
|
16
|
-
|
|
17
16
|
gemspec path: "../"
|
data/lib/doorkeeper/config.rb
CHANGED
|
@@ -46,6 +46,7 @@ module Doorkeeper
|
|
|
46
46
|
end
|
|
47
47
|
|
|
48
48
|
def build
|
|
49
|
+
@config.validate
|
|
49
50
|
@config
|
|
50
51
|
end
|
|
51
52
|
|
|
@@ -83,6 +84,13 @@ module Doorkeeper
|
|
|
83
84
|
@config.instance_variable_set(:@optional_scopes, OAuth::Scopes.from_array(scopes))
|
|
84
85
|
end
|
|
85
86
|
|
|
87
|
+
# Define scopes_by_grant_type to limit certain scope to certain grant_type
|
|
88
|
+
# @param { Hash } with grant_types as keys.
|
|
89
|
+
# Default set to {} i.e. no limitation on scopes usage
|
|
90
|
+
def scopes_by_grant_type(hash = {})
|
|
91
|
+
@config.instance_variable_set(:@scopes_by_grant_type, hash)
|
|
92
|
+
end
|
|
93
|
+
|
|
86
94
|
# Change the way client credentials are retrieved from the request object.
|
|
87
95
|
# By default it retrieves first from the `HTTP_AUTHORIZATION` header, then
|
|
88
96
|
# falls back to the `:client_id` and `:client_secret` params from the
|
|
@@ -118,6 +126,15 @@ module Doorkeeper
|
|
|
118
126
|
@config.instance_variable_set(:@reuse_access_token, true)
|
|
119
127
|
end
|
|
120
128
|
|
|
129
|
+
# Sets the token_reuse_limit
|
|
130
|
+
# It will be used only when reuse_access_token option in enabled
|
|
131
|
+
# By default it will be 100
|
|
132
|
+
# It will be used for token reusablity to some threshold percentage
|
|
133
|
+
# Rationale: https://github.com/doorkeeper-gem/doorkeeper/issues/1189
|
|
134
|
+
def token_reuse_limit(percentage)
|
|
135
|
+
@config.instance_variable_set(:@token_reuse_limit, percentage)
|
|
136
|
+
end
|
|
137
|
+
|
|
121
138
|
# Use an API mode for applications generated with --api argument
|
|
122
139
|
# It will skip applications controller, disable forgery protection
|
|
123
140
|
def api_only
|
|
@@ -136,6 +153,57 @@ module Doorkeeper
|
|
|
136
153
|
def enforce_content_type
|
|
137
154
|
@config.instance_variable_set(:@enforce_content_type, true)
|
|
138
155
|
end
|
|
156
|
+
|
|
157
|
+
# Allow optional hashing of input tokens before persisting them.
|
|
158
|
+
# Will be used for hashing of input token and grants.
|
|
159
|
+
#
|
|
160
|
+
# @param using
|
|
161
|
+
# Provide a different secret storage implementation class for tokens
|
|
162
|
+
# @param fallback
|
|
163
|
+
# Provide a fallback secret storage implementation class for tokens
|
|
164
|
+
# or use :plain to fallback to plain tokens
|
|
165
|
+
def hash_token_secrets(using: nil, fallback: nil)
|
|
166
|
+
default = '::Doorkeeper::SecretStoring::Sha256Hash'
|
|
167
|
+
configure_secrets_for :token,
|
|
168
|
+
using: using || default,
|
|
169
|
+
fallback: fallback
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# Allow optional hashing of application secrets before persisting them.
|
|
173
|
+
# Will be used for hashing of input token and grants.
|
|
174
|
+
#
|
|
175
|
+
# @param using
|
|
176
|
+
# Provide a different secret storage implementation for applications
|
|
177
|
+
# @param fallback
|
|
178
|
+
# Provide a fallback secret storage implementation for applications
|
|
179
|
+
# or use :plain to fallback to plain application secrets
|
|
180
|
+
def hash_application_secrets(using: nil, fallback: nil)
|
|
181
|
+
default = '::Doorkeeper::SecretStoring::Sha256Hash'
|
|
182
|
+
configure_secrets_for :application,
|
|
183
|
+
using: using || default,
|
|
184
|
+
fallback: fallback
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
private
|
|
188
|
+
|
|
189
|
+
# Configure the secret storing functionality
|
|
190
|
+
def configure_secrets_for(type, using:, fallback:)
|
|
191
|
+
unless %i[application token].include?(type)
|
|
192
|
+
raise ArgumentError, "Invalid type #{type}"
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
@config.instance_variable_set(:"@#{type}_secret_strategy",
|
|
196
|
+
using.constantize)
|
|
197
|
+
|
|
198
|
+
if fallback.nil?
|
|
199
|
+
return
|
|
200
|
+
elsif fallback.to_sym == :plain
|
|
201
|
+
fallback = '::Doorkeeper::SecretStoring::Plain'
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
@config.instance_variable_set(:"@#{type}_secret_fallback_strategy",
|
|
205
|
+
fallback.constantize)
|
|
206
|
+
end
|
|
139
207
|
end
|
|
140
208
|
|
|
141
209
|
module Option
|
|
@@ -226,11 +294,16 @@ module Doorkeeper
|
|
|
226
294
|
|
|
227
295
|
nil
|
|
228
296
|
end)
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
option :
|
|
232
|
-
option :
|
|
233
|
-
|
|
297
|
+
|
|
298
|
+
# Hooks for authorization
|
|
299
|
+
option :before_successful_authorization, default: ->(_context) {}
|
|
300
|
+
option :after_successful_authorization, default: ->(_context) {}
|
|
301
|
+
# Hooks for strategies responses
|
|
302
|
+
option :before_successful_strategy_response, default: ->(_request) {}
|
|
303
|
+
option :after_successful_strategy_response, default: ->(_request, _response) {}
|
|
304
|
+
# Allows to customize Token Introspection response
|
|
305
|
+
option :custom_introspection_response, default: ->(_token, _context) { {} }
|
|
306
|
+
|
|
234
307
|
option :skip_authorization, default: ->(_routes) {}
|
|
235
308
|
option :access_token_expires_in, default: 7200
|
|
236
309
|
option :custom_access_token_expires_in, default: ->(_context) { nil }
|
|
@@ -278,6 +351,15 @@ module Doorkeeper
|
|
|
278
351
|
option :access_token_generator,
|
|
279
352
|
default: 'Doorkeeper::OAuth::Helpers::UniqueToken'
|
|
280
353
|
|
|
354
|
+
|
|
355
|
+
# Default access token generator is a SecureRandom class from Ruby stdlib.
|
|
356
|
+
# This option defines which method will be used to generate a unique token value.
|
|
357
|
+
#
|
|
358
|
+
# @param access_token_generator [String]
|
|
359
|
+
# the name of the access token generator class
|
|
360
|
+
#
|
|
361
|
+
option :default_generator_method, default: :urlsafe_base64
|
|
362
|
+
|
|
281
363
|
# The controller Doorkeeper::ApplicationController inherits from.
|
|
282
364
|
# Defaults to ActionController::Base.
|
|
283
365
|
# https://github.com/doorkeeper-gem/doorkeeper#custom-base-controller
|
|
@@ -286,9 +368,16 @@ module Doorkeeper
|
|
|
286
368
|
option :base_controller,
|
|
287
369
|
default: 'ActionController::Base'
|
|
288
370
|
|
|
289
|
-
attr_reader :
|
|
290
|
-
|
|
291
|
-
|
|
371
|
+
attr_reader :api_only,
|
|
372
|
+
:enforce_content_type,
|
|
373
|
+
:reuse_access_token
|
|
374
|
+
|
|
375
|
+
# Return the valid subset of this configuration
|
|
376
|
+
def validate
|
|
377
|
+
validate_reuse_access_token_value
|
|
378
|
+
validate_token_reuse_limit
|
|
379
|
+
validate_secret_strategies
|
|
380
|
+
end
|
|
292
381
|
|
|
293
382
|
def api_only
|
|
294
383
|
@api_only ||= false
|
|
@@ -306,22 +395,42 @@ module Doorkeeper
|
|
|
306
395
|
end
|
|
307
396
|
end
|
|
308
397
|
|
|
398
|
+
def token_reuse_limit
|
|
399
|
+
@token_reuse_limit ||= 100
|
|
400
|
+
end
|
|
401
|
+
|
|
309
402
|
def enforce_configured_scopes?
|
|
310
|
-
|
|
403
|
+
option_set? :enforce_configured_scopes
|
|
311
404
|
end
|
|
312
405
|
|
|
313
406
|
def enable_application_owner?
|
|
314
|
-
|
|
407
|
+
option_set? :enable_application_owner
|
|
315
408
|
end
|
|
316
409
|
|
|
317
410
|
def confirm_application_owner?
|
|
318
|
-
|
|
411
|
+
option_set? :confirm_application_owner
|
|
319
412
|
end
|
|
320
413
|
|
|
321
414
|
def raise_on_errors?
|
|
322
415
|
handle_auth_errors == :raise
|
|
323
416
|
end
|
|
324
417
|
|
|
418
|
+
def token_secret_strategy
|
|
419
|
+
@token_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def token_secret_fallback_strategy
|
|
423
|
+
@token_secret_fallback_strategy
|
|
424
|
+
end
|
|
425
|
+
|
|
426
|
+
def application_secret_strategy
|
|
427
|
+
@application_secret_strategy ||= ::Doorkeeper::SecretStoring::Plain
|
|
428
|
+
end
|
|
429
|
+
|
|
430
|
+
def application_secret_fallback_strategy
|
|
431
|
+
@application_secret_fallback_strategy
|
|
432
|
+
end
|
|
433
|
+
|
|
325
434
|
def default_scopes
|
|
326
435
|
@default_scopes ||= OAuth::Scopes.new
|
|
327
436
|
end
|
|
@@ -334,6 +443,10 @@ module Doorkeeper
|
|
|
334
443
|
@scopes ||= default_scopes + optional_scopes
|
|
335
444
|
end
|
|
336
445
|
|
|
446
|
+
def scopes_by_grant_type
|
|
447
|
+
@scopes_by_grant_type ||= {}
|
|
448
|
+
end
|
|
449
|
+
|
|
337
450
|
def client_credentials_methods
|
|
338
451
|
@client_credentials_methods ||= %i[from_basic from_params]
|
|
339
452
|
end
|
|
@@ -352,6 +465,12 @@ module Doorkeeper
|
|
|
352
465
|
|
|
353
466
|
private
|
|
354
467
|
|
|
468
|
+
# Helper to read boolearized configuration option
|
|
469
|
+
def option_set?(instance_key)
|
|
470
|
+
var = instance_variable_get("@#{instance_key}")
|
|
471
|
+
!!(defined?(var) && var)
|
|
472
|
+
end
|
|
473
|
+
|
|
355
474
|
# Determines what values are acceptable for 'response_type' param in
|
|
356
475
|
# authorization request endpoint, and return them as an array of strings.
|
|
357
476
|
#
|
|
@@ -370,5 +489,39 @@ module Doorkeeper
|
|
|
370
489
|
types << 'refresh_token' if refresh_token_enabled?
|
|
371
490
|
types
|
|
372
491
|
end
|
|
492
|
+
|
|
493
|
+
# Determine whether +reuse_access_token+ and a non-restorable
|
|
494
|
+
# +token_secret_strategy+ have both been activated.
|
|
495
|
+
#
|
|
496
|
+
# In that case, disable reuse_access_token value and warn the user.
|
|
497
|
+
def validate_reuse_access_token_value
|
|
498
|
+
strategy = token_secret_strategy
|
|
499
|
+
return if !reuse_access_token || strategy.allows_restoring_secrets?
|
|
500
|
+
|
|
501
|
+
::Rails.logger.warn(
|
|
502
|
+
"You have configured both reuse_access_token " \
|
|
503
|
+
"AND strategy strategy '#{strategy}' that cannot restore tokens. " \
|
|
504
|
+
"This combination is unsupported. reuse_access_token will be disabled"
|
|
505
|
+
)
|
|
506
|
+
@reuse_access_token = false
|
|
507
|
+
end
|
|
508
|
+
|
|
509
|
+
# Validate that the provided strategies are valid for
|
|
510
|
+
# tokens and applications
|
|
511
|
+
def validate_secret_strategies
|
|
512
|
+
token_secret_strategy.validate_for :token
|
|
513
|
+
application_secret_strategy.validate_for :application
|
|
514
|
+
end
|
|
515
|
+
|
|
516
|
+
def validate_token_reuse_limit
|
|
517
|
+
return if !reuse_access_token ||
|
|
518
|
+
(token_reuse_limit > 0 && token_reuse_limit <= 100)
|
|
519
|
+
|
|
520
|
+
::Rails.logger.warn(
|
|
521
|
+
'You have configured an invalid value for token_reuse_limit option. ' \
|
|
522
|
+
'It will be set to default 100'
|
|
523
|
+
)
|
|
524
|
+
@token_reuse_limit = 100
|
|
525
|
+
end
|
|
373
526
|
end
|
|
374
527
|
end
|
|
@@ -55,8 +55,9 @@ module Doorkeeper
|
|
|
55
55
|
end
|
|
56
56
|
|
|
57
57
|
def enforce_content_type
|
|
58
|
-
|
|
59
|
-
|
|
58
|
+
if (request.put? || request.post? || request.patch?) && request.content_type != 'application/x-www-form-urlencoded'
|
|
59
|
+
render json: {}, status: :unsupported_media_type
|
|
60
|
+
end
|
|
60
61
|
end
|
|
61
62
|
end
|
|
62
63
|
end
|
|
@@ -9,6 +9,7 @@ module Doorkeeper
|
|
|
9
9
|
include Models::Revocable
|
|
10
10
|
include Models::Accessible
|
|
11
11
|
include Models::Orderable
|
|
12
|
+
include Models::SecretStorable
|
|
12
13
|
include Models::Scopes
|
|
13
14
|
|
|
14
15
|
# never uses pkce, if pkce migrations were not generated
|
|
@@ -30,7 +31,7 @@ module Doorkeeper
|
|
|
30
31
|
# if there is no record with such token
|
|
31
32
|
#
|
|
32
33
|
def by_token(token)
|
|
33
|
-
|
|
34
|
+
find_by_plaintext_token(:token, token)
|
|
34
35
|
end
|
|
35
36
|
|
|
36
37
|
# Revokes AccessGrant records that have not been revoked and associated
|
|
@@ -94,6 +95,20 @@ module Doorkeeper
|
|
|
94
95
|
def pkce_supported?
|
|
95
96
|
new.pkce_supported?
|
|
96
97
|
end
|
|
98
|
+
|
|
99
|
+
##
|
|
100
|
+
# Determines the secret storing transformer
|
|
101
|
+
# Unless configured otherwise, uses the plain secret strategy
|
|
102
|
+
def secret_strategy
|
|
103
|
+
::Doorkeeper.configuration.token_secret_strategy
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
##
|
|
107
|
+
# Determine the fallback storing strategy
|
|
108
|
+
# Unless configured, there will be no fallback
|
|
109
|
+
def fallback_secret_strategy
|
|
110
|
+
::Doorkeeper.configuration.token_secret_fallback_strategy
|
|
111
|
+
end
|
|
97
112
|
end
|
|
98
113
|
end
|
|
99
114
|
end
|
|
@@ -6,23 +6,25 @@ module Doorkeeper
|
|
|
6
6
|
|
|
7
7
|
include OAuth::Helpers
|
|
8
8
|
include Models::Expirable
|
|
9
|
+
include Models::Reusable
|
|
9
10
|
include Models::Revocable
|
|
10
11
|
include Models::Accessible
|
|
11
12
|
include Models::Orderable
|
|
13
|
+
include Models::SecretStorable
|
|
12
14
|
include Models::Scopes
|
|
13
15
|
|
|
14
16
|
module ClassMethods
|
|
15
17
|
# Returns an instance of the Doorkeeper::AccessToken with
|
|
16
|
-
# specific token value.
|
|
18
|
+
# specific plain text token value.
|
|
17
19
|
#
|
|
18
20
|
# @param token [#to_s]
|
|
19
|
-
# token value (any object that responds to `#to_s`)
|
|
21
|
+
# Plain text token value (any object that responds to `#to_s`)
|
|
20
22
|
#
|
|
21
23
|
# @return [Doorkeeper::AccessToken, nil] AccessToken object or nil
|
|
22
24
|
# if there is no record with such token
|
|
23
25
|
#
|
|
24
26
|
def by_token(token)
|
|
25
|
-
|
|
27
|
+
find_by_plaintext_token(:token, token)
|
|
26
28
|
end
|
|
27
29
|
|
|
28
30
|
# Returns an instance of the Doorkeeper::AccessToken
|
|
@@ -35,7 +37,7 @@ module Doorkeeper
|
|
|
35
37
|
# if there is no record with such refresh token
|
|
36
38
|
#
|
|
37
39
|
def by_refresh_token(refresh_token)
|
|
38
|
-
|
|
40
|
+
find_by_plaintext_token(:refresh_token, refresh_token)
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
# Revokes AccessToken records that have not been revoked and associated
|
|
@@ -98,9 +100,9 @@ module Doorkeeper
|
|
|
98
100
|
|
|
99
101
|
(token_scopes.sort == param_scopes.sort) &&
|
|
100
102
|
Doorkeeper::OAuth::Helpers::ScopeChecker.valid?(
|
|
101
|
-
param_scopes.to_s,
|
|
102
|
-
Doorkeeper.configuration.scopes,
|
|
103
|
-
app_scopes
|
|
103
|
+
scope_str: param_scopes.to_s,
|
|
104
|
+
server_scopes: Doorkeeper.configuration.scopes,
|
|
105
|
+
app_scopes: app_scopes
|
|
104
106
|
)
|
|
105
107
|
end
|
|
106
108
|
|
|
@@ -125,7 +127,7 @@ module Doorkeeper
|
|
|
125
127
|
if Doorkeeper.configuration.reuse_access_token
|
|
126
128
|
access_token = matching_token_for(application, resource_owner_id, scopes)
|
|
127
129
|
|
|
128
|
-
return access_token if access_token &&
|
|
130
|
+
return access_token if access_token && access_token.reusable?
|
|
129
131
|
end
|
|
130
132
|
|
|
131
133
|
create!(
|
|
@@ -168,6 +170,20 @@ module Doorkeeper
|
|
|
168
170
|
def last_authorized_token_for(application_id, resource_owner_id)
|
|
169
171
|
authorized_tokens_for(application_id, resource_owner_id).first
|
|
170
172
|
end
|
|
173
|
+
|
|
174
|
+
##
|
|
175
|
+
# Determines the secret storing transformer
|
|
176
|
+
# Unless configured otherwise, uses the plain secret strategy
|
|
177
|
+
def secret_strategy
|
|
178
|
+
::Doorkeeper.configuration.token_secret_strategy
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
##
|
|
182
|
+
# Determine the fallback storing strategy
|
|
183
|
+
# Unless configured, there will be no fallback
|
|
184
|
+
def fallback_secret_strategy
|
|
185
|
+
::Doorkeeper.configuration.token_secret_fallback_strategy
|
|
186
|
+
end
|
|
171
187
|
end
|
|
172
188
|
|
|
173
189
|
# Access Token type: Bearer.
|
|
@@ -219,6 +235,30 @@ module Doorkeeper
|
|
|
219
235
|
accessible? && includes_scope?(*scopes)
|
|
220
236
|
end
|
|
221
237
|
|
|
238
|
+
# We keep a volatile copy of the raw refresh token for initial communication
|
|
239
|
+
# The stored refresh_token may be mapped and not available in cleartext.
|
|
240
|
+
def plaintext_refresh_token
|
|
241
|
+
if secret_strategy.allows_restoring_secrets?
|
|
242
|
+
secret_strategy.restore_secret(self, :refresh_token)
|
|
243
|
+
else
|
|
244
|
+
@raw_refresh_token
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
# We keep a volatile copy of the raw token for initial communication
|
|
249
|
+
# The stored refresh_token may be mapped and not available in cleartext.
|
|
250
|
+
#
|
|
251
|
+
# Some strategies allow restoring stored secrets (e.g. symmetric encryption)
|
|
252
|
+
# while hashing strategies do not, so you cannot rely on this value
|
|
253
|
+
# returning a present value for persisted tokens.
|
|
254
|
+
def plaintext_token
|
|
255
|
+
if secret_strategy.allows_restoring_secrets?
|
|
256
|
+
secret_strategy.restore_secret(self, :token)
|
|
257
|
+
else
|
|
258
|
+
@raw_token
|
|
259
|
+
end
|
|
260
|
+
end
|
|
261
|
+
|
|
222
262
|
private
|
|
223
263
|
|
|
224
264
|
# Generates refresh token with UniqueToken generator.
|
|
@@ -226,7 +266,8 @@ module Doorkeeper
|
|
|
226
266
|
# @return [String] refresh token value
|
|
227
267
|
#
|
|
228
268
|
def generate_refresh_token
|
|
229
|
-
|
|
269
|
+
@raw_refresh_token = UniqueToken.generate
|
|
270
|
+
secret_strategy.store_secret(self, :refresh_token, @raw_refresh_token)
|
|
230
271
|
end
|
|
231
272
|
|
|
232
273
|
# Generates and sets the token value with the
|
|
@@ -242,13 +283,16 @@ module Doorkeeper
|
|
|
242
283
|
def generate_token
|
|
243
284
|
self.created_at ||= Time.now.utc
|
|
244
285
|
|
|
245
|
-
|
|
286
|
+
@raw_token = token_generator.generate(
|
|
246
287
|
resource_owner_id: resource_owner_id,
|
|
247
288
|
scopes: scopes,
|
|
248
289
|
application: application,
|
|
249
290
|
expires_in: expires_in,
|
|
250
291
|
created_at: created_at
|
|
251
292
|
)
|
|
293
|
+
|
|
294
|
+
secret_strategy.store_secret(self, :token, @raw_token)
|
|
295
|
+
@raw_token
|
|
252
296
|
end
|
|
253
297
|
|
|
254
298
|
def token_generator
|