doorkeeper 5.1.0 → 5.2.0

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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/Appraisals +1 -1
  3. data/CHANGELOG.md +843 -0
  4. data/CONTRIBUTING.md +11 -9
  5. data/Dangerfile +2 -2
  6. data/Dockerfile +29 -0
  7. data/Gemfile +2 -1
  8. data/NEWS.md +1 -814
  9. data/README.md +11 -3
  10. data/RELEASING.md +6 -5
  11. data/app/controllers/doorkeeper/application_controller.rb +1 -1
  12. data/app/controllers/doorkeeper/application_metal_controller.rb +2 -1
  13. data/app/controllers/doorkeeper/applications_controller.rb +2 -0
  14. data/app/controllers/doorkeeper/authorizations_controller.rb +14 -7
  15. data/app/controllers/doorkeeper/tokens_controller.rb +32 -9
  16. data/app/views/doorkeeper/applications/_form.html.erb +0 -6
  17. data/app/views/doorkeeper/applications/show.html.erb +1 -1
  18. data/config/locales/en.yml +8 -2
  19. data/doorkeeper.gemspec +9 -1
  20. data/gemfiles/rails_5_0.gemfile +1 -0
  21. data/gemfiles/rails_5_1.gemfile +1 -0
  22. data/gemfiles/rails_5_2.gemfile +1 -0
  23. data/gemfiles/rails_6_0.gemfile +2 -1
  24. data/gemfiles/rails_master.gemfile +1 -0
  25. data/lib/doorkeeper/config/option.rb +13 -7
  26. data/lib/doorkeeper/config.rb +88 -6
  27. data/lib/doorkeeper/errors.rb +13 -18
  28. data/lib/doorkeeper/grape/helpers.rb +5 -1
  29. data/lib/doorkeeper/helpers/controller.rb +20 -3
  30. data/lib/doorkeeper/models/access_token_mixin.rb +43 -2
  31. data/lib/doorkeeper/oauth/authorization/code.rb +11 -13
  32. data/lib/doorkeeper/oauth/authorization/token.rb +1 -1
  33. data/lib/doorkeeper/oauth/authorization_code_request.rb +18 -9
  34. data/lib/doorkeeper/oauth/base_request.rb +2 -0
  35. data/lib/doorkeeper/oauth/client_credentials/creator.rb +14 -0
  36. data/lib/doorkeeper/oauth/client_credentials/validation.rb +8 -0
  37. data/lib/doorkeeper/oauth/code_request.rb +5 -11
  38. data/lib/doorkeeper/oauth/code_response.rb +2 -2
  39. data/lib/doorkeeper/oauth/error_response.rb +1 -1
  40. data/lib/doorkeeper/oauth/helpers/uri_checker.rb +18 -4
  41. data/lib/doorkeeper/oauth/invalid_request_response.rb +43 -0
  42. data/lib/doorkeeper/oauth/nonstandard.rb +39 -0
  43. data/lib/doorkeeper/oauth/password_access_token_request.rb +7 -2
  44. data/lib/doorkeeper/oauth/pre_authorization.rb +70 -37
  45. data/lib/doorkeeper/oauth/refresh_token_request.rb +13 -10
  46. data/lib/doorkeeper/oauth/token_introspection.rb +23 -13
  47. data/lib/doorkeeper/oauth/token_request.rb +4 -18
  48. data/lib/doorkeeper/orm/active_record/access_grant.rb +1 -1
  49. data/lib/doorkeeper/orm/active_record/access_token.rb +2 -2
  50. data/lib/doorkeeper/orm/active_record/application.rb +8 -2
  51. data/lib/doorkeeper/orm/active_record/redirect_uri_validator.rb +61 -0
  52. data/lib/doorkeeper/orm/active_record.rb +19 -3
  53. data/lib/doorkeeper/request/authorization_code.rb +2 -0
  54. data/lib/doorkeeper/request.rb +6 -11
  55. data/lib/doorkeeper/server.rb +2 -6
  56. data/lib/doorkeeper/stale_records_cleaner.rb +6 -2
  57. data/lib/doorkeeper/version.rb +1 -1
  58. data/lib/doorkeeper.rb +4 -0
  59. data/lib/generators/doorkeeper/previous_refresh_token_generator.rb +6 -6
  60. data/lib/generators/doorkeeper/templates/initializer.rb +110 -33
  61. data/lib/generators/doorkeeper/templates/migration.rb.erb +4 -1
  62. data/spec/controllers/applications_controller_spec.rb +93 -0
  63. data/spec/controllers/authorizations_controller_spec.rb +140 -61
  64. data/spec/controllers/protected_resources_controller_spec.rb +3 -3
  65. data/spec/controllers/tokens_controller_spec.rb +205 -37
  66. data/spec/dummy/config/application.rb +3 -1
  67. data/spec/dummy/config/initializers/doorkeeper.rb +54 -9
  68. data/spec/dummy/db/migrate/20151223192035_create_doorkeeper_tables.rb +1 -1
  69. data/spec/lib/config_spec.rb +43 -1
  70. data/spec/lib/oauth/authorization_code_request_spec.rb +11 -1
  71. data/spec/lib/oauth/base_request_spec.rb +33 -16
  72. data/spec/lib/oauth/client_credentials/creator_spec.rb +3 -0
  73. data/spec/lib/oauth/code_request_spec.rb +27 -28
  74. data/spec/lib/oauth/helpers/uri_checker_spec.rb +17 -2
  75. data/spec/lib/oauth/invalid_request_response_spec.rb +75 -0
  76. data/spec/lib/oauth/pre_authorization_spec.rb +76 -66
  77. data/spec/lib/oauth/refresh_token_request_spec.rb +1 -0
  78. data/spec/lib/oauth/token_request_spec.rb +20 -17
  79. data/spec/lib/server_spec.rb +0 -12
  80. data/spec/requests/endpoints/authorization_spec.rb +21 -5
  81. data/spec/requests/endpoints/token_spec.rb +1 -1
  82. data/spec/requests/flows/authorization_code_errors_spec.rb +1 -0
  83. data/spec/requests/flows/authorization_code_spec.rb +93 -27
  84. data/spec/requests/flows/client_credentials_spec.rb +38 -0
  85. data/spec/requests/flows/implicit_grant_errors_spec.rb +22 -10
  86. data/spec/requests/flows/implicit_grant_spec.rb +9 -8
  87. data/spec/requests/flows/password_spec.rb +37 -0
  88. data/spec/requests/flows/refresh_token_spec.rb +1 -1
  89. data/spec/requests/flows/revoke_token_spec.rb +19 -11
  90. data/spec/support/doorkeeper_rspec.rb +1 -1
  91. data/spec/support/helpers/request_spec_helper.rb +14 -2
  92. data/spec/validators/redirect_uri_validator_spec.rb +40 -15
  93. metadata +15 -13
  94. data/.coveralls.yml +0 -1
  95. data/.github/ISSUE_TEMPLATE.md +0 -25
  96. data/.github/PULL_REQUEST_TEMPLATE.md +0 -17
  97. data/.gitignore +0 -20
  98. data/.gitlab-ci.yml +0 -16
  99. data/.hound.yml +0 -3
  100. data/.rspec +0 -1
  101. data/.rubocop.yml +0 -50
  102. data/.travis.yml +0 -35
  103. data/app/validators/redirect_uri_validator.rb +0 -50
@@ -7,7 +7,7 @@ module Doorkeeper
7
7
  # @see https://tools.ietf.org/html/rfc7662
8
8
  class TokenIntrospection
9
9
  attr_reader :server, :token
10
- attr_reader :error
10
+ attr_reader :error, :invalid_request_reason
11
11
 
12
12
  def initialize(server, token)
13
13
  @server = server
@@ -25,6 +25,8 @@ module Doorkeeper
25
25
 
26
26
  if @error == :invalid_token
27
27
  OAuth::InvalidTokenResponse.from_access_token(authorized_token)
28
+ elsif @error == :invalid_request
29
+ OAuth::InvalidRequestResponse.from_request(self)
28
30
  else
29
31
  OAuth::ErrorResponse.new(name: @error)
30
32
  end
@@ -67,9 +69,10 @@ module Doorkeeper
67
69
  # HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
68
70
  # Usage [RFC6750].
69
71
  #
70
- @error = :invalid_token if authorized_token_matches_introspected? || !authorized_token.accessible?
72
+ @error = :invalid_token unless valid_authorized_token?
71
73
  else
72
74
  @error = :invalid_request
75
+ @invalid_request_reason = :request_not_authorized
73
76
  end
74
77
  end
75
78
 
@@ -80,8 +83,7 @@ module Doorkeeper
80
83
 
81
84
  # Bearer Token Authentication
82
85
  def authorized_token
83
- @authorized_token ||=
84
- OAuth::Token.authenticate(server.context.request, :from_bearer_authorization)
86
+ @authorized_token ||= Doorkeeper.authenticate(server.context.request)
85
87
  end
86
88
 
87
89
  # 2.2. Introspection Response
@@ -150,7 +152,7 @@ module Doorkeeper
150
152
  #
151
153
  def active?
152
154
  if authorized_client
153
- valid_token? && authorized_for_client?
155
+ valid_token? && token_introspection_allowed?(auth_client: authorized_client.application)
154
156
  else
155
157
  valid_token?
156
158
  end
@@ -161,19 +163,27 @@ module Doorkeeper
161
163
  @token&.accessible?
162
164
  end
163
165
 
166
+ def valid_authorized_token?
167
+ !authorized_token_matches_introspected? &&
168
+ authorized_token.accessible? &&
169
+ token_introspection_allowed?(auth_token: authorized_token)
170
+ end
171
+
164
172
  # RFC7662 Section 2.1
165
173
  def authorized_token_matches_introspected?
166
174
  authorized_token.token == @token&.token
167
175
  end
168
176
 
169
- # If token doesn't belong to some client, then it is public.
170
- # Otherwise in it required for token to be connected to the same client.
171
- def authorized_for_client?
172
- if @token.application
173
- @token.application == authorized_client.application
174
- else
175
- true
176
- end
177
+ # config constraints for introspection in Doorkeeper.configuration.allow_token_introspection
178
+ def token_introspection_allowed?(auth_client: nil, auth_token: nil)
179
+ allow_introspection = Doorkeeper.configuration.allow_token_introspection
180
+ return allow_introspection unless allow_introspection.respond_to?(:call)
181
+
182
+ allow_introspection.call(
183
+ @token,
184
+ auth_client,
185
+ auth_token
186
+ )
177
187
  end
178
188
 
179
189
  # Allows to customize introspection response.
@@ -11,28 +11,14 @@ module Doorkeeper
11
11
  end
12
12
 
13
13
  def authorize
14
- if pre_auth.authorizable?
15
- auth = Authorization::Token.new(pre_auth, resource_owner)
16
- auth.issue_token
17
- @response = CodeResponse.new pre_auth,
18
- auth,
19
- response_on_fragment: true
20
- else
21
- @response = error_response
22
- end
14
+ auth = Authorization::Token.new(pre_auth, resource_owner)
15
+ auth.issue_token
16
+ CodeResponse.new(pre_auth, auth, response_on_fragment: true)
23
17
  end
24
18
 
25
19
  def deny
26
20
  pre_auth.error = :access_denied
27
- error_response
28
- end
29
-
30
- private
31
-
32
- def error_response
33
- ErrorResponse.from_request pre_auth,
34
- redirect_uri: pre_auth.redirect_uri,
35
- response_on_fragment: true
21
+ pre_auth.error_response
36
22
  end
37
23
  end
38
24
  end
@@ -16,7 +16,7 @@ module Doorkeeper
16
16
  :redirect_uri,
17
17
  presence: true
18
18
 
19
- validates :token, uniqueness: true
19
+ validates :token, uniqueness: { case_sensitive: true }
20
20
 
21
21
  before_validation :generate_token, on: :create
22
22
 
@@ -9,8 +9,8 @@ module Doorkeeper
9
9
  belongs_to :application, class_name: "Doorkeeper::Application",
10
10
  inverse_of: :access_tokens, optional: true
11
11
 
12
- validates :token, presence: true, uniqueness: true
13
- validates :refresh_token, uniqueness: true, if: :use_refresh_token?
12
+ validates :token, presence: true, uniqueness: { case_sensitive: true }
13
+ validates :refresh_token, uniqueness: { case_sensitive: true }, if: :use_refresh_token?
14
14
 
15
15
  # @attr_writer [Boolean, nil] use_refresh_token
16
16
  # indicates the possibility of using refresh token
@@ -10,8 +10,8 @@ module Doorkeeper
10
10
  has_many :access_tokens, dependent: :delete_all, class_name: "Doorkeeper::AccessToken"
11
11
 
12
12
  validates :name, :secret, :uid, presence: true
13
- validates :uid, uniqueness: true
14
- validates :redirect_uri, redirect_uri: true
13
+ validates :uid, uniqueness: { case_sensitive: true }
14
+ validates :redirect_uri, "doorkeeper/redirect_uri": true
15
15
  validates :confidential, inclusion: { in: [true, false] }
16
16
 
17
17
  validate :scopes_match_configured, if: :enforce_scopes?
@@ -60,6 +60,12 @@ module Doorkeeper
60
60
  end
61
61
  end
62
62
 
63
+ def to_json(options)
64
+ serializable_hash(except: :secret)
65
+ .merge(secret: plaintext_secret)
66
+ .to_json(options)
67
+ end
68
+
63
69
  private
64
70
 
65
71
  def generate_uid
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri"
4
+
5
+ module Doorkeeper
6
+ # ActiveModel validator for redirect URI validation in according
7
+ # to OAuth standards and Doorkeeper configuration.
8
+ class RedirectUriValidator < ActiveModel::EachValidator
9
+ def validate_each(record, attribute, value)
10
+ if value.blank?
11
+ return if Doorkeeper.configuration.allow_blank_redirect_uri?(record)
12
+
13
+ record.errors.add(attribute, :blank)
14
+ else
15
+ value.split.each do |val|
16
+ next if oob_redirect_uri?(val)
17
+
18
+ uri = ::URI.parse(val)
19
+ record.errors.add(attribute, :forbidden_uri) if forbidden_uri?(uri)
20
+ record.errors.add(attribute, :fragment_present) unless uri.fragment.nil?
21
+ record.errors.add(attribute, :unspecified_scheme) if unspecified_scheme?(uri)
22
+ record.errors.add(attribute, :relative_uri) if relative_uri?(uri)
23
+ record.errors.add(attribute, :secured_uri) if invalid_ssl_uri?(uri)
24
+ end
25
+ end
26
+ rescue URI::InvalidURIError
27
+ record.errors.add(attribute, :invalid_uri)
28
+ end
29
+
30
+ private
31
+
32
+ def oob_redirect_uri?(uri)
33
+ Doorkeeper::OAuth::NonStandard::IETF_WG_OAUTH2_OOB_METHODS.include?(uri)
34
+ end
35
+
36
+ def forbidden_uri?(uri)
37
+ Doorkeeper.configuration.forbid_redirect_uri.call(uri)
38
+ end
39
+
40
+ def unspecified_scheme?(uri)
41
+ return true if uri.opaque.present?
42
+
43
+ %w[localhost].include?(uri.try(:scheme))
44
+ end
45
+
46
+ def relative_uri?(uri)
47
+ uri.scheme.nil? && uri.host.nil?
48
+ end
49
+
50
+ def invalid_ssl_uri?(uri)
51
+ forces_ssl = Doorkeeper.configuration.force_ssl_in_redirect_uri
52
+ non_https = uri.try(:scheme) == "http"
53
+
54
+ if forces_ssl.respond_to?(:call)
55
+ forces_ssl.call(uri) && non_https
56
+ else
57
+ forces_ssl && non_https
58
+ end
59
+ end
60
+ end
61
+ end
@@ -2,19 +2,27 @@
2
2
 
3
3
  require "active_support/lazy_load_hooks"
4
4
 
5
- require "doorkeeper/orm/active_record/stale_records_cleaner"
6
-
7
5
  module Doorkeeper
8
6
  module Orm
7
+ # ActiveRecord ORM for Doorkeeper entity models.
8
+ # Consists of three main OAuth entities:
9
+ # * Access Token
10
+ # * Access Grant
11
+ # * Application (client)
12
+ #
13
+ # Do a lazy loading of all the required and configured stuff.
14
+ #
9
15
  module ActiveRecord
10
16
  def self.initialize_models!
11
17
  lazy_load do
18
+ require "doorkeeper/orm/active_record/stale_records_cleaner"
19
+ require "doorkeeper/orm/active_record/redirect_uri_validator"
12
20
  require "doorkeeper/orm/active_record/access_grant"
13
21
  require "doorkeeper/orm/active_record/access_token"
14
22
  require "doorkeeper/orm/active_record/application"
15
23
 
16
24
  if Doorkeeper.configuration.active_record_options[:establish_connection]
17
- [Doorkeeper::AccessGrant, Doorkeeper::AccessToken, Doorkeeper::Application].each do |model|
25
+ Doorkeeper::Orm::ActiveRecord.models.each do |model|
18
26
  options = Doorkeeper.configuration.active_record_options[:establish_connection]
19
27
  model.establish_connection(options)
20
28
  end
@@ -33,6 +41,14 @@ module Doorkeeper
33
41
  def self.lazy_load(&block)
34
42
  ActiveSupport.on_load(:active_record, {}, &block)
35
43
  end
44
+
45
+ def self.models
46
+ [
47
+ Doorkeeper::AccessGrant,
48
+ Doorkeeper::AccessToken,
49
+ Doorkeeper::Application,
50
+ ]
51
+ end
36
52
  end
37
53
  end
38
54
  end
@@ -17,6 +17,8 @@ module Doorkeeper
17
17
  private
18
18
 
19
19
  def grant
20
+ raise Errors::MissingRequiredParameter, :code if parameters[:code].blank?
21
+
20
22
  AccessGrant.by_token(parameters[:code])
21
23
  end
22
24
  end
@@ -4,30 +4,25 @@ module Doorkeeper
4
4
  module Request
5
5
  class << self
6
6
  def authorization_strategy(response_type)
7
- get_strategy(response_type, authorization_response_types)
8
- rescue NameError
9
- raise Errors::InvalidAuthorizationStrategy
7
+ build_strategy_class(response_type)
10
8
  end
11
9
 
12
10
  def token_strategy(grant_type)
11
+ raise Errors::MissingRequiredParameter, :grant_type if grant_type.blank?
12
+
13
13
  get_strategy(grant_type, token_grant_types)
14
14
  rescue NameError
15
15
  raise Errors::InvalidTokenStrategy
16
16
  end
17
17
 
18
- def get_strategy(grant_or_request_type, available)
19
- raise Errors::MissingRequestStrategy if grant_or_request_type.blank?
20
- raise NameError unless available.include?(grant_or_request_type.to_s)
18
+ def get_strategy(grant_type, available)
19
+ raise NameError unless available.include?(grant_type.to_s)
21
20
 
22
- build_strategy_class(grant_or_request_type)
21
+ build_strategy_class(grant_type)
23
22
  end
24
23
 
25
24
  private
26
25
 
27
- def authorization_response_types
28
- Doorkeeper.configuration.authorization_response_types
29
- end
30
-
31
26
  def token_grant_types
32
27
  Doorkeeper.configuration.token_grant_types
33
28
  end
@@ -10,12 +10,12 @@ module Doorkeeper
10
10
 
11
11
  def authorization_request(strategy)
12
12
  klass = Request.authorization_strategy strategy
13
- klass.new self
13
+ klass.new(self)
14
14
  end
15
15
 
16
16
  def token_request(strategy)
17
17
  klass = Request.token_strategy strategy
18
- klass.new self
18
+ klass.new(self)
19
19
  end
20
20
 
21
21
  # TODO: context should be the request
@@ -27,10 +27,6 @@ module Doorkeeper
27
27
  @client ||= OAuth::Client.authenticate(credentials)
28
28
  end
29
29
 
30
- def client_via_uid
31
- @client_via_uid ||= OAuth::Client.find(parameters[:client_id])
32
- end
33
-
34
30
  def current_resource_owner
35
31
  context.send :current_resource_owner
36
32
  end
@@ -5,12 +5,16 @@ module Doorkeeper
5
5
  CLEANER_CLASS = "StaleRecordsCleaner"
6
6
 
7
7
  def self.for(base_scope)
8
- orm_adapter = "doorkeeper/orm/#{Doorkeeper.configuration.orm}".classify
8
+ orm_adapter = "doorkeeper/orm/#{configured_orm}".classify
9
9
 
10
10
  orm_cleaner = "#{orm_adapter}::#{CLEANER_CLASS}".constantize
11
11
  orm_cleaner.new(base_scope)
12
12
  rescue NameError
13
- raise Doorkeeper::Errors::NoOrmCleaner, "'#{Doorkeeper.configuration.orm}' ORM has no cleaner!"
13
+ raise Doorkeeper::Errors::NoOrmCleaner, "'#{configured_orm}' ORM has no cleaner!"
14
+ end
15
+
16
+ def self.configured_orm
17
+ Doorkeeper.configuration.orm
14
18
  end
15
19
 
16
20
  def self.new(base_scope)
@@ -8,7 +8,7 @@ module Doorkeeper
8
8
  module VERSION
9
9
  # Semantic versioning
10
10
  MAJOR = 5
11
- MINOR = 1
11
+ MINOR = 2
12
12
  TINY = 0
13
13
  PRE = nil
14
14
 
data/lib/doorkeeper.rb CHANGED
@@ -52,6 +52,8 @@ require "doorkeeper/oauth/token"
52
52
  require "doorkeeper/oauth/token_introspection"
53
53
  require "doorkeeper/oauth/invalid_token_response"
54
54
  require "doorkeeper/oauth/forbidden_token_response"
55
+ require "doorkeeper/oauth/invalid_request_response"
56
+ require "doorkeeper/oauth/nonstandard"
55
57
 
56
58
  require "doorkeeper/secret_storing/base"
57
59
  require "doorkeeper/secret_storing/plain"
@@ -80,6 +82,8 @@ require "doorkeeper/stale_records_cleaner"
80
82
 
81
83
  require "doorkeeper/orm/active_record"
82
84
 
85
+ # Main Doorkeeper namespace.
86
+ #
83
87
  module Doorkeeper
84
88
  def self.authenticate(request, methods = Doorkeeper.configuration.access_token_methods)
85
89
  OAuth::Token.authenticate(request, *methods)
@@ -17,12 +17,12 @@ module Doorkeeper
17
17
  end
18
18
 
19
19
  def previous_refresh_token
20
- if no_previous_refresh_token_column?
21
- migration_template(
22
- "add_previous_refresh_token_to_access_tokens.rb.erb",
23
- "db/migrate/add_previous_refresh_token_to_access_tokens.rb"
24
- )
25
- end
20
+ return unless no_previous_refresh_token_column?
21
+
22
+ migration_template(
23
+ "add_previous_refresh_token_to_access_tokens.rb.erb",
24
+ "db/migrate/add_previous_refresh_token_to_access_tokens.rb"
25
+ )
26
26
  end
27
27
 
28
28
  private
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  Doorkeeper.configure do
4
- # Change the ORM that doorkeeper will use (needs plugins)
4
+ # Change the ORM that doorkeeper will use (requires ORM extensions installed).
5
+ # Check the list of supported ORMs here: https://github.com/doorkeeper-gem/doorkeeper#orms
5
6
  orm :active_record
6
7
 
7
8
  # This block will be called to check whether the resource owner is authenticated or not.
@@ -9,7 +10,7 @@ Doorkeeper.configure do
9
10
  raise "Please configure doorkeeper resource_owner_authenticator block located in #{__FILE__}"
10
11
  # Put your resource owner authentication logic here.
11
12
  # Example implementation:
12
- # User.find_by_id(session[:user_id]) || redirect_to(new_user_session_url)
13
+ # User.find_by(id: session[:user_id]) || redirect_to(new_user_session_url)
13
14
  end
14
15
 
15
16
  # If you didn't skip applications controller from Doorkeeper routes in your application routes.rb
@@ -39,18 +40,18 @@ Doorkeeper.configure do
39
40
  #
40
41
  # enforce_content_type
41
42
 
42
- # Authorization Code expiration time (default 10 minutes).
43
+ # Authorization Code expiration time (default: 10 minutes).
43
44
  #
44
45
  # authorization_code_expires_in 10.minutes
45
46
 
46
- # Access token expiration time (default 2 hours).
47
- # If you want to disable expiration, set this to nil.
47
+ # Access token expiration time (default: 2 hours).
48
+ # If you want to disable expiration, set this to `nil`.
48
49
  #
49
50
  # access_token_expires_in 2.hours
50
51
 
51
52
  # Assign custom TTL for access tokens. Will be used instead of access_token_expires_in
52
53
  # option if defined. In case the block returns `nil` value Doorkeeper fallbacks to
53
- # `access_token_expires_in` configuration option value. If you really need to issue a
54
+ # +access_token_expires_in+ configuration option value. If you really need to issue a
54
55
  # non-expiring access token (which is not recommended) then you need to return
55
56
  # Float::INFINITY from this block.
56
57
  #
@@ -65,12 +66,13 @@ Doorkeeper.configure do
65
66
  # end
66
67
 
67
68
  # Use a custom class for generating the access token.
68
- # See https://github.com/doorkeeper-gem/doorkeeper#custom-access-token-generator
69
+ # See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-access-token-generator
69
70
  #
70
71
  # access_token_generator '::Doorkeeper::JWT'
71
72
 
72
- # The controller Doorkeeper::ApplicationController inherits from.
73
- # Defaults to ActionController::Base.
73
+ # The controller +Doorkeeper::ApplicationController+ inherits from.
74
+ # Defaults to +ActionController::Base+ unless +api_only+ is set, which changes the default to
75
+ # +ActionController::API+. The return value of this option must be a stringified class name.
74
76
  # See https://doorkeeper.gitbook.io/guides/configuration/other-configurations#custom-base-controller
75
77
  #
76
78
  # base_controller 'ApplicationController'
@@ -128,11 +130,10 @@ Doorkeeper.configure do
128
130
  #
129
131
  # hash_application_secrets using: '::Doorkeeper::SecretStoring::BCrypt'
130
132
 
131
- # When the above option is enabled,
132
- # and a hashed token or secret is not found,
133
- # you can allow to fall back to another strategy.
134
- # For users upgrading doorkeeper and wishing to enable hashing,
135
- # you will probably want to enable the fallback to plain tokens.
133
+ # When the above option is enabled, and a hashed token or secret is not found,
134
+ # you can allow to fall back to another strategy. For users upgrading
135
+ # doorkeeper and wishing to enable hashing, you will probably want to enable
136
+ # the fallback to plain tokens.
136
137
  #
137
138
  # This will ensure that old access tokens and secrets
138
139
  # will remain valid even if the hashing above is enabled.
@@ -141,8 +142,8 @@ Doorkeeper.configure do
141
142
 
142
143
  # Issue access tokens with refresh token (disabled by default), you may also
143
144
  # pass a block which accepts `context` to customize when to give a refresh
144
- # token or not. Similar to `custom_access_token_expires_in`, `context` has
145
- # the properties:
145
+ # token or not. Similar to +custom_access_token_expires_in+, `context` has
146
+ # the following properties:
146
147
  #
147
148
  # `client` - the OAuth client application (see Doorkeeper::OAuth::Client)
148
149
  # `grant_type` - the grant type of the request (see Doorkeeper::OAuth)
@@ -151,7 +152,7 @@ Doorkeeper.configure do
151
152
  # use_refresh_token
152
153
 
153
154
  # Provide support for an owner to be assigned to each registered application (disabled by default)
154
- # Optional parameter confirmation: true (default false) if you want to enforce ownership of
155
+ # Optional parameter confirmation: true (default: false) if you want to enforce ownership of
155
156
  # a registered application
156
157
  # NOTE: you must also run the rails g doorkeeper:application_owner generator
157
158
  # to provide the necessary support
@@ -160,22 +161,22 @@ Doorkeeper.configure do
160
161
 
161
162
  # Define access token scopes for your provider
162
163
  # For more information go to
163
- # https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes
164
+ # https://doorkeeper.gitbook.io/guides/ruby-on-rails/scopes
164
165
  #
165
166
  # default_scopes :public
166
167
  # optional_scopes :write, :update
167
168
 
168
- # Define scopes_by_grant_type to restrict only certain scopes for grant_type
169
+ # Allows to restrict only certain scopes for grant_type.
169
170
  # By default, all the scopes will be available for all the grant types.
170
171
  #
171
172
  # Keys to this hash should be the name of grant_type and
172
173
  # values should be the array of scopes for that grant type.
173
- # Note: scopes should be from configured_scopes(i.e. deafult or optional)
174
+ # Note: scopes should be from configured_scopes (i.e. default or optional)
174
175
  #
175
176
  # scopes_by_grant_type password: [:write], client_credentials: [:update]
176
177
 
177
178
  # Forbids creating/updating applications with arbitrary scopes that are
178
- # not in configuration, i.e. `default_scopes` or `optional_scopes`.
179
+ # not in configuration, i.e. +default_scopes+ or +optional_scopes+.
179
180
  # (disabled by default)
180
181
  #
181
182
  # enforce_configured_scopes
@@ -196,15 +197,6 @@ Doorkeeper.configure do
196
197
  #
197
198
  # access_token_methods :from_bearer_authorization, :from_access_token_param, :from_bearer_param
198
199
 
199
- # Change the native redirect uri for client apps
200
- # When clients register with the following redirect uri, they won't be redirected to
201
- # any server and the authorizationcode will be displayed within the provider
202
- # The value can be any string. Use nil to disable this feature. When disabled, clients
203
- # must providea valid URL
204
- # (Similar behaviour: https://developers.google.com/accounts/docs/OAuth2InstalledApp#choosingredirecturi)
205
- #
206
- # native_redirect_uri 'urn:ietf:wg:oauth:2.0:oob'
207
-
208
200
  # Forces the usage of the HTTPS protocol in non-native redirect uris (enabled
209
201
  # by default in non-development environments). OAuth2 delegates security in
210
202
  # communication to the HTTPS protocol so it is wise to keep this enabled.
@@ -246,7 +238,7 @@ Doorkeeper.configure do
246
238
  # is invalid, expired, revoked or has invalid scopes.
247
239
  #
248
240
  # If you want to render error response yourself (i.e. rescue exceptions),
249
- # set handle_auth_errors to `:raise` and rescue Doorkeeper::Errors::InvalidToken
241
+ # set +handle_auth_errors+ to `:raise` and rescue Doorkeeper::Errors::InvalidToken
250
242
  # or following specific errors:
251
243
  #
252
244
  # Doorkeeper::Errors::TokenForbidden, Doorkeeper::Errors::TokenExpired,
@@ -290,6 +282,37 @@ Doorkeeper.configure do
290
282
  #
291
283
  # grant_flows %w[authorization_code client_credentials]
292
284
 
285
+ # Allows to customize OAuth grant flows that +each+ application support.
286
+ # You can configure a custom block (or use a class respond to `#call`) that must
287
+ # return `true` in case Application instance supports requested OAuth grant flow
288
+ # during the authorization request to the server. This configuration +doesn't+
289
+ # set flows per application, it only allows to check if application supports
290
+ # specific grant flow.
291
+ #
292
+ # For example you can add an additional database column to `oauth_applications` table,
293
+ # say `t.array :grant_flows, default: []`, and store allowed grant flows that can
294
+ # be used with this application there. Then when authorization requested Doorkeeper
295
+ # will call this block to check if specific Application (passed with client_id and/or
296
+ # client_secret) is allowed to perform the request for the specific grant type
297
+ # (authorization, password, client_credentials, etc).
298
+ #
299
+ # Example of the block:
300
+ #
301
+ # ->(flow, client) { client.grant_flows.include?(flow) }
302
+ #
303
+ # In case this option invocation result is `false`, Doorkeeper server returns
304
+ # :unauthorized_client error and stops the request.
305
+ #
306
+ # @param allow_grant_flow_for_client [Proc] Block or any object respond to #call
307
+ # @return [Boolean] `true` if allow or `false` if forbid the request
308
+ #
309
+ # allow_grant_flow_for_client do |grant_flow, client|
310
+ # # `grant_flows` is an Array column with grant
311
+ # # flows that application supports
312
+ #
313
+ # client.grant_flows.include?(grant_flow)
314
+ # end
315
+
293
316
  # Hook into the strategies' request & response life-cycle in case your
294
317
  # application needs advanced customization or logging:
295
318
  #
@@ -305,7 +328,7 @@ Doorkeeper.configure do
305
328
  # or add any other functionality.
306
329
  #
307
330
  # before_successful_authorization do |controller|
308
- # Rails.logger.info(params.inspect)
331
+ # Rails.logger.info(controller.request.params.inspect)
309
332
  # end
310
333
  #
311
334
  # after_successful_authorization do |controller|
@@ -323,7 +346,61 @@ Doorkeeper.configure do
323
346
  # client.superapp? or resource_owner.admin?
324
347
  # end
325
348
 
326
- # WWW-Authenticate Realm (default "Doorkeeper").
349
+ # Configure custom constraints for the Token Introspection request.
350
+ # By default this configuration option allows to introspect a token by another
351
+ # token of the same application, OR to introspect the token that belongs to
352
+ # authorized client (from authenticated client) OR when token doesn't
353
+ # belong to any client (public token). Otherwise requester has no access to the
354
+ # introspection and it will return response as stated in the RFC.
355
+ #
356
+ # Block arguments:
357
+ #
358
+ # @param token [Doorkeeper::AccessToken]
359
+ # token to be introspected
360
+ #
361
+ # @param authorized_client [Doorkeeper::Application]
362
+ # authorized client (if request is authorized using Basic auth with
363
+ # Client Credentials for example)
364
+ #
365
+ # @param authorized_token [Doorkeeper::AccessToken]
366
+ # Bearer token used to authorize the request
367
+ #
368
+ # In case the block returns `nil` or `false` introspection responses with 401 status code
369
+ # when using authorized token to introspect, or you'll get 200 with { "active": false } body
370
+ # when using authorized client to introspect as stated in the
371
+ # RFC 7662 section 2.2. Introspection Response.
372
+ #
373
+ # Using with caution:
374
+ # Keep in mind that these three parameters pass to block can be nil as following case:
375
+ # `authorized_client` is nil if and only if `authorized_token` is present, and vice versa.
376
+ # `token` will be nil if and only if `authorized_token` is present.
377
+ # So remember to use `&` or check if it is present before calling method on
378
+ # them to make sure you doesn't get NoMethodError exception.
379
+ #
380
+ # You can define your custom check:
381
+ #
382
+ # allow_token_introspection do |token, authorized_client, authorized_token|
383
+ # if authorized_token
384
+ # # customize: require `introspection` scope
385
+ # authorized_token.application == token&.application ||
386
+ # authorized_token.scopes.include?("introspection")
387
+ # elsif token.application
388
+ # # `protected_resource` is a new database boolean column, for example
389
+ # authorized_client == token.application || authorized_client.protected_resource?
390
+ # else
391
+ # # public token (when token.application is nil, token doesn't belong to any application)
392
+ # true
393
+ # end
394
+ # end
395
+ #
396
+ # Or you can completely disable any token introspection:
397
+ #
398
+ # allow_token_introspection false
399
+ #
400
+ # If you need to block the request at all, then configure your routes.rb or web-server
401
+ # like nginx to forbid the request.
402
+
403
+ # WWW-Authenticate Realm (default: "Doorkeeper").
327
404
  #
328
405
  # realm "Doorkeeper"
329
406
  end