jwt 2.8.2 → 2.9.3

Sign up to get free protection for your applications and to get access to all the features.
data/lib/jwt/encode.rb CHANGED
@@ -1,20 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'jwa'
4
- require_relative 'claims_validator'
5
4
 
6
5
  # JWT::Encode module
7
6
  module JWT
8
7
  # Encoding logic for JWT
9
8
  class Encode
10
- ALG_KEY = 'alg'
11
-
12
9
  def initialize(options)
13
10
  @payload = options[:payload]
14
11
  @key = options[:key]
15
- @algorithm = JWA.create(options[:algorithm])
12
+ @algorithm = JWA.resolve(options[:algorithm])
16
13
  @headers = options[:headers].transform_keys(&:to_s)
17
- @headers[ALG_KEY] = @algorithm.alg
18
14
  end
19
15
 
20
16
  def segments
@@ -41,7 +37,7 @@ module JWT
41
37
  end
42
38
 
43
39
  def encode_header
44
- encode_data(@headers)
40
+ encode_data(@headers.merge(@algorithm.header(signing_key: @key)))
45
41
  end
46
42
 
47
43
  def encode_payload
@@ -55,7 +51,7 @@ module JWT
55
51
  def validate_claims!
56
52
  return unless @payload.is_a?(Hash)
57
53
 
58
- ClaimsValidator.new(@payload).validate!
54
+ Claims.verify_payload!(@payload, :numeric)
59
55
  end
60
56
 
61
57
  def encode_signature
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module JWA
5
+ module Compat
6
+ module ClassMethods
7
+ def from_algorithm(algorithm)
8
+ new(algorithm)
9
+ end
10
+
11
+ def sign(algorithm, msg, key)
12
+ Deprecations.warning('Support for calling sign with positional arguments will be removed in future ruby-jwt versions')
13
+
14
+ from_algorithm(algorithm).sign(data: msg, signing_key: key)
15
+ end
16
+
17
+ def verify(algorithm, key, signing_input, signature)
18
+ Deprecations.warning('Support for calling verify with positional arguments will be removed in future ruby-jwt versions')
19
+
20
+ from_algorithm(algorithm).verify(data: signing_input, signature: signature, verification_key: key)
21
+ end
22
+ end
23
+
24
+ def self.included(klass)
25
+ klass.extend(ClassMethods)
26
+ end
27
+ end
28
+ end
29
+ end
data/lib/jwt/jwa/ecdsa.rb CHANGED
@@ -2,8 +2,35 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Ecdsa
6
- module_function
5
+ class Ecdsa
6
+ include JWT::JWA::SigningAlgorithm
7
+
8
+ def initialize(alg, digest)
9
+ @alg = alg
10
+ @digest = OpenSSL::Digest.new(digest)
11
+ end
12
+
13
+ def sign(data:, signing_key:)
14
+ curve_definition = curve_by_name(signing_key.group.curve_name)
15
+ key_algorithm = curve_definition[:algorithm]
16
+ if alg != key_algorithm
17
+ raise IncorrectAlgorithm, "payload algorithm is #{alg} but #{key_algorithm} signing key was provided"
18
+ end
19
+
20
+ asn1_to_raw(signing_key.dsa_sign_asn1(digest.digest(data)), signing_key)
21
+ end
22
+
23
+ def verify(data:, signature:, verification_key:)
24
+ curve_definition = curve_by_name(verification_key.group.curve_name)
25
+ key_algorithm = curve_definition[:algorithm]
26
+ if alg != key_algorithm
27
+ raise IncorrectAlgorithm, "payload algorithm is #{alg} but #{key_algorithm} verification key was provided"
28
+ end
29
+
30
+ verification_key.dsa_verify_asn1(digest.digest(data), raw_to_asn1(signature, verification_key))
31
+ rescue OpenSSL::PKey::PKeyError
32
+ raise JWT::VerificationError, 'Signature verification raised'
33
+ end
7
34
 
8
35
  NAMED_CURVES = {
9
36
  'prime256v1' => {
@@ -28,38 +55,28 @@ module JWT
28
55
  }
29
56
  }.freeze
30
57
 
31
- SUPPORTED = NAMED_CURVES.map { |_, c| c[:algorithm] }.uniq.freeze
32
-
33
- def sign(algorithm, msg, key)
34
- curve_definition = curve_by_name(key.group.curve_name)
35
- key_algorithm = curve_definition[:algorithm]
36
- if algorithm != key_algorithm
37
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} signing key was provided"
38
- end
39
-
40
- digest = OpenSSL::Digest.new(curve_definition[:digest])
41
- asn1_to_raw(key.dsa_sign_asn1(digest.digest(msg)), key)
58
+ NAMED_CURVES.each_value do |v|
59
+ register_algorithm(new(v[:algorithm], v[:digest]))
42
60
  end
43
61
 
44
- def verify(algorithm, public_key, signing_input, signature)
45
- curve_definition = curve_by_name(public_key.group.curve_name)
46
- key_algorithm = curve_definition[:algorithm]
47
- if algorithm != key_algorithm
48
- raise IncorrectAlgorithm, "payload algorithm is #{algorithm} but #{key_algorithm} verification key was provided"
49
- end
50
-
51
- digest = OpenSSL::Digest.new(curve_definition[:digest])
52
- public_key.dsa_verify_asn1(digest.digest(signing_input), raw_to_asn1(signature, public_key))
53
- rescue OpenSSL::PKey::PKeyError
54
- raise JWT::VerificationError, 'Signature verification raised'
62
+ def self.from_algorithm(algorithm)
63
+ new(algorithm, algorithm.downcase.gsub('es', 'sha'))
55
64
  end
56
65
 
57
- def curve_by_name(name)
66
+ def self.curve_by_name(name)
58
67
  NAMED_CURVES.fetch(name) do
59
68
  raise UnsupportedEcdsaCurve, "The ECDSA curve '#{name}' is not supported"
60
69
  end
61
70
  end
62
71
 
72
+ private
73
+
74
+ attr_reader :digest
75
+
76
+ def curve_by_name(name)
77
+ self.class.curve_by_name(name)
78
+ end
79
+
63
80
  def raw_to_asn1(signature, private_key)
64
81
  byte_size = (private_key.group.degree + 7) / 8
65
82
  sig_bytes = signature[0..(byte_size - 1)]
data/lib/jwt/jwa/eddsa.rb CHANGED
@@ -2,41 +2,33 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Eddsa
6
- SUPPORTED = %w[ED25519 EdDSA].freeze
7
- SUPPORTED_DOWNCASED = SUPPORTED.map(&:downcase).freeze
5
+ class Eddsa
6
+ include JWT::JWA::SigningAlgorithm
8
7
 
9
- class << self
10
- def sign(algorithm, msg, key)
11
- unless key.is_a?(RbNaCl::Signatures::Ed25519::SigningKey)
12
- raise EncodeError, "Key given is a #{key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey"
13
- end
14
-
15
- validate_algorithm!(algorithm)
8
+ def initialize(alg)
9
+ @alg = alg
10
+ end
16
11
 
17
- key.sign(msg)
12
+ def sign(data:, signing_key:)
13
+ unless signing_key.is_a?(RbNaCl::Signatures::Ed25519::SigningKey)
14
+ raise_encode_error!("Key given is a #{signing_key.class} but has to be an RbNaCl::Signatures::Ed25519::SigningKey")
18
15
  end
19
16
 
20
- def verify(algorithm, public_key, signing_input, signature)
21
- unless public_key.is_a?(RbNaCl::Signatures::Ed25519::VerifyKey)
22
- raise DecodeError, "key given is a #{public_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey"
23
- end
24
-
25
- validate_algorithm!(algorithm)
17
+ signing_key.sign(data)
18
+ end
26
19
 
27
- public_key.verify(signature, signing_input)
28
- rescue RbNaCl::CryptoError
29
- false
20
+ def verify(data:, signature:, verification_key:)
21
+ unless verification_key.is_a?(RbNaCl::Signatures::Ed25519::VerifyKey)
22
+ raise_decode_error!("key given is a #{verification_key.class} but has to be a RbNaCl::Signatures::Ed25519::VerifyKey")
30
23
  end
31
24
 
32
- private
33
-
34
- def validate_algorithm!(algorithm)
35
- return if SUPPORTED_DOWNCASED.include?(algorithm.downcase)
36
-
37
- raise IncorrectAlgorithm, "Algorithm #{algorithm} not supported. Supported algoritms are #{SUPPORTED.join(', ')}"
38
- end
25
+ verification_key.verify(signature, data)
26
+ rescue RbNaCl::CryptoError
27
+ false
39
28
  end
29
+
30
+ register_algorithm(new('ED25519'))
31
+ register_algorithm(new('EdDSA'))
40
32
  end
41
33
  end
42
34
  end
data/lib/jwt/jwa/hmac.rb CHANGED
@@ -2,35 +2,43 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Hmac
6
- module_function
5
+ class Hmac
6
+ include JWT::JWA::SigningAlgorithm
7
7
 
8
- MAPPING = {
9
- 'HS256' => OpenSSL::Digest::SHA256,
10
- 'HS384' => OpenSSL::Digest::SHA384,
11
- 'HS512' => OpenSSL::Digest::SHA512
12
- }.freeze
13
-
14
- SUPPORTED = MAPPING.keys
8
+ def self.from_algorithm(algorithm)
9
+ new(algorithm, OpenSSL::Digest.new(algorithm.downcase.gsub('hs', 'sha')))
10
+ end
15
11
 
16
- def sign(algorithm, msg, key)
17
- key ||= ''
12
+ def initialize(alg, digest)
13
+ @alg = alg
14
+ @digest = digest
15
+ end
18
16
 
19
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
17
+ def sign(data:, signing_key:)
18
+ signing_key ||= ''
19
+ raise_verify_error!('HMAC key expected to be a String') unless signing_key.is_a?(String)
20
20
 
21
- OpenSSL::HMAC.digest(MAPPING[algorithm].new, key, msg)
21
+ OpenSSL::HMAC.digest(digest.new, signing_key, data)
22
22
  rescue OpenSSL::HMACError => e
23
- if key == '' && e.message == 'EVP_PKEY_new_mac_key: malloc failure'
24
- raise JWT::DecodeError, 'OpenSSL 3.0 does not support nil or empty hmac_secret'
23
+ if signing_key == '' && e.message == 'EVP_PKEY_new_mac_key: malloc failure'
24
+ raise_verify_error!('OpenSSL 3.0 does not support nil or empty hmac_secret')
25
25
  end
26
26
 
27
27
  raise e
28
28
  end
29
29
 
30
- def verify(algorithm, key, signing_input, signature)
31
- SecurityUtils.secure_compare(signature, sign(algorithm, signing_input, key))
30
+ def verify(data:, signature:, verification_key:)
31
+ SecurityUtils.secure_compare(signature, sign(data: data, signing_key: verification_key))
32
32
  end
33
33
 
34
+ register_algorithm(new('HS256', OpenSSL::Digest::SHA256))
35
+ register_algorithm(new('HS384', OpenSSL::Digest::SHA384))
36
+ register_algorithm(new('HS512', OpenSSL::Digest::SHA512))
37
+
38
+ private
39
+
40
+ attr_reader :digest
41
+
34
42
  # Copy of https://github.com/rails/rails/blob/v7.0.3.1/activesupport/lib/active_support/security_utils.rb
35
43
  # rubocop:disable Naming/MethodParameterName, Style/StringLiterals, Style/NumericPredicate
36
44
  module SecurityUtils
@@ -1,49 +1,48 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWT
4
- module Algos
5
- module HmacRbNaCl
6
- MAPPING = { 'HS512256' => ::RbNaCl::HMAC::SHA512256 }.freeze
7
- SUPPORTED = MAPPING.keys
8
- class << self
9
- def sign(algorithm, msg, key)
10
- Deprecations.warning("The use of the algorithm #{algorithm} is deprecated and will be removed in the next major version of ruby-jwt")
11
- if (hmac = resolve_algorithm(algorithm))
12
- hmac.auth(key_for_rbnacl(hmac, key).encode('binary'), msg.encode('binary'))
13
- else
14
- Hmac.sign(algorithm, msg, key)
15
- end
16
- end
17
-
18
- def verify(algorithm, key, signing_input, signature)
19
- Deprecations.warning("The use of the algorithm #{algorithm} is deprecated and will be removed in the next major version of ruby-jwt")
20
- if (hmac = resolve_algorithm(algorithm))
21
- hmac.verify(key_for_rbnacl(hmac, key).encode('binary'), signature.encode('binary'), signing_input.encode('binary'))
22
- else
23
- Hmac.verify(algorithm, key, signing_input, signature)
24
- end
25
- rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
26
- false
27
- end
28
-
29
- private
30
-
31
- def key_for_rbnacl(hmac, key)
32
- key ||= ''
33
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
34
-
35
- return padded_empty_key(hmac.key_bytes) if key == ''
36
-
37
- key
38
- end
39
-
40
- def resolve_algorithm(algorithm)
41
- MAPPING.fetch(algorithm)
42
- end
43
-
44
- def padded_empty_key(length)
45
- Array.new(length, 0x0).pack('C*').encode('binary')
46
- end
4
+ module JWA
5
+ class HmacRbNaCl
6
+ include JWT::JWA::SigningAlgorithm
7
+
8
+ def self.from_algorithm(algorithm)
9
+ new(algorithm, ::RbNaCl::HMAC.const_get(algorithm.upcase.gsub('HS', 'SHA')))
10
+ end
11
+
12
+ def initialize(alg, hmac)
13
+ @alg = alg
14
+ @hmac = hmac
15
+ end
16
+
17
+ def sign(data:, signing_key:)
18
+ Deprecations.warning("The use of the algorithm #{alg} is deprecated and will be removed in the next major version of ruby-jwt")
19
+ hmac.auth(key_for_rbnacl(hmac, signing_key).encode('binary'), data.encode('binary'))
20
+ end
21
+
22
+ def verify(data:, signature:, verification_key:)
23
+ Deprecations.warning("The use of the algorithm #{alg} is deprecated and will be removed in the next major version of ruby-jwt")
24
+ hmac.verify(key_for_rbnacl(hmac, verification_key).encode('binary'), signature.encode('binary'), data.encode('binary'))
25
+ rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
26
+ false
27
+ end
28
+
29
+ register_algorithm(new('HS512256', ::RbNaCl::HMAC::SHA512256))
30
+
31
+ private
32
+
33
+ attr_reader :hmac
34
+
35
+ def key_for_rbnacl(hmac, key)
36
+ key ||= ''
37
+ raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
38
+
39
+ return padded_empty_key(hmac.key_bytes) if key == ''
40
+
41
+ key
42
+ end
43
+
44
+ def padded_empty_key(length)
45
+ Array.new(length, 0x0).pack('C*').encode('binary')
47
46
  end
48
47
  end
49
48
  end
@@ -1,45 +1,45 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module JWT
4
- module Algos
5
- module HmacRbNaClFixed
6
- MAPPING = { 'HS512256' => ::RbNaCl::HMAC::SHA512256 }.freeze
7
- SUPPORTED = MAPPING.keys
8
-
9
- class << self
10
- def sign(algorithm, msg, key)
11
- key ||= ''
12
- Deprecations.warning("The use of the algorithm #{algorithm} is deprecated and will be removed in the next major version of ruby-jwt")
13
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
14
-
15
- if (hmac = resolve_algorithm(algorithm)) && key.bytesize <= hmac.key_bytes
16
- hmac.auth(padded_key_bytes(key, hmac.key_bytes), msg.encode('binary'))
17
- else
18
- Hmac.sign(algorithm, msg, key)
19
- end
20
- end
21
-
22
- def verify(algorithm, key, signing_input, signature)
23
- key ||= ''
24
- Deprecations.warning("The use of the algorithm #{algorithm} is deprecated and will be removed in the next major version of ruby-jwt")
25
- raise JWT::DecodeError, 'HMAC key expected to be a String' unless key.is_a?(String)
26
-
27
- if (hmac = resolve_algorithm(algorithm)) && key.bytesize <= hmac.key_bytes
28
- hmac.verify(padded_key_bytes(key, hmac.key_bytes), signature.encode('binary'), signing_input.encode('binary'))
29
- else
30
- Hmac.verify(algorithm, key, signing_input, signature)
31
- end
32
- rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
33
- false
34
- end
35
-
36
- def resolve_algorithm(algorithm)
37
- MAPPING.fetch(algorithm)
38
- end
39
-
40
- def padded_key_bytes(key, bytesize)
41
- key.bytes.fill(0, key.bytesize...bytesize).pack('C*')
42
- end
4
+ module JWA
5
+ class HmacRbNaClFixed
6
+ include JWT::JWA::SigningAlgorithm
7
+
8
+ def self.from_algorithm(algorithm)
9
+ new(algorithm, ::RbNaCl::HMAC.const_get(algorithm.upcase.gsub('HS', 'SHA')))
10
+ end
11
+
12
+ def initialize(alg, hmac)
13
+ @alg = alg
14
+ @hmac = hmac
15
+ end
16
+
17
+ def sign(data:, signing_key:)
18
+ signing_key ||= ''
19
+ Deprecations.warning("The use of the algorithm #{alg} is deprecated and will be removed in the next major version of ruby-jwt")
20
+ raise JWT::DecodeError, 'HMAC key expected to be a String' unless signing_key.is_a?(String)
21
+
22
+ hmac.auth(padded_key_bytes(signing_key, hmac.key_bytes), data.encode('binary'))
23
+ end
24
+
25
+ def verify(data:, signature:, verification_key:)
26
+ verification_key ||= ''
27
+ Deprecations.warning("The use of the algorithm #{alg} is deprecated and will be removed in the next major version of ruby-jwt")
28
+ raise JWT::DecodeError, 'HMAC key expected to be a String' unless verification_key.is_a?(String)
29
+
30
+ hmac.verify(padded_key_bytes(verification_key, hmac.key_bytes), signature.encode('binary'), data.encode('binary'))
31
+ rescue ::RbNaCl::BadAuthenticatorError, ::RbNaCl::LengthError
32
+ false
33
+ end
34
+
35
+ register_algorithm(new('HS512256', ::RbNaCl::HMAC::SHA512256))
36
+
37
+ private
38
+
39
+ attr_reader :hmac
40
+
41
+ def padded_key_bytes(key, bytesize)
42
+ key.bytes.fill(0, key.bytesize...bytesize).pack('C*')
43
43
  end
44
44
  end
45
45
  end
data/lib/jwt/jwa/none.rb CHANGED
@@ -2,10 +2,12 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module None
6
- module_function
5
+ class None
6
+ include JWT::JWA::SigningAlgorithm
7
7
 
8
- SUPPORTED = %w[none].freeze
8
+ def initialize
9
+ @alg = 'none'
10
+ end
9
11
 
10
12
  def sign(*)
11
13
  ''
@@ -14,6 +16,8 @@ module JWT
14
16
  def verify(*)
15
17
  true
16
18
  end
19
+
20
+ register_algorithm(new)
17
21
  end
18
22
  end
19
23
  end
data/lib/jwt/jwa/ps.rb CHANGED
@@ -2,29 +2,35 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Ps
6
- # RSASSA-PSS signing algorithms
5
+ class Ps
6
+ include JWT::JWA::SigningAlgorithm
7
7
 
8
- module_function
9
-
10
- SUPPORTED = %w[PS256 PS384 PS512].freeze
8
+ def initialize(alg)
9
+ @alg = alg
10
+ @digest_algorithm = alg.sub('PS', 'sha')
11
+ end
11
12
 
12
- def sign(algorithm, msg, key)
13
- unless key.is_a?(::OpenSSL::PKey::RSA)
14
- raise EncodeError, "The given key is a #{key_class}. It has to be an OpenSSL::PKey::RSA instance."
13
+ def sign(data:, signing_key:)
14
+ unless signing_key.is_a?(::OpenSSL::PKey::RSA)
15
+ raise_sign_error!("The given key is a #{signing_key.class}. It has to be an OpenSSL::PKey::RSA instance.")
15
16
  end
16
17
 
17
- translated_algorithm = algorithm.sub('PS', 'sha')
18
-
19
- key.sign_pss(translated_algorithm, msg, salt_length: :digest, mgf1_hash: translated_algorithm)
18
+ signing_key.sign_pss(digest_algorithm, data, salt_length: :digest, mgf1_hash: digest_algorithm)
20
19
  end
21
20
 
22
- def verify(algorithm, public_key, signing_input, signature)
23
- translated_algorithm = algorithm.sub('PS', 'sha')
24
- public_key.verify_pss(translated_algorithm, signature, signing_input, salt_length: :auto, mgf1_hash: translated_algorithm)
21
+ def verify(data:, signature:, verification_key:)
22
+ verification_key.verify_pss(digest_algorithm, signature, data, salt_length: :auto, mgf1_hash: digest_algorithm)
25
23
  rescue OpenSSL::PKey::PKeyError
26
24
  raise JWT::VerificationError, 'Signature verification raised'
27
25
  end
26
+
27
+ register_algorithm(new('PS256'))
28
+ register_algorithm(new('PS384'))
29
+ register_algorithm(new('PS512'))
30
+
31
+ private
32
+
33
+ attr_reader :digest_algorithm
28
34
  end
29
35
  end
30
36
  end
data/lib/jwt/jwa/rsa.rb CHANGED
@@ -2,24 +2,35 @@
2
2
 
3
3
  module JWT
4
4
  module JWA
5
- module Rsa
6
- module_function
5
+ class Rsa
6
+ include JWT::JWA::SigningAlgorithm
7
7
 
8
- SUPPORTED = %w[RS256 RS384 RS512].freeze
8
+ def initialize(alg)
9
+ @alg = alg
10
+ @digest = OpenSSL::Digest.new(alg.sub('RS', 'SHA'))
11
+ end
9
12
 
10
- def sign(algorithm, msg, key)
11
- unless key.is_a?(OpenSSL::PKey::RSA)
12
- raise EncodeError, "The given key is a #{key.class}. It has to be an OpenSSL::PKey::RSA instance"
13
+ def sign(data:, signing_key:)
14
+ unless signing_key.is_a?(OpenSSL::PKey::RSA)
15
+ raise_sign_error!("The given key is a #{signing_key.class}. It has to be an OpenSSL::PKey::RSA instance")
13
16
  end
14
17
 
15
- key.sign(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), msg)
18
+ signing_key.sign(digest, data)
16
19
  end
17
20
 
18
- def verify(algorithm, public_key, signing_input, signature)
19
- public_key.verify(OpenSSL::Digest.new(algorithm.sub('RS', 'sha')), signature, signing_input)
21
+ def verify(data:, signature:, verification_key:)
22
+ verification_key.verify(digest, signature, data)
20
23
  rescue OpenSSL::PKey::PKeyError
21
24
  raise JWT::VerificationError, 'Signature verification raised'
22
25
  end
26
+
27
+ register_algorithm(new('RS256'))
28
+ register_algorithm(new('RS384'))
29
+ register_algorithm(new('RS512'))
30
+
31
+ private
32
+
33
+ attr_reader :digest
23
34
  end
24
35
  end
25
36
  end
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JWT
4
+ module JWA
5
+ module SigningAlgorithm
6
+ module ClassMethods
7
+ def register_algorithm(algo)
8
+ ::JWT::JWA.register_algorithm(algo)
9
+ end
10
+ end
11
+
12
+ def self.included(klass)
13
+ klass.extend(ClassMethods)
14
+ klass.include(JWT::JWA::Compat)
15
+ end
16
+
17
+ attr_reader :alg
18
+
19
+ def valid_alg?(alg_to_check)
20
+ alg&.casecmp(alg_to_check)&.zero? == true
21
+ end
22
+
23
+ def header(*)
24
+ { 'alg' => alg }
25
+ end
26
+
27
+ def sign(*)
28
+ raise_sign_error!('Algorithm implementation is missing the sign method')
29
+ end
30
+
31
+ def verify(*)
32
+ raise_verify_error!('Algorithm implementation is missing the verify method')
33
+ end
34
+
35
+ def raise_verify_error!(message)
36
+ raise(DecodeError.new(message).tap { |e| e.set_backtrace(caller(1)) })
37
+ end
38
+
39
+ def raise_sign_error!(message)
40
+ raise(EncodeError.new(message).tap { |e| e.set_backtrace(caller(1)) })
41
+ end
42
+ end
43
+
44
+ class << self
45
+ def register_algorithm(algo)
46
+ algorithms[algo.alg.to_s.downcase] = algo
47
+ end
48
+
49
+ def find(algo)
50
+ algorithms.fetch(algo.to_s.downcase, Unsupported)
51
+ end
52
+
53
+ private
54
+
55
+ def algorithms
56
+ @algorithms ||= {}
57
+ end
58
+ end
59
+ end
60
+ end
@@ -3,16 +3,16 @@
3
3
  module JWT
4
4
  module JWA
5
5
  module Unsupported
6
- module_function
6
+ class << self
7
+ include JWT::JWA::SigningAlgorithm
7
8
 
8
- SUPPORTED = [].freeze
9
+ def sign(*)
10
+ raise_sign_error!('Unsupported signing method')
11
+ end
9
12
 
10
- def sign(*)
11
- raise NotImplementedError, 'Unsupported signing method'
12
- end
13
-
14
- def verify(*)
15
- raise JWT::VerificationError, 'Algorithm not supported'
13
+ def verify(*)
14
+ raise JWT::VerificationError, 'Algorithm not supported'
15
+ end
16
16
  end
17
17
  end
18
18
  end