doorkeeper 5.8.0 → 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: 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