jwt 2.4.1 → 2.6.0

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.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +33 -2
  3. data/CONTRIBUTING.md +7 -7
  4. data/README.md +135 -31
  5. data/lib/jwt/algos/algo_wrapper.rb +30 -0
  6. data/lib/jwt/algos/ecdsa.rb +2 -4
  7. data/lib/jwt/algos/eddsa.rb +4 -4
  8. data/lib/jwt/algos/hmac.rb +54 -17
  9. data/lib/jwt/algos/hmac_rbnacl.rb +53 -0
  10. data/lib/jwt/algos/hmac_rbnacl_fixed.rb +52 -0
  11. data/lib/jwt/algos/none.rb +3 -1
  12. data/lib/jwt/algos/ps.rb +3 -5
  13. data/lib/jwt/algos/rsa.rb +3 -4
  14. data/lib/jwt/algos.rb +38 -15
  15. data/lib/jwt/base64.rb +19 -0
  16. data/lib/jwt/configuration/container.rb +21 -0
  17. data/lib/jwt/configuration/decode_configuration.rb +46 -0
  18. data/lib/jwt/configuration/jwk_configuration.rb +27 -0
  19. data/lib/jwt/configuration.rb +15 -0
  20. data/lib/jwt/decode.rb +48 -27
  21. data/lib/jwt/encode.rb +30 -20
  22. data/lib/jwt/jwk/ec.rb +131 -62
  23. data/lib/jwt/jwk/hmac.rb +59 -24
  24. data/lib/jwt/jwk/key_base.rb +43 -7
  25. data/lib/jwt/jwk/key_finder.rb +14 -34
  26. data/lib/jwt/jwk/kid_as_key_digest.rb +15 -0
  27. data/lib/jwt/jwk/rsa.rb +128 -53
  28. data/lib/jwt/jwk/set.rb +80 -0
  29. data/lib/jwt/jwk/thumbprint.rb +26 -0
  30. data/lib/jwt/jwk.rb +13 -11
  31. data/lib/jwt/security_utils.rb +0 -27
  32. data/lib/jwt/version.rb +23 -2
  33. data/lib/jwt/x5c_key_finder.rb +1 -1
  34. data/lib/jwt.rb +5 -4
  35. data/ruby-jwt.gemspec +8 -4
  36. metadata +15 -30
  37. data/.codeclimate.yml +0 -8
  38. data/.github/workflows/coverage.yml +0 -27
  39. data/.github/workflows/test.yml +0 -66
  40. data/.gitignore +0 -13
  41. data/.reek.yml +0 -22
  42. data/.rspec +0 -2
  43. data/.rubocop.yml +0 -67
  44. data/.sourcelevel.yml +0 -17
  45. data/Appraisals +0 -13
  46. data/Gemfile +0 -7
  47. data/Rakefile +0 -16
  48. data/lib/jwt/default_options.rb +0 -18
  49. data/lib/jwt/signature.rb +0 -35
data/lib/jwt/jwk/rsa.rb CHANGED
@@ -2,16 +2,33 @@
2
2
 
3
3
  module JWT
4
4
  module JWK
5
- class RSA < KeyBase
5
+ class RSA < KeyBase # rubocop:disable Metrics/ClassLength
6
6
  BINARY = 2
7
7
  KTY = 'RSA'
8
- KTYS = [KTY, OpenSSL::PKey::RSA].freeze
9
- RSA_KEY_ELEMENTS = %i[n e d p q dp dq qi].freeze
8
+ KTYS = [KTY, OpenSSL::PKey::RSA, JWT::JWK::RSA].freeze
9
+ RSA_PUBLIC_KEY_ELEMENTS = %i[kty n e].freeze
10
+ RSA_PRIVATE_KEY_ELEMENTS = %i[d p q dp dq qi].freeze
11
+ RSA_KEY_ELEMENTS = (RSA_PRIVATE_KEY_ELEMENTS + RSA_PUBLIC_KEY_ELEMENTS).freeze
10
12
 
11
- def initialize(keypair, kid = nil)
12
- raise ArgumentError, 'keypair must be of type OpenSSL::PKey::RSA' unless keypair.is_a?(OpenSSL::PKey::RSA)
13
+ RSA_OPT_PARAMS = %i[p q dp dq qi].freeze
14
+ RSA_ASN1_SEQUENCE = (%i[n e d] + RSA_OPT_PARAMS).freeze # https://www.rfc-editor.org/rfc/rfc3447#appendix-A.1.2
13
15
 
14
- super(keypair, kid || generate_kid(keypair.public_key))
16
+ def initialize(key, params = nil, options = {})
17
+ params ||= {}
18
+
19
+ # For backwards compatibility when kid was a String
20
+ params = { kid: params } if params.is_a?(String)
21
+
22
+ key_params = extract_key_params(key)
23
+
24
+ params = params.transform_keys(&:to_sym)
25
+ check_jwk(key_params, params)
26
+
27
+ super(options, key_params.merge(params))
28
+ end
29
+
30
+ def keypair
31
+ @keypair ||= self.class.create_rsa_key(jwk_attributes(*(RSA_KEY_ELEMENTS - [:kty])))
15
32
  end
16
33
 
17
34
  def private?
@@ -23,75 +40,124 @@ module JWT
23
40
  end
24
41
 
25
42
  def export(options = {})
26
- exported_hash = {
27
- kty: KTY,
28
- n: encode_open_ssl_bn(public_key.n),
29
- e: encode_open_ssl_bn(public_key.e),
30
- kid: kid
31
- }
32
-
33
- return exported_hash unless private? && options[:include_private] == true
34
-
35
- append_private_parts(exported_hash)
43
+ exported = parameters.clone
44
+ exported.reject! { |k, _| RSA_PRIVATE_KEY_ELEMENTS.include? k } unless private? && options[:include_private] == true
45
+ exported
36
46
  end
37
47
 
38
- private
48
+ def members
49
+ RSA_PUBLIC_KEY_ELEMENTS.each_with_object({}) { |i, h| h[i] = self[i] }
50
+ end
39
51
 
40
- def generate_kid(public_key)
52
+ def key_digest
41
53
  sequence = OpenSSL::ASN1::Sequence([OpenSSL::ASN1::Integer.new(public_key.n),
42
54
  OpenSSL::ASN1::Integer.new(public_key.e)])
43
55
  OpenSSL::Digest::SHA256.hexdigest(sequence.to_der)
44
56
  end
45
57
 
46
- def append_private_parts(the_hash)
47
- the_hash.merge(
48
- d: encode_open_ssl_bn(keypair.d),
49
- p: encode_open_ssl_bn(keypair.p),
50
- q: encode_open_ssl_bn(keypair.q),
51
- dp: encode_open_ssl_bn(keypair.dmp1),
52
- dq: encode_open_ssl_bn(keypair.dmq1),
53
- qi: encode_open_ssl_bn(keypair.iqmp)
54
- )
58
+ def []=(key, value)
59
+ if RSA_KEY_ELEMENTS.include?(key.to_sym)
60
+ raise ArgumentError, 'cannot overwrite cryptographic key attributes'
61
+ end
62
+
63
+ super(key, value)
64
+ end
65
+
66
+ private
67
+
68
+ def extract_key_params(key)
69
+ case key
70
+ when JWT::JWK::RSA
71
+ key.export(include_private: true)
72
+ when OpenSSL::PKey::RSA # Accept OpenSSL key as input
73
+ @keypair = key # Preserve the object to avoid recreation
74
+ parse_rsa_key(key)
75
+ when Hash
76
+ key.transform_keys(&:to_sym)
77
+ else
78
+ raise ArgumentError, 'key must be of type OpenSSL::PKey::RSA or Hash with key parameters'
79
+ end
80
+ end
81
+
82
+ def check_jwk(keypair, params)
83
+ raise ArgumentError, 'cannot overwrite cryptographic key attributes' unless (RSA_KEY_ELEMENTS & params.keys).empty?
84
+ raise JWT::JWKError, "Incorrect 'kty' value: #{keypair[:kty]}, expected #{KTY}" unless keypair[:kty] == KTY
85
+ raise JWT::JWKError, 'Key format is invalid for RSA' unless keypair[:n] && keypair[:e]
86
+ end
87
+
88
+ def parse_rsa_key(key)
89
+ {
90
+ kty: KTY,
91
+ n: encode_open_ssl_bn(key.n),
92
+ e: encode_open_ssl_bn(key.e),
93
+ d: encode_open_ssl_bn(key.d),
94
+ p: encode_open_ssl_bn(key.p),
95
+ q: encode_open_ssl_bn(key.q),
96
+ dp: encode_open_ssl_bn(key.dmp1),
97
+ dq: encode_open_ssl_bn(key.dmq1),
98
+ qi: encode_open_ssl_bn(key.iqmp)
99
+ }.compact
100
+ end
101
+
102
+ def jwk_attributes(*attributes)
103
+ attributes.each_with_object({}) do |attribute, hash|
104
+ hash[attribute] = decode_open_ssl_bn(self[attribute])
105
+ end
55
106
  end
56
107
 
57
108
  def encode_open_ssl_bn(key_part)
58
- Base64.urlsafe_encode64(key_part.to_s(BINARY), padding: false)
109
+ return unless key_part
110
+
111
+ ::JWT::Base64.url_encode(key_part.to_s(BINARY))
112
+ end
113
+
114
+ def decode_open_ssl_bn(jwk_data)
115
+ self.class.decode_open_ssl_bn(jwk_data)
59
116
  end
60
117
 
61
118
  class << self
62
119
  def import(jwk_data)
63
- pkey_params = jwk_attributes(jwk_data, *RSA_KEY_ELEMENTS) do |value|
64
- decode_open_ssl_bn(value)
65
- end
66
- kid = jwk_attributes(jwk_data, :kid)[:kid]
67
- new(rsa_pkey(pkey_params), kid)
120
+ new(jwk_data)
68
121
  end
69
122
 
70
- private
123
+ def decode_open_ssl_bn(jwk_data)
124
+ return nil unless jwk_data
71
125
 
72
- def jwk_attributes(jwk_data, *attributes)
73
- attributes.each_with_object({}) do |attribute, hash|
74
- value = jwk_data[attribute] || jwk_data[attribute.to_s]
75
- value = yield(value) if block_given?
76
- hash[attribute] = value
77
- end
126
+ OpenSSL::BN.new(::JWT::Base64.url_decode(jwk_data), BINARY)
78
127
  end
79
128
 
80
- def rsa_pkey(rsa_parameters)
81
- raise JWT::JWKError, 'Key format is invalid for RSA' unless rsa_parameters[:n] && rsa_parameters[:e]
129
+ def create_rsa_key_using_der(rsa_parameters)
130
+ validate_rsa_parameters!(rsa_parameters)
131
+
132
+ sequence = RSA_ASN1_SEQUENCE.each_with_object([]) do |key, arr|
133
+ next if rsa_parameters[key].nil?
134
+
135
+ arr << OpenSSL::ASN1::Integer.new(rsa_parameters[key])
136
+ end
137
+
138
+ if sequence.size > 2 # Append "two-prime" version for private key
139
+ sequence.unshift(OpenSSL::ASN1::Integer.new(0))
140
+
141
+ raise JWT::JWKError, 'Creating a RSA key with a private key requires the CRT parameters to be defined' if sequence.size < RSA_ASN1_SEQUENCE.size
142
+ end
82
143
 
83
- populate_key(OpenSSL::PKey::RSA.new, rsa_parameters)
144
+ OpenSSL::PKey::RSA.new(OpenSSL::ASN1::Sequence(sequence).to_der)
84
145
  end
85
146
 
86
- if OpenSSL::PKey::RSA.new.respond_to?(:set_key)
87
- def populate_key(rsa_key, rsa_parameters)
147
+ def create_rsa_key_using_sets(rsa_parameters)
148
+ validate_rsa_parameters!(rsa_parameters)
149
+
150
+ OpenSSL::PKey::RSA.new.tap do |rsa_key|
88
151
  rsa_key.set_key(rsa_parameters[:n], rsa_parameters[:e], rsa_parameters[:d])
89
152
  rsa_key.set_factors(rsa_parameters[:p], rsa_parameters[:q]) if rsa_parameters[:p] && rsa_parameters[:q]
90
153
  rsa_key.set_crt_params(rsa_parameters[:dp], rsa_parameters[:dq], rsa_parameters[:qi]) if rsa_parameters[:dp] && rsa_parameters[:dq] && rsa_parameters[:qi]
91
- rsa_key
92
154
  end
93
- else
94
- def populate_key(rsa_key, rsa_parameters)
155
+ end
156
+
157
+ def create_rsa_key_using_accessors(rsa_parameters) # rubocop:disable Metrics/AbcSize
158
+ validate_rsa_parameters!(rsa_parameters)
159
+
160
+ OpenSSL::PKey::RSA.new.tap do |rsa_key|
95
161
  rsa_key.n = rsa_parameters[:n]
96
162
  rsa_key.e = rsa_parameters[:e]
97
163
  rsa_key.d = rsa_parameters[:d] if rsa_parameters[:d]
@@ -100,15 +166,24 @@ module JWT
100
166
  rsa_key.dmp1 = rsa_parameters[:dp] if rsa_parameters[:dp]
101
167
  rsa_key.dmq1 = rsa_parameters[:dq] if rsa_parameters[:dq]
102
168
  rsa_key.iqmp = rsa_parameters[:qi] if rsa_parameters[:qi]
103
-
104
- rsa_key
105
169
  end
106
170
  end
107
171
 
108
- def decode_open_ssl_bn(jwk_data)
109
- return nil unless jwk_data
172
+ def validate_rsa_parameters!(rsa_parameters)
173
+ return unless rsa_parameters.key?(:d)
174
+
175
+ parameters = RSA_OPT_PARAMS - rsa_parameters.keys
176
+ return if parameters.empty? || parameters.size == RSA_OPT_PARAMS.size
110
177
 
111
- OpenSSL::BN.new(Base64.urlsafe_decode64(jwk_data), BINARY)
178
+ raise JWT::JWKError, 'When one of p, q, dp, dq or qi is given all the other optimization parameters also needs to be defined' # https://www.rfc-editor.org/rfc/rfc7518.html#section-6.3.2
179
+ end
180
+
181
+ if ::JWT.openssl_3?
182
+ alias create_rsa_key create_rsa_key_using_der
183
+ elsif OpenSSL::PKey::RSA.new.respond_to?(:set_key)
184
+ alias create_rsa_key create_rsa_key_using_sets
185
+ else
186
+ alias create_rsa_key create_rsa_key_using_accessors
112
187
  end
113
188
  end
114
189
  end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ module JWT
6
+ module JWK
7
+ class Set
8
+ include Enumerable
9
+ extend Forwardable
10
+
11
+ attr_reader :keys
12
+
13
+ def initialize(jwks = nil, options = {}) # rubocop:disable Metrics/CyclomaticComplexity
14
+ jwks ||= {}
15
+
16
+ @keys = case jwks
17
+ when JWT::JWK::Set # Simple duplication
18
+ jwks.keys
19
+ when JWT::JWK::KeyBase # Singleton
20
+ [jwks]
21
+ when Hash
22
+ jwks = jwks.transform_keys(&:to_sym)
23
+ [*jwks[:keys]].map { |k| JWT::JWK.new(k, nil, options) }
24
+ when Array
25
+ jwks.map { |k| JWT::JWK.new(k, nil, options) }
26
+ else
27
+ raise ArgumentError, 'Can only create new JWKS from Hash, Array and JWK'
28
+ end
29
+ end
30
+
31
+ def export(options = {})
32
+ { keys: @keys.map { |k| k.export(options) } }
33
+ end
34
+
35
+ def_delegators :@keys, :each, :size, :delete, :dig
36
+
37
+ def select!(&block)
38
+ return @keys.select! unless block
39
+
40
+ self if @keys.select!(&block)
41
+ end
42
+
43
+ def reject!(&block)
44
+ return @keys.reject! unless block
45
+
46
+ self if @keys.reject!(&block)
47
+ end
48
+
49
+ def uniq!(&block)
50
+ self if @keys.uniq!(&block)
51
+ end
52
+
53
+ def merge(enum)
54
+ @keys += JWT::JWK::Set.new(enum.to_a).keys
55
+ self
56
+ end
57
+
58
+ def union(enum)
59
+ dup.merge(enum)
60
+ end
61
+
62
+ def add(key)
63
+ @keys << JWT::JWK.new(key)
64
+ self
65
+ end
66
+
67
+ def ==(other)
68
+ other.is_a?(JWT::JWK::Set) && keys.sort == other.keys.sort
69
+ end
70
+
71
+ alias eql? ==
72
+ alias filter! select!
73
+ alias length size
74
+ # For symbolic manipulation
75
+ alias | union
76
+ alias + union
77
+ alias << add
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module JWK
5
+ # https://tools.ietf.org/html/rfc7638
6
+ class Thumbprint
7
+ attr_reader :jwk
8
+
9
+ def initialize(jwk)
10
+ @jwk = jwk
11
+ end
12
+
13
+ def generate
14
+ ::Base64.urlsafe_encode64(
15
+ Digest::SHA256.digest(
16
+ JWT::JSON.generate(
17
+ jwk.members.sort.to_h
18
+ )
19
+ ), padding: false
20
+ )
21
+ end
22
+
23
+ alias to_s generate
24
+ end
25
+ end
26
+ end
data/lib/jwt/jwk.rb CHANGED
@@ -1,23 +1,24 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'jwk/key_finder'
4
+ require_relative 'jwk/set'
4
5
 
5
6
  module JWT
6
7
  module JWK
7
8
  class << self
8
- def import(jwk_data)
9
- jwk_kty = jwk_data[:kty] || jwk_data['kty']
10
- raise JWT::JWKError, 'Key type (kty) not provided' unless jwk_kty
11
-
12
- mappings.fetch(jwk_kty.to_s) do |kty|
13
- raise JWT::JWKError, "Key type #{kty} not supported"
14
- end.import(jwk_data)
15
- end
9
+ def create_from(key, params = nil, options = {})
10
+ if key.is_a?(Hash)
11
+ jwk_kty = key[:kty] || key['kty']
12
+ raise JWT::JWKError, 'Key type (kty) not provided' unless jwk_kty
13
+
14
+ return mappings.fetch(jwk_kty.to_s) do |kty|
15
+ raise JWT::JWKError, "Key type #{kty} not supported"
16
+ end.new(key, params, options)
17
+ end
16
18
 
17
- def create_from(keypair, kid = nil)
18
- mappings.fetch(keypair.class) do |klass|
19
+ mappings.fetch(key.class) do |klass|
19
20
  raise JWT::JWKError, "Cannot create JWK from a #{klass.name}"
20
- end.new(keypair, kid)
21
+ end.new(key, params, options)
21
22
  end
22
23
 
23
24
  def classes
@@ -26,6 +27,7 @@ module JWT
26
27
  end
27
28
 
28
29
  alias new create_from
30
+ alias import create_from
29
31
 
30
32
  private
31
33
 
@@ -7,17 +7,6 @@ module JWT
7
7
  module SecurityUtils
8
8
  module_function
9
9
 
10
- def secure_compare(left, right)
11
- left_bytesize = left.bytesize
12
-
13
- return false unless left_bytesize == right.bytesize
14
-
15
- unpacked_left = left.unpack "C#{left_bytesize}"
16
- result = 0
17
- right.each_byte { |byte| result |= byte ^ unpacked_left.shift }
18
- result.zero?
19
- end
20
-
21
10
  def verify_rsa(algorithm, public_key, signing_input, signature)
22
11
  public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
23
12
  end
@@ -39,21 +28,5 @@ module JWT
39
28
  sig_char = signature[byte_size..-1] || ''
40
29
  OpenSSL::ASN1::Sequence.new([sig_bytes, sig_char].map { |int| OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(int, 2)) }).to_der
41
30
  end
42
-
43
- def rbnacl_fixup(algorithm, key)
44
- algorithm = algorithm.sub('HS', 'SHA').to_sym
45
-
46
- return [] unless defined?(RbNaCl) && RbNaCl::HMAC.constants(false).include?(algorithm)
47
-
48
- authenticator = RbNaCl::HMAC.const_get(algorithm)
49
-
50
- # Fall back to OpenSSL for keys larger than 32 bytes.
51
- return [] if key.bytesize > authenticator.key_bytes
52
-
53
- [
54
- authenticator,
55
- key.bytes.fill(0, key.bytesize...authenticator.key_bytes).pack('C*')
56
- ]
57
- end
58
31
  end
59
32
  end
data/lib/jwt/version.rb CHANGED
@@ -11,13 +11,34 @@ module JWT
11
11
  # major version
12
12
  MAJOR = 2
13
13
  # minor version
14
- MINOR = 4
14
+ MINOR = 6
15
15
  # tiny version
16
- TINY = 1
16
+ TINY = 0
17
17
  # alpha, beta, etc. tag
18
18
  PRE = nil
19
19
 
20
20
  # Build version string
21
21
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
22
22
  end
23
+
24
+ def self.openssl_3?
25
+ return false if OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
26
+ return true if OpenSSL::OPENSSL_VERSION_NUMBER >= 3 * 0x10000000
27
+ end
28
+
29
+ def self.rbnacl?
30
+ defined?(::RbNaCl)
31
+ end
32
+
33
+ def self.rbnacl_6_or_greater?
34
+ rbnacl? && ::Gem::Version.new(::RbNaCl::VERSION) >= ::Gem::Version.new('6.0.0')
35
+ end
36
+
37
+ def self.openssl_3_hmac_empty_key_regression?
38
+ openssl_3? && openssl_version <= ::Gem::Version.new('3.0.0')
39
+ end
40
+
41
+ def self.openssl_version
42
+ @openssl_version ||= ::Gem::Version.new(OpenSSL::VERSION)
43
+ end
23
44
  end
@@ -47,7 +47,7 @@ module JWT
47
47
  x5c_header_or_certificates
48
48
  else
49
49
  x5c_header_or_certificates.map do |encoded|
50
- OpenSSL::X509::Certificate.new(::Base64.strict_decode64(encoded))
50
+ OpenSSL::X509::Certificate.new(::JWT::Base64.url_decode(encoded))
51
51
  end
52
52
  end
53
53
  end
data/lib/jwt.rb CHANGED
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'base64'
3
+ require 'jwt/version'
4
+ require 'jwt/base64'
4
5
  require 'jwt/json'
5
6
  require 'jwt/decode'
6
- require 'jwt/default_options'
7
+ require 'jwt/configuration'
7
8
  require 'jwt/encode'
8
9
  require 'jwt/error'
9
10
  require 'jwt/jwk'
@@ -13,7 +14,7 @@ require 'jwt/jwk'
13
14
  # Should be up to date with the latest spec:
14
15
  # https://tools.ietf.org/html/rfc7519
15
16
  module JWT
16
- include JWT::DefaultOptions
17
+ extend ::JWT::Configuration
17
18
 
18
19
  module_function
19
20
 
@@ -25,6 +26,6 @@ module JWT
25
26
  end
26
27
 
27
28
  def decode(jwt, key = nil, verify = true, options = {}, &keyfinder) # rubocop:disable Style/OptionalBooleanParameter
28
- Decode.new(jwt, key, verify, DEFAULT_OPTIONS.merge(options), &keyfinder).decode_segments
29
+ Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments
29
30
  end
30
31
  end
data/ruby-jwt.gemspec CHANGED
@@ -18,18 +18,22 @@ Gem::Specification.new do |spec|
18
18
  spec.required_ruby_version = '>= 2.5'
19
19
  spec.metadata = {
20
20
  'bug_tracker_uri' => 'https://github.com/jwt/ruby-jwt/issues',
21
- 'changelog_uri' => "https://github.com/jwt/ruby-jwt/blob/v#{JWT.gem_version}/CHANGELOG.md"
21
+ 'changelog_uri' => "https://github.com/jwt/ruby-jwt/blob/v#{JWT.gem_version}/CHANGELOG.md",
22
+ 'rubygems_mfa_required' => 'true'
22
23
  }
23
24
 
24
- spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec|gemfiles|coverage|bin)/}) }
25
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
26
+ f.match(%r{^(spec|gemfiles|coverage|bin)/}) || # Irrelevant folders
27
+ f.match(/^\.+/) || # Files and folders starting with .
28
+ f.match(/^(Appraisals|Gemfile|Rakefile)$/) # Irrelevant files
29
+ end
30
+
25
31
  spec.executables = []
26
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
27
32
  spec.require_paths = %w[lib]
28
33
 
29
34
  spec.add_development_dependency 'appraisal'
30
35
  spec.add_development_dependency 'bundler'
31
36
  spec.add_development_dependency 'rake'
32
- spec.add_development_dependency 'reek'
33
37
  spec.add_development_dependency 'rspec'
34
38
  spec.add_development_dependency 'simplecov'
35
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jwt
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.4.1
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tim Rudat
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-07 00:00:00.000000000 Z
11
+ date: 2022-12-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: appraisal
@@ -52,20 +52,6 @@ dependencies:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: reek
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
56
  name: rspec
71
57
  requirement: !ruby/object:Gem::Requirement
@@ -101,35 +87,31 @@ executables: []
101
87
  extensions: []
102
88
  extra_rdoc_files: []
103
89
  files:
104
- - ".codeclimate.yml"
105
- - ".github/workflows/coverage.yml"
106
- - ".github/workflows/test.yml"
107
- - ".gitignore"
108
- - ".reek.yml"
109
- - ".rspec"
110
- - ".rubocop.yml"
111
- - ".sourcelevel.yml"
112
90
  - AUTHORS
113
- - Appraisals
114
91
  - CHANGELOG.md
115
92
  - CODE_OF_CONDUCT.md
116
93
  - CONTRIBUTING.md
117
- - Gemfile
118
94
  - LICENSE
119
95
  - README.md
120
- - Rakefile
121
96
  - lib/jwt.rb
122
97
  - lib/jwt/algos.rb
98
+ - lib/jwt/algos/algo_wrapper.rb
123
99
  - lib/jwt/algos/ecdsa.rb
124
100
  - lib/jwt/algos/eddsa.rb
125
101
  - lib/jwt/algos/hmac.rb
102
+ - lib/jwt/algos/hmac_rbnacl.rb
103
+ - lib/jwt/algos/hmac_rbnacl_fixed.rb
126
104
  - lib/jwt/algos/none.rb
127
105
  - lib/jwt/algos/ps.rb
128
106
  - lib/jwt/algos/rsa.rb
129
107
  - lib/jwt/algos/unsupported.rb
108
+ - lib/jwt/base64.rb
130
109
  - lib/jwt/claims_validator.rb
110
+ - lib/jwt/configuration.rb
111
+ - lib/jwt/configuration/container.rb
112
+ - lib/jwt/configuration/decode_configuration.rb
113
+ - lib/jwt/configuration/jwk_configuration.rb
131
114
  - lib/jwt/decode.rb
132
- - lib/jwt/default_options.rb
133
115
  - lib/jwt/encode.rb
134
116
  - lib/jwt/error.rb
135
117
  - lib/jwt/json.rb
@@ -138,9 +120,11 @@ files:
138
120
  - lib/jwt/jwk/hmac.rb
139
121
  - lib/jwt/jwk/key_base.rb
140
122
  - lib/jwt/jwk/key_finder.rb
123
+ - lib/jwt/jwk/kid_as_key_digest.rb
141
124
  - lib/jwt/jwk/rsa.rb
125
+ - lib/jwt/jwk/set.rb
126
+ - lib/jwt/jwk/thumbprint.rb
142
127
  - lib/jwt/security_utils.rb
143
- - lib/jwt/signature.rb
144
128
  - lib/jwt/verify.rb
145
129
  - lib/jwt/version.rb
146
130
  - lib/jwt/x5c_key_finder.rb
@@ -150,7 +134,8 @@ licenses:
150
134
  - MIT
151
135
  metadata:
152
136
  bug_tracker_uri: https://github.com/jwt/ruby-jwt/issues
153
- changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.4.1/CHANGELOG.md
137
+ changelog_uri: https://github.com/jwt/ruby-jwt/blob/v2.6.0/CHANGELOG.md
138
+ rubygems_mfa_required: 'true'
154
139
  post_install_message:
155
140
  rdoc_options: []
156
141
  require_paths:
data/.codeclimate.yml DELETED
@@ -1,8 +0,0 @@
1
- plugins:
2
- fixme:
3
- enabled: true
4
- shellcheck:
5
- enabled: true
6
- rubocop:
7
- enabled: true
8
- channel: rubocop-1-23-0
@@ -1,27 +0,0 @@
1
- ---
2
- name: coverage
3
- on:
4
- push:
5
- branches:
6
- - "master"
7
- jobs:
8
- coverage:
9
- name: coverage
10
- runs-on: ubuntu-20.04
11
- env:
12
- BUNDLE_GEMFILE: 'gemfiles/rbnacl.gemfile'
13
- CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
14
- steps:
15
- - uses: actions/checkout@v2
16
- - name: Install libsodium
17
- run: |
18
- sudo apt-get update -q
19
- sudo apt-get install libsodium-dev -y
20
- - name: Set up Ruby
21
- uses: ruby/setup-ruby@v1
22
- with:
23
- ruby-version: "2.7"
24
- bundler-cache: true
25
- - uses: paambaati/codeclimate-action@v3.0.0
26
- with:
27
- coverageCommand: bundle exec rspec