doorkeeper 5.7.1 → 5.8.1

Sign up to get free protection for your applications and to get access to all the features.
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