doorkeeper 5.8.0 → 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: f4907be020648eb5c1dbc6e596c31c72c4133740e849ee1345ff337a4ce01c56
4
- data.tar.gz: 831e491b48efe921e43065d393c6a785a9988e6057f1ed3e1e4f2e8626555e65
3
+ metadata.gz: 8364fc5d75f9cbe96cc3ef67c8010dde471eb51ced0cf328f9ca84705553976f
4
+ data.tar.gz: db817023f41b070185ae9d6fae32b9d9b0eb0fc7abf8bdd99961c80e8bece1dd
5
5
  SHA512:
6
- metadata.gz: 2f97a8c5d6749cea33b31737988b26271d1ad03f4bd8f003b3674e8e81159a44e6a54f5611b868a06a9a074995bcc47165f222aadcd961746cc43776ee993c57
7
- data.tar.gz: 3d2e13efa8bba0cedc4a63055d6ecb70f0af8d1dc0644047b4b1ecb3bc3bf5affd2a0a20d46989a4999b4361573c39ae72f516398c67ffe708512f0fd6e23011
6
+ metadata.gz: 940f6253760d9117390495e97fa270aa0337a7379d2070d2be5ce2a44cf8148f451ffe7a3ba0451ab88d1cbb5bd4242f6d4a7de90204cf2749a57bdeaa4005ed
7
+ data.tar.gz: 728ea65c1e37f7f77183e5528c441cf7b9c8a4493428bbafbfe7815dec4b227d8bd033e05c4ee2dde50b9cc252cad7241b5d287d2df28e6631f9ccada5c7afc5
data/CHANGELOG.md CHANGED
@@ -9,6 +9,13 @@ 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
+
12
19
  ## 5.8.0
13
20
 
14
21
  - [#1739] Add support for dynamic scopes
@@ -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
 
@@ -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)
@@ -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
 
@@ -70,10 +70,28 @@ module Doorkeeper
70
70
  end
71
71
  end
72
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.
73
79
  def &(other)
80
+ return allowed(other) if dynamic_scopes_enabled?
81
+
74
82
  self.class.from_array(all & to_array(other))
75
83
  end
76
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
+
77
95
  private
78
96
 
79
97
  def dynamic_scopes_enabled?
@@ -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
@@ -5,7 +5,7 @@ module Doorkeeper
5
5
  # Semantic versioning
6
6
  MAJOR = 5
7
7
  MINOR = 8
8
- TINY = 0
8
+ TINY = 1
9
9
  PRE = nil
10
10
 
11
11
  # Full version number
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"
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.8.0
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-10-31 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
@@ -326,6 +328,7 @@ metadata:
326
328
  source_code_uri: https://github.com/doorkeeper-gem/doorkeeper
327
329
  bug_tracker_uri: https://github.com/doorkeeper-gem/doorkeeper/issues
328
330
  documentation_uri: https://doorkeeper.gitbook.io/guides/
331
+ funding_uri: https://opencollective.com/doorkeeper-gem
329
332
  post_install_message: "Starting from 5.5.0 RC1 Doorkeeper requires client authentication
330
333
  for Resource Owner Password Grant\nas stated in the OAuth RFC. You have to create
331
334
  a new OAuth client (Doorkeeper::Application) if you didn't\nhave it before and use