jwt 2.2.2 → 2.10.2

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 (80) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHORS +79 -44
  3. data/CHANGELOG.md +299 -5
  4. data/CODE_OF_CONDUCT.md +84 -0
  5. data/CONTRIBUTING.md +99 -0
  6. data/README.md +416 -107
  7. data/lib/jwt/base64.rb +19 -2
  8. data/lib/jwt/claims/audience.rb +30 -0
  9. data/lib/jwt/claims/crit.rb +35 -0
  10. data/lib/jwt/claims/decode_verifier.rb +40 -0
  11. data/lib/jwt/claims/expiration.rb +32 -0
  12. data/lib/jwt/claims/issued_at.rb +22 -0
  13. data/lib/jwt/claims/issuer.rb +34 -0
  14. data/lib/jwt/claims/jwt_id.rb +35 -0
  15. data/lib/jwt/claims/not_before.rb +32 -0
  16. data/lib/jwt/claims/numeric.rb +77 -0
  17. data/lib/jwt/claims/required.rb +33 -0
  18. data/lib/jwt/claims/subject.rb +30 -0
  19. data/lib/jwt/claims/verification_methods.rb +20 -0
  20. data/lib/jwt/claims/verifier.rb +61 -0
  21. data/lib/jwt/claims.rb +74 -0
  22. data/lib/jwt/claims_validator.rb +7 -22
  23. data/lib/jwt/configuration/container.rb +52 -0
  24. data/lib/jwt/configuration/decode_configuration.rb +70 -0
  25. data/lib/jwt/configuration/jwk_configuration.rb +28 -0
  26. data/lib/jwt/configuration.rb +23 -0
  27. data/lib/jwt/decode.rb +70 -57
  28. data/lib/jwt/deprecations.rb +49 -0
  29. data/lib/jwt/encode.rb +16 -54
  30. data/lib/jwt/encoded_token.rb +139 -0
  31. data/lib/jwt/error.rb +37 -0
  32. data/lib/jwt/json.rb +1 -1
  33. data/lib/jwt/jwa/compat.rb +32 -0
  34. data/lib/jwt/jwa/ecdsa.rb +90 -0
  35. data/lib/jwt/jwa/eddsa.rb +35 -0
  36. data/lib/jwt/jwa/hmac.rb +82 -0
  37. data/lib/jwt/jwa/hmac_rbnacl.rb +50 -0
  38. data/lib/jwt/jwa/hmac_rbnacl_fixed.rb +47 -0
  39. data/lib/jwt/jwa/none.rb +24 -0
  40. data/lib/jwt/jwa/ps.rb +35 -0
  41. data/lib/jwt/jwa/rsa.rb +35 -0
  42. data/lib/jwt/jwa/signing_algorithm.rb +63 -0
  43. data/lib/jwt/jwa/unsupported.rb +20 -0
  44. data/lib/jwt/jwa/wrapper.rb +44 -0
  45. data/lib/jwt/jwa.rb +58 -0
  46. data/lib/jwt/jwk/ec.rb +250 -0
  47. data/lib/jwt/jwk/hmac.rb +102 -0
  48. data/lib/jwt/jwk/key_base.rb +58 -0
  49. data/lib/jwt/jwk/key_finder.rb +20 -30
  50. data/lib/jwt/jwk/kid_as_key_digest.rb +16 -0
  51. data/lib/jwt/jwk/okp_rbnacl.rb +109 -0
  52. data/lib/jwt/jwk/rsa.rb +174 -26
  53. data/lib/jwt/jwk/set.rb +82 -0
  54. data/lib/jwt/jwk/thumbprint.rb +26 -0
  55. data/lib/jwt/jwk.rb +40 -15
  56. data/lib/jwt/token.rb +112 -0
  57. data/lib/jwt/verify.rb +16 -74
  58. data/lib/jwt/version.rb +52 -10
  59. data/lib/jwt/x5c_key_finder.rb +52 -0
  60. data/lib/jwt.rb +28 -4
  61. data/ruby-jwt.gemspec +20 -11
  62. metadata +61 -63
  63. data/.codeclimate.yml +0 -20
  64. data/.ebert.yml +0 -18
  65. data/.gitignore +0 -11
  66. data/.rspec +0 -1
  67. data/.rubocop.yml +0 -98
  68. data/.travis.yml +0 -29
  69. data/Appraisals +0 -18
  70. data/Gemfile +0 -3
  71. data/Rakefile +0 -11
  72. data/lib/jwt/algos/ecdsa.rb +0 -35
  73. data/lib/jwt/algos/eddsa.rb +0 -23
  74. data/lib/jwt/algos/hmac.rb +0 -34
  75. data/lib/jwt/algos/ps.rb +0 -43
  76. data/lib/jwt/algos/rsa.rb +0 -19
  77. data/lib/jwt/algos/unsupported.rb +0 -16
  78. data/lib/jwt/default_options.rb +0 -15
  79. data/lib/jwt/security_utils.rb +0 -57
  80. data/lib/jwt/signature.rb +0 -54
@@ -1,35 +0,0 @@
1
- module JWT
2
- module Algos
3
- module Ecdsa
4
- module_function
5
-
6
- SUPPORTED = %w[ES256 ES384 ES512].freeze
7
- NAMED_CURVES = {
8
- 'prime256v1' => 'ES256',
9
- 'secp384r1' => 'ES384',
10
- 'secp521r1' => 'ES512'
11
- }.freeze
12
-
13
- def sign(to_sign)
14
- algorithm, msg, key = to_sign.values
15
- key_algorithm = NAMED_CURVES[key.group.curve_name]
16
- if algorithm != key_algorithm
17
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} signing key was provided"
18
- end
19
-
20
- digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
21
- SecurityUtils.asn1_to_raw(key.dsa_sign_asn1(digest.digest(msg)), key)
22
- end
23
-
24
- def verify(to_verify)
25
- algorithm, public_key, signing_input, signature = to_verify.values
26
- key_algorithm = NAMED_CURVES[public_key.group.curve_name]
27
- if algorithm != key_algorithm
28
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} verification key was provided"
29
- end
30
- digest = OpenSSL::Digest.new(algorithm.sub('ES', 'sha'))
31
- public_key.dsa_verify_asn1(digest.digest(signing_input), SecurityUtils.raw_to_asn1(signature, public_key))
32
- end
33
- end
34
- end
35
- end
@@ -1,23 +0,0 @@
1
- module JWT
2
- module Algos
3
- module Eddsa
4
- module_function
5
-
6
- SUPPORTED = %w[ED25519].freeze
7
-
8
- def sign(to_sign)
9
- algorithm, msg, key = to_sign.values
10
- raise EncodeError, "Key given is a #{key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey" if key.class != RbNaCl::Signatures::Ed25519::SigningKey
11
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key.primitive} signing key was provided" if algorithm.downcase.to_sym != key.primitive
12
- key.sign(msg)
13
- end
14
-
15
- def verify(to_verify)
16
- algorithm, public_key, signing_input, signature = to_verify.values
17
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{public_key.primitive} verification key was provided" if algorithm.downcase.to_sym != public_key.primitive
18
- raise DecodeError, "key given is a #{public_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey" if public_key.class != RbNaCl::Signatures::Ed25519::VerifyKey
19
- public_key.verify(signature, signing_input)
20
- end
21
- end
22
- end
23
- end
@@ -1,34 +0,0 @@
1
- module JWT
2
- module Algos
3
- module Hmac
4
- module_function
5
-
6
- SUPPORTED = %w[HS256 HS512256 HS384 HS512].freeze
7
-
8
- def sign(to_sign)
9
- algorithm, msg, key = to_sign.values
10
- key ||= ''
11
- authenticator, padded_key = SecurityUtils.rbnacl_fixup(algorithm, key)
12
- if authenticator && padded_key
13
- authenticator.auth(padded_key, msg.encode('binary'))
14
- else
15
- OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
16
- end
17
- end
18
-
19
- def verify(to_verify)
20
- algorithm, public_key, signing_input, signature = to_verify.values
21
- authenticator, padded_key = SecurityUtils.rbnacl_fixup(algorithm, public_key)
22
- if authenticator && padded_key
23
- begin
24
- authenticator.verify(padded_key, signature.encode('binary'), signing_input.encode('binary'))
25
- rescue RbNaCl::BadAuthenticatorError
26
- false
27
- end
28
- else
29
- SecurityUtils.secure_compare(signature, sign(JWT::Signature::ToSign.new(algorithm, signing_input, public_key)))
30
- end
31
- end
32
- end
33
- end
34
- end
data/lib/jwt/algos/ps.rb DELETED
@@ -1,43 +0,0 @@
1
- module JWT
2
- module Algos
3
- module Ps
4
- # RSASSA-PSS signing algorithms
5
-
6
- module_function
7
-
8
- SUPPORTED = %w[PS256 PS384 PS512].freeze
9
-
10
- def sign(to_sign)
11
- require_openssl!
12
-
13
- algorithm, msg, key = to_sign.values
14
-
15
- key_class = key.class
16
-
17
- raise EncodeError, "The given key is a #{key_class}. It has to be an OpenSSL::PKey::RSA instance." if key_class == String
18
-
19
- translated_algorithm = algorithm.sub('PS', 'sha')
20
-
21
- key.sign_pss(translated_algorithm, msg, salt_length: :digest, mgf1_hash: translated_algorithm)
22
- end
23
-
24
- def verify(to_verify)
25
- require_openssl!
26
-
27
- SecurityUtils.verify_ps(to_verify.algorithm, to_verify.public_key, to_verify.signing_input, to_verify.signature)
28
- end
29
-
30
- def require_openssl!
31
- if Object.const_defined?('OpenSSL')
32
- major, minor = OpenSSL::VERSION.split('.').first(2)
33
-
34
- unless major.to_i >= 2 && minor.to_i >= 1
35
- raise JWT::RequiredDependencyError, "You currently have OpenSSL #{OpenSSL::VERSION}. PS support requires >= 2.1"
36
- end
37
- else
38
- raise JWT::RequiredDependencyError, 'PS signing requires OpenSSL +2.1'
39
- end
40
- end
41
- end
42
- end
43
- end
data/lib/jwt/algos/rsa.rb DELETED
@@ -1,19 +0,0 @@
1
- module JWT
2
- module Algos
3
- module Rsa
4
- module_function
5
-
6
- SUPPORTED = %w[RS256 RS384 RS512].freeze
7
-
8
- def sign(to_sign)
9
- algorithm, msg, key = to_sign.values
10
- raise EncodeError, "The given key is a #{key.class}. It has to be an OpenSSL::PKey::RSA instance." if key.class == String
11
- key.sign(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), msg)
12
- end
13
-
14
- def verify(to_verify)
15
- SecurityUtils.verify_rsa(to_verify.algorithm, to_verify.public_key, to_verify.signing_input, to_verify.signature)
16
- end
17
- end
18
- end
19
- end
@@ -1,16 +0,0 @@
1
- module JWT
2
- module Algos
3
- module Unsupported
4
- module_function
5
-
6
- SUPPORTED = Object.new.tap { |object| object.define_singleton_method(:include?) { |*| true } }
7
- def verify(*)
8
- raise JWT::VerificationError, 'Algorithm not supported'
9
- end
10
-
11
- def sign(*)
12
- raise NotImplementedError, 'Unsupported signing method'
13
- end
14
- end
15
- end
16
- end
@@ -1,15 +0,0 @@
1
- module JWT
2
- module DefaultOptions
3
- DEFAULT_OPTIONS = {
4
- verify_expiration: true,
5
- verify_not_before: true,
6
- verify_iss: false,
7
- verify_iat: false,
8
- verify_jti: false,
9
- verify_aud: false,
10
- verify_sub: false,
11
- leeway: 0,
12
- algorithms: ['HS256']
13
- }.freeze
14
- end
15
- end
@@ -1,57 +0,0 @@
1
- module JWT
2
- # Collection of security methods
3
- #
4
- # @see: https://github.com/rails/rails/blob/master/activesupport/lib/active_support/security_utils.rb
5
- module SecurityUtils
6
- module_function
7
-
8
- def secure_compare(left, right)
9
- left_bytesize = left.bytesize
10
-
11
- return false unless left_bytesize == right.bytesize
12
-
13
- unpacked_left = left.unpack "C#{left_bytesize}"
14
- result = 0
15
- right.each_byte { |byte| result |= byte ^ unpacked_left.shift }
16
- result.zero?
17
- end
18
-
19
- def verify_rsa(algorithm, public_key, signing_input, signature)
20
- public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
21
- end
22
-
23
- def verify_ps(algorithm, public_key, signing_input, signature)
24
- formatted_algorithm = algorithm.sub('PS', 'sha')
25
-
26
- public_key.verify_pss(formatted_algorithm, signature, signing_input, salt_length: :auto, mgf1_hash: formatted_algorithm)
27
- end
28
-
29
- def asn1_to_raw(signature, public_key)
30
- byte_size = (public_key.group.degree + 7) / 8
31
- OpenSSL::ASN1.decode(signature).value.map { |value| value.value.to_s(2).rjust(byte_size, "\x00") }.join
32
- end
33
-
34
- def raw_to_asn1(signature, private_key)
35
- byte_size = (private_key.group.degree + 7) / 8
36
- sig_bytes = signature[0..(byte_size - 1)]
37
- sig_char = signature[byte_size..-1] || ''
38
- OpenSSL::ASN1::Sequence.new([sig_bytes, sig_char].map { |int| OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(int, 2)) }).to_der
39
- end
40
-
41
- def rbnacl_fixup(algorithm, key)
42
- algorithm = algorithm.sub('HS', 'SHA').to_sym
43
-
44
- return [] unless defined?(RbNaCl) && RbNaCl::HMAC.constants(false).include?(algorithm)
45
-
46
- authenticator = RbNaCl::HMAC.const_get(algorithm)
47
-
48
- # Fall back to OpenSSL for keys larger than 32 bytes.
49
- return [] if key.bytesize > authenticator.key_bytes
50
-
51
- [
52
- authenticator,
53
- key.bytes.fill(0, key.bytesize...authenticator.key_bytes).pack('C*')
54
- ]
55
- end
56
- end
57
- end
data/lib/jwt/signature.rb DELETED
@@ -1,54 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'jwt/security_utils'
4
- require 'openssl'
5
- require 'jwt/algos/hmac'
6
- require 'jwt/algos/eddsa'
7
- require 'jwt/algos/ecdsa'
8
- require 'jwt/algos/rsa'
9
- require 'jwt/algos/ps'
10
- require 'jwt/algos/unsupported'
11
- begin
12
- require 'rbnacl'
13
- rescue LoadError
14
- raise if defined?(RbNaCl)
15
- end
16
-
17
- # JWT::Signature module
18
- module JWT
19
- # Signature logic for JWT
20
- module Signature
21
- extend self
22
- ALGOS = [
23
- Algos::Hmac,
24
- Algos::Ecdsa,
25
- Algos::Rsa,
26
- Algos::Eddsa,
27
- Algos::Ps,
28
- Algos::Unsupported
29
- ].freeze
30
- ToSign = Struct.new(:algorithm, :msg, :key)
31
- ToVerify = Struct.new(:algorithm, :public_key, :signing_input, :signature)
32
-
33
- def sign(algorithm, msg, key)
34
- algo = ALGOS.find do |alg|
35
- alg.const_get(:SUPPORTED).include? algorithm
36
- end
37
- algo.sign ToSign.new(algorithm, msg, key)
38
- end
39
-
40
- def verify(algorithm, key, signing_input, signature)
41
- raise JWT::DecodeError, 'No verification key available' unless key
42
-
43
- algo = ALGOS.find do |alg|
44
- alg.const_get(:SUPPORTED).include? algorithm
45
- end
46
- verified = algo.verify(ToVerify.new(algorithm, key, signing_input, signature))
47
- raise(JWT::VerificationError, 'Signature verification raised') unless verified
48
- rescue OpenSSL::PKey::PKeyError
49
- raise JWT::VerificationError, 'Signature verification raised'
50
- ensure
51
- OpenSSL.errors.clear
52
- end
53
- end
54
- end