doorkeeper 5.7.1 → 5.8.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: df8ee24bf06e6b24c9ee822c24abf45ce0424b93ff05361dcdff76c930fa3c5a
4
- data.tar.gz: 56e84b30480a60d02eea4b417f41c1cd6b322365bfce0e9fa31aad504def3807
3
+ metadata.gz: 8364fc5d75f9cbe96cc3ef67c8010dde471eb51ced0cf328f9ca84705553976f
4
+ data.tar.gz: db817023f41b070185ae9d6fae32b9d9b0eb0fc7abf8bdd99961c80e8bece1dd
5
5
  SHA512:
6
- metadata.gz: d25945505890cb67e1e2db1e0a7eb8d49cd8bcccf05d2732883df6ace7269fe4bbe3de491a563ea3e254e1ac16e2daa407f665078cf243f7131a26db00b39842
7
- data.tar.gz: 2269f220720be56f31928a1ab4180254058bc2b636994160db72030bc32f0a5db695e76b3186f6b0c24b8d77565bd4c49911d4f5a632b14c6bd57e213c278694
6
+ metadata.gz: 940f6253760d9117390495e97fa270aa0337a7379d2070d2be5ce2a44cf8148f451ffe7a3ba0451ab88d1cbb5bd4242f6d4a7de90204cf2749a57bdeaa4005ed
7
+ data.tar.gz: 728ea65c1e37f7f77183e5528c441cf7b9c8a4493428bbafbfe7815dec4b227d8bd033e05c4ee2dde50b9cc252cad7241b5d287d2df28e6631f9ccada5c7afc5
data/CHANGELOG.md CHANGED
@@ -9,6 +9,23 @@ User-visible changes worth mentioning.
9
9
 
10
10
  Add your entry here.
11
11
 
12
+ ## 5.8.1
13
+
14
+ - [#1752] Bump the range of supported Ruby and Rails versions
15
+ - [#1747] Fix unknown pkce method error when configured
16
+ - [#1744] Allow for expired refresh tokens to be revoked
17
+ - [#1754] Fix refresh tokens with dynamic scopes
18
+
19
+ ## 5.8.0
20
+
21
+ - [#1739] Add support for dynamic scopes
22
+ - [#1715] Fix token introspection invalid request reason
23
+ - [#1714] Fix `Doorkeeper::AccessToken.find_or_create_for` with empty scopes which raises NoMethodError
24
+ - [#1712] Add `Pragma: no-cache` to token response
25
+ - [#1726] Refactor token introspection class.
26
+ - [#1727] Allow to set null secret value for Applications if they are public.
27
+ - [#1735] Add `pkce_code_challenge_methods` config option.
28
+
12
29
  ## 5.7.1
13
30
 
14
31
  - [#1705] Add `force_pkce` option that requires non-confidential clients to use PKCE when requesting an access_token using an authorization code
@@ -113,19 +113,38 @@ module Doorkeeper
113
113
  # The authorization server responds with HTTP status code 200 if the token
114
114
  # has been revoked successfully or if the client submitted an invalid
115
115
  # token
116
- token.revoke if token&.accessible?
116
+ revocable_token.revoke if revocable_token.revocable?
117
117
  end
118
118
 
119
119
  def token
120
- @token ||=
120
+ revocable_token&.token
121
+ end
122
+
123
+ def revocable_token
124
+ return @revocable_token if defined? @revocable_token
125
+
126
+ @revocable_token =
121
127
  if params[:token_type_hint] == "refresh_token"
122
- Doorkeeper.config.access_token_model.by_refresh_token(params["token"])
128
+ refresh_token
123
129
  else
124
- Doorkeeper.config.access_token_model.by_token(params["token"]) ||
125
- Doorkeeper.config.access_token_model.by_refresh_token(params["token"])
130
+ access_token || refresh_token
126
131
  end
127
132
  end
128
133
 
134
+ def refresh_token
135
+ token = Doorkeeper.config.access_token_model.by_refresh_token(params["token"])
136
+ return unless token
137
+
138
+ RevocableTokens::RevocableRefreshToken.new(token)
139
+ end
140
+
141
+ def access_token
142
+ token = Doorkeeper.config.access_token_model.by_token(params["token"])
143
+ return unless token
144
+
145
+ RevocableTokens::RevocableAccessToken.new(token)
146
+ end
147
+
129
148
  def strategy
130
149
  @strategy ||= server.token_request(params[:grant_type])
131
150
  end
@@ -100,7 +100,10 @@ en:
100
100
  unauthorized_client: 'The client is not authorized to perform this request using this method.'
101
101
  access_denied: 'The resource owner or authorization server denied the request.'
102
102
  invalid_scope: 'The requested scope is invalid, unknown, or malformed.'
103
- invalid_code_challenge_method: 'The code challenge method must be plain or S256.'
103
+ invalid_code_challenge_method:
104
+ zero: 'The authorization server does not support PKCE as there are no accepted code_challenge_method values.'
105
+ one: 'The code_challenge_method must be %{challenge_methods}.'
106
+ other: 'The code_challenge_method must be one of %{challenge_methods}.'
104
107
  server_error: 'The authorization server encountered an unexpected condition which prevented it from fulfilling the request.'
105
108
  temporarily_unavailable: 'The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server.'
106
109
 
@@ -11,6 +11,7 @@ module Doorkeeper
11
11
  validate_reuse_access_token_value
12
12
  validate_token_reuse_limit
13
13
  validate_secret_strategies
14
+ validate_pkce_code_challenge_methods
14
15
  end
15
16
 
16
17
  private
@@ -48,6 +49,17 @@ module Doorkeeper
48
49
  )
49
50
  @token_reuse_limit = 100
50
51
  end
52
+
53
+ def validate_pkce_code_challenge_methods
54
+ return if pkce_code_challenge_methods.all? {|method| method =~ /^plain$|^S256$/ }
55
+
56
+ ::Rails.logger.warn(
57
+ "[DOORKEEPER] You have configured an invalid value for pkce_code_challenge_methods option. " \
58
+ "It will be set to default ['plain', 'S256']",
59
+ )
60
+
61
+ @pkce_code_challenge_methods = ['plain', 'S256']
62
+ end
51
63
  end
52
64
  end
53
65
  end
@@ -31,6 +31,16 @@ module Doorkeeper
31
31
  @config.instance_variable_set(:@confirm_application_owner, true)
32
32
  end
33
33
 
34
+ # Provide support for dynamic scopes (e.g. user:*) (disabled by default)
35
+ # Optional parameter delimiter (default ":") if you want to customize
36
+ # the delimiter separating the scope name and matching value.
37
+ #
38
+ # @param opts [Hash] the options to configure dynamic scopes
39
+ def enable_dynamic_scopes(opts = {})
40
+ @config.instance_variable_set(:@enable_dynamic_scopes, true)
41
+ @config.instance_variable_set(:@dynamic_scopes_delimiter, opts[:delimiter] || ':')
42
+ end
43
+
34
44
  # Define default access token scopes for your provider
35
45
  #
36
46
  # @param scopes [Array] Default set of access (OAuth::Scopes.new)
@@ -243,6 +253,7 @@ module Doorkeeper
243
253
  option :orm, default: :active_record
244
254
  option :native_redirect_uri, default: "urn:ietf:wg:oauth:2.0:oob", deprecated: true
245
255
  option :grant_flows, default: %w[authorization_code client_credentials]
256
+ option :pkce_code_challenge_methods, default: %w[plain S256]
246
257
  option :handle_auth_errors, default: :render
247
258
  option :token_lookup_batch_size, default: 10_000
248
259
  # Sets the token_reuse_limit
@@ -418,7 +429,7 @@ module Doorkeeper
418
429
  default: (lambda do |token, authorized_client, authorized_token|
419
430
  if authorized_token
420
431
  authorized_token.application == token&.application
421
- elsif token.application
432
+ elsif token&.application
422
433
  authorized_client == token.application
423
434
  else
424
435
  true
@@ -510,6 +521,14 @@ module Doorkeeper
510
521
  option_set? :enable_application_owner
511
522
  end
512
523
 
524
+ def enable_dynamic_scopes?
525
+ option_set? :enable_dynamic_scopes
526
+ end
527
+
528
+ def dynamic_scopes_delimiter
529
+ @dynamic_scopes_delimiter
530
+ end
531
+
513
532
  def polymorphic_resource_owner?
514
533
  option_set? :polymorphic_resource_owner
515
534
  end
@@ -554,6 +573,12 @@ module Doorkeeper
554
573
  @scopes_by_grant_type ||= {}
555
574
  end
556
575
 
576
+ def pkce_code_challenge_methods_supported
577
+ return [] unless access_grant_model.pkce_supported?
578
+
579
+ pkce_code_challenge_methods
580
+ end
581
+
557
582
  def client_credentials_methods
558
583
  @client_credentials_methods ||= %i[from_basic from_params]
559
584
  end
@@ -6,6 +6,10 @@ module Doorkeeper
6
6
  def type
7
7
  message
8
8
  end
9
+
10
+ def self.translate_options
11
+ {}
12
+ end
9
13
  end
10
14
 
11
15
  class InvalidGrantReuse < DoorkeeperError
@@ -45,6 +49,16 @@ module Doorkeeper
45
49
  end
46
50
  end
47
51
 
52
+ class InvalidCodeChallengeMethod < BaseResponseError
53
+ def self.translate_options
54
+ challenge_methods = Doorkeeper.config.pkce_code_challenge_methods_supported
55
+ {
56
+ challenge_methods: challenge_methods.join(", "),
57
+ count: challenge_methods.length
58
+ }
59
+ end
60
+ end
61
+
48
62
  UnableToGenerateToken = Class.new(DoorkeeperError)
49
63
  TokenGeneratorNotFound = Class.new(DoorkeeperError)
50
64
  NoOrmCleaner = Class.new(DoorkeeperError)
@@ -55,7 +69,6 @@ module Doorkeeper
55
69
  InvalidScope = Class.new(BaseResponseError)
56
70
  InvalidRedirectUri = Class.new(BaseResponseError)
57
71
  InvalidCodeChallenge = Class.new(BaseResponseError)
58
- InvalidCodeChallengeMethod = Class.new(BaseResponseError)
59
72
  InvalidGrant = Class.new(BaseResponseError)
60
73
 
61
74
  UnauthorizedClient = Class.new(BaseResponseError)
@@ -214,6 +214,8 @@ module Doorkeeper
214
214
  # @return [Doorkeeper::AccessToken] existing record or a new one
215
215
  #
216
216
  def find_or_create_for(application:, resource_owner:, scopes:, **token_attributes)
217
+ scopes = Doorkeeper::OAuth::Scopes.from_string(scopes) if scopes.is_a?(String)
218
+
217
219
  if Doorkeeper.config.reuse_access_token
218
220
  custom_attributes = extract_custom_attributes(token_attributes).presence
219
221
  access_token = matching_token_for(
@@ -59,7 +59,8 @@ module Doorkeeper
59
59
  client_scopes = @client&.scopes
60
60
  return default_scopes if client_scopes.blank?
61
61
 
62
- default_scopes & client_scopes
62
+ # Avoid using Scope#& for dynamic scopes
63
+ client_scopes.allowed(default_scopes)
63
64
  end
64
65
  end
65
66
  end
@@ -2,13 +2,14 @@
2
2
 
3
3
  module Doorkeeper
4
4
  module OAuth
5
- Error = Struct.new(:name, :state) do
5
+ Error = Struct.new(:name, :state, :translate_options) do
6
6
  def description
7
- I18n.translate(
8
- name,
7
+ options = (translate_options || {}).merge(
9
8
  scope: %i[doorkeeper errors messages],
10
9
  default: :server_error,
11
10
  )
11
+
12
+ I18n.translate(name, **options)
12
13
  end
13
14
  end
14
15
  end
@@ -12,6 +12,7 @@ module Doorkeeper
12
12
  attributes.merge(
13
13
  name: error_name_for(request.error),
14
14
  exception_class: exception_class_for(request.error),
15
+ translate_options: request.error.try(:translate_options),
15
16
  state: request.try(:state),
16
17
  redirect_uri: request.try(:redirect_uri),
17
18
  ),
@@ -33,7 +34,7 @@ module Doorkeeper
33
34
  delegate :name, :description, :state, to: :@error
34
35
 
35
36
  def initialize(attributes = {})
36
- @error = OAuth::Error.new(*attributes.values_at(:name, :state))
37
+ @error = OAuth::Error.new(*attributes.values_at(:name, :state, :translate_options))
37
38
  @exception_class = attributes[:exception_class]
38
39
  @redirect_uri = attributes[:redirect_uri]
39
40
  @response_on_fragment = attributes[:response_on_fragment]
@@ -75,7 +75,7 @@ module Doorkeeper
75
75
  if client_scopes.blank?
76
76
  server.default_scopes.to_s
77
77
  else
78
- (server.default_scopes & client_scopes).to_s
78
+ server.default_scopes.allowed(client_scopes).to_s
79
79
  end
80
80
  end
81
81
 
@@ -154,7 +154,7 @@ module Doorkeeper
154
154
  return true unless Doorkeeper.config.access_grant_model.pkce_supported?
155
155
 
156
156
  code_challenge.blank? ||
157
- (code_challenge_method.present? && code_challenge_method =~ /^plain$|^S256$/)
157
+ (code_challenge_method.present? && Doorkeeper.config.pkce_code_challenge_methods_supported.include?(code_challenge_method))
158
158
  end
159
159
 
160
160
  def response_on_fragment?
@@ -6,6 +6,8 @@ module Doorkeeper
6
6
  include Enumerable
7
7
  include Comparable
8
8
 
9
+ DYNAMIC_SCOPE_WILDCARD = "*"
10
+
9
11
  def self.from_string(string)
10
12
  string ||= ""
11
13
  new.tap do |scope|
@@ -26,7 +28,15 @@ module Doorkeeper
26
28
  end
27
29
 
28
30
  def exists?(scope)
29
- @scopes.include? scope.to_s
31
+ scope = scope.to_s
32
+
33
+ @scopes.any? do |allowed_scope|
34
+ if dynamic_scopes_enabled? && dynamic_scopes_present?(allowed_scope, scope)
35
+ dynamic_scope_match?(allowed_scope, scope)
36
+ else
37
+ allowed_scope == scope
38
+ end
39
+ end
30
40
  end
31
41
 
32
42
  def add(*scopes)
@@ -60,12 +70,56 @@ module Doorkeeper
60
70
  end
61
71
  end
62
72
 
73
+ # DEPRECATED: With dynamic scopes, #allowed should be called because
74
+ # A & B doesn't really make sense with dynamic scopes.
75
+ #
76
+ # For example, if A = user:* and B is user:1, A & B = [].
77
+ # If we modified this method to take dynamic scopes into an account, then order
78
+ # becomes important, and this would violate the principle that A & B = B & A.
63
79
  def &(other)
80
+ return allowed(other) if dynamic_scopes_enabled?
81
+
64
82
  self.class.from_array(all & to_array(other))
65
83
  end
66
84
 
85
+ # Returns a set of scopes that are allowed, taking dynamic
86
+ # scopes into account. This instance's scopes is taken as the allowed set,
87
+ # and the passed value is the set to filter.
88
+ #
89
+ # @param other The set of scopes to filter
90
+ def allowed(other)
91
+ filtered_scopes = other.select { |scope| self.exists?(scope) }
92
+ self.class.from_array(filtered_scopes)
93
+ end
94
+
67
95
  private
68
96
 
97
+ def dynamic_scopes_enabled?
98
+ Doorkeeper.config.enable_dynamic_scopes?
99
+ end
100
+
101
+ def dynamic_scope_delimiter
102
+ return unless dynamic_scopes_enabled?
103
+
104
+ @dynamic_scope_delimiter ||= Doorkeeper.config.dynamic_scopes_delimiter
105
+ end
106
+
107
+ def dynamic_scopes_present?(allowed, requested)
108
+ allowed.include?(dynamic_scope_delimiter) && requested.include?(dynamic_scope_delimiter)
109
+ end
110
+
111
+ def dynamic_scope_match?(allowed, requested)
112
+ allowed_pattern = allowed.split(dynamic_scope_delimiter, 2)
113
+ request_pattern = requested.split(dynamic_scope_delimiter, 2)
114
+
115
+ return false if allowed_pattern[0] != request_pattern[0]
116
+ return false if allowed_pattern[1].blank?
117
+ return false if request_pattern[1].blank?
118
+ return true if allowed_pattern[1] == DYNAMIC_SCOPE_WILDCARD && allowed_pattern[1].present?
119
+
120
+ allowed_pattern[1] == request_pattern[1]
121
+ end
122
+
69
123
  def to_array(other)
70
124
  case other
71
125
  when Scopes
@@ -6,16 +6,15 @@ module Doorkeeper
6
6
  #
7
7
  # @see https://datatracker.ietf.org/doc/html/rfc7662
8
8
  class TokenIntrospection
9
- attr_reader :error
9
+ attr_reader :token, :error, :invalid_request_reason
10
10
 
11
11
  def initialize(server, token)
12
12
  @server = server
13
13
  @token = token
14
-
15
- authorize!
16
14
  end
17
15
 
18
16
  def authorized?
17
+ authorize!
19
18
  @error.blank?
20
19
  end
21
20
 
@@ -37,8 +36,7 @@ module Doorkeeper
37
36
 
38
37
  private
39
38
 
40
- attr_reader :server, :token
41
- attr_reader :invalid_request_reason
39
+ attr_reader :server
42
40
 
43
41
  # If the protected resource uses OAuth 2.0 client credentials to
44
42
  # authenticate to the introspection endpoint and its credentials are
@@ -60,24 +58,38 @@ module Doorkeeper
60
58
  def authorize!
61
59
  # Requested client authorization
62
60
  if server.credentials
63
- @error = Errors::InvalidClient unless authorized_client
61
+ authorize_using_basic_auth!
64
62
  elsif authorized_token
65
- # Requested bearer token authorization
66
- #
67
- # If the protected resource uses an OAuth 2.0 bearer token to authorize
68
- # its call to the introspection endpoint and the token used for
69
- # authorization does not contain sufficient privileges or is otherwise
70
- # invalid for this request, the authorization server responds with an
71
- # HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
72
- # Usage [RFC6750].
73
- #
74
- @error = Errors::InvalidToken unless valid_authorized_token?
63
+ authorize_using_bearer_token!
75
64
  else
76
65
  @error = Errors::InvalidRequest
77
66
  @invalid_request_reason = :request_not_authorized
78
67
  end
79
68
  end
80
69
 
70
+ def authorize_using_basic_auth!
71
+ # Note that a properly formed and authorized query for an inactive or
72
+ # otherwise invalid token (or a token the protected resource is not
73
+ # allowed to know about) is not considered an error response by this
74
+ # specification. In these cases, the authorization server MUST instead
75
+ # respond with an introspection response with the "active" field set to
76
+ # "false" as described in Section 2.2.
77
+ @error = Errors::InvalidClient unless authorized_client
78
+ end
79
+
80
+ def authorize_using_bearer_token!
81
+ # Requested bearer token authorization
82
+ #
83
+ # If the protected resource uses an OAuth 2.0 bearer token to authorize
84
+ # its call to the introspection endpoint and the token used for
85
+ # authorization does not contain sufficient privileges or is otherwise
86
+ # invalid for this request, the authorization server responds with an
87
+ # HTTP 401 code as described in Section 3 of OAuth 2.0 Bearer Token
88
+ # Usage [RFC6750].
89
+ #
90
+ @error = Errors::InvalidToken unless valid_authorized_token?
91
+ end
92
+
81
93
  # Client Authentication
82
94
  def authorized_client
83
95
  @authorized_client ||= server.credentials && server.client
@@ -30,6 +30,7 @@ module Doorkeeper
30
30
  {
31
31
  "Cache-Control" => "no-store, no-cache",
32
32
  "Content-Type" => "application/json; charset=utf-8",
33
+ "Pragma" => "no-cache",
33
34
  }
34
35
  end
35
36
  end
@@ -20,11 +20,13 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
20
20
  dependent: :delete_all,
21
21
  class_name: Doorkeeper.config.access_token_class.to_s
22
22
 
23
- validates :name, :secret, :uid, presence: true
23
+ validates :name, :uid, presence: true
24
+ validates :secret, presence: true, if: -> { secret_required? }
24
25
  validates :uid, uniqueness: { case_sensitive: true }
25
- validates_with Doorkeeper::RedirectUriValidator, attributes: [:redirect_uri]
26
26
  validates :confidential, inclusion: { in: [true, false] }
27
27
 
28
+ validates_with Doorkeeper::RedirectUriValidator, attributes: [:redirect_uri]
29
+
28
30
  validate :scopes_match_configured, if: :enforce_scopes?
29
31
 
30
32
  before_validation :generate_uid, :generate_secret, on: :create
@@ -118,7 +120,7 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
118
120
  end
119
121
 
120
122
  def generate_secret
121
- return if secret.present?
123
+ return if secret.present? || !secret_required?
122
124
 
123
125
  renew_secret
124
126
  end
@@ -136,6 +138,11 @@ module Doorkeeper::Orm::ActiveRecord::Mixins
136
138
  Doorkeeper.config.enforce_configured_scopes?
137
139
  end
138
140
 
141
+ def secret_required?
142
+ confidential? ||
143
+ !self.class.columns.detect { |column| column.name == "secret" }&.null
144
+ end
145
+
139
146
  # Helper method to extract collection of serializable attribute names
140
147
  # considering serialization options (like `only`, `except` and so on).
141
148
  #
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module RevocableTokens
5
+ class RevocableAccessToken
6
+ attr_reader :token
7
+
8
+ def initialize(token)
9
+ @token = token
10
+ end
11
+
12
+ def revocable?
13
+ token.accessible?
14
+ end
15
+
16
+ def revoke
17
+ token.revoke
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Doorkeeper
4
+ module RevocableTokens
5
+ class RevocableRefreshToken
6
+ attr_reader :token
7
+
8
+ def initialize(token)
9
+ @token = token
10
+ end
11
+
12
+ def revocable?
13
+ !token.revoked?
14
+ end
15
+
16
+ def revoke
17
+ token.revoke
18
+ end
19
+ end
20
+ end
21
+ end
@@ -4,7 +4,7 @@ module Doorkeeper
4
4
  module VERSION
5
5
  # Semantic versioning
6
6
  MAJOR = 5
7
- MINOR = 7
7
+ MINOR = 8
8
8
  TINY = 1
9
9
  PRE = nil
10
10
 
data/lib/doorkeeper.rb CHANGED
@@ -34,6 +34,11 @@ module Doorkeeper
34
34
  autoload :Token, "doorkeeper/request/token"
35
35
  end
36
36
 
37
+ module RevocableTokens
38
+ autoload :RevocableAccessToken, "doorkeeper/revocable_tokens/revocable_access_token"
39
+ autoload :RevocableRefreshToken, "doorkeeper/revocable_tokens/revocable_refresh_token"
40
+ end
41
+
37
42
  module OAuth
38
43
  autoload :BaseRequest, "doorkeeper/oauth/base_request"
39
44
  autoload :AuthorizationCodeRequest, "doorkeeper/oauth/authorization_code_request"
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "rails/generators"
4
+ require "rails/generators/active_record"
5
+
6
+ module Doorkeeper
7
+ # Generates migration with which drops NOT NULL constraint and allows not
8
+ # to bloat the database with redundant secret value.
9
+ #
10
+ class RemoveApplicationSecretNotNullConstraint < ::Rails::Generators::Base
11
+ include ::Rails::Generators::Migration
12
+ source_root File.expand_path("templates", __dir__)
13
+ desc "Removes NOT NULL constraint for OAuth2 applications."
14
+
15
+ def enable_polymorphic_resource_owner
16
+ migration_template(
17
+ "remove_applications_secret_not_null_constraint.rb.erb",
18
+ "db/migrate/remove_applications_secret_not_null_constraint.rb",
19
+ migration_version: migration_version,
20
+ )
21
+ end
22
+
23
+ def self.next_migration_number(dirname)
24
+ ActiveRecord::Generators::Base.next_migration_number(dirname)
25
+ end
26
+
27
+ private
28
+
29
+ def migration_version
30
+ "[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
31
+ end
32
+ end
33
+ end
@@ -5,6 +5,7 @@ class CreateDoorkeeperTables < ActiveRecord::Migration<%= migration_version %>
5
5
  create_table :oauth_applications do |t|
6
6
  t.string :name, null: false
7
7
  t.string :uid, null: false
8
+ # Remove `null: false` or use conditional constraint if you are planning to use public clients.
8
9
  t.string :secret, null: false
9
10
 
10
11
  # Remove `null: false` if you are planning to use grant flows
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ class RemoveApplicationsSecretNotNullConstraint < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ change_column_null :oauth_applications, :secret, true
6
+ end
7
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: doorkeeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.7.1
4
+ version: 5.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Felipe Elias Philipp
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2024-06-25 00:00:00.000000000 Z
14
+ date: 2024-12-09 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: railties
@@ -290,6 +290,8 @@ files:
290
290
  - lib/doorkeeper/request/refresh_token.rb
291
291
  - lib/doorkeeper/request/strategy.rb
292
292
  - lib/doorkeeper/request/token.rb
293
+ - lib/doorkeeper/revocable_tokens/revocable_access_token.rb
294
+ - lib/doorkeeper/revocable_tokens/revocable_refresh_token.rb
293
295
  - lib/doorkeeper/secret_storing/base.rb
294
296
  - lib/doorkeeper/secret_storing/bcrypt.rb
295
297
  - lib/doorkeeper/secret_storing/plain.rb
@@ -305,6 +307,7 @@ files:
305
307
  - lib/generators/doorkeeper/migration_generator.rb
306
308
  - lib/generators/doorkeeper/pkce_generator.rb
307
309
  - lib/generators/doorkeeper/previous_refresh_token_generator.rb
310
+ - lib/generators/doorkeeper/remove_applications_secret_not_null_constraint_generator.rb
308
311
  - lib/generators/doorkeeper/templates/README
309
312
  - lib/generators/doorkeeper/templates/add_confidential_to_applications.rb.erb
310
313
  - lib/generators/doorkeeper/templates/add_owner_to_application_migration.rb.erb
@@ -313,6 +316,7 @@ files:
313
316
  - lib/generators/doorkeeper/templates/enable_polymorphic_resource_owner_migration.rb.erb
314
317
  - lib/generators/doorkeeper/templates/initializer.rb
315
318
  - lib/generators/doorkeeper/templates/migration.rb.erb
319
+ - lib/generators/doorkeeper/templates/remove_applications_secret_not_null_constraint.rb.erb
316
320
  - lib/generators/doorkeeper/views_generator.rb
317
321
  - vendor/assets/stylesheets/doorkeeper/bootstrap.min.css
318
322
  homepage: https://github.com/doorkeeper-gem/doorkeeper
@@ -324,6 +328,7 @@ metadata:
324
328
  source_code_uri: https://github.com/doorkeeper-gem/doorkeeper
325
329
  bug_tracker_uri: https://github.com/doorkeeper-gem/doorkeeper/issues
326
330
  documentation_uri: https://doorkeeper.gitbook.io/guides/
331
+ funding_uri: https://opencollective.com/doorkeeper-gem
327
332
  post_install_message: "Starting from 5.5.0 RC1 Doorkeeper requires client authentication
328
333
  for Resource Owner Password Grant\nas stated in the OAuth RFC. You have to create
329
334
  a new OAuth client (Doorkeeper::Application) if you didn't\nhave it before and use
@@ -346,7 +351,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
346
351
  - !ruby/object:Gem::Version
347
352
  version: '0'
348
353
  requirements: []
349
- rubygems_version: 3.2.3
354
+ rubygems_version: 3.5.15
350
355
  signing_key:
351
356
  specification_version: 4
352
357
  summary: OAuth 2 provider for Rails and Grape