sealights-rspec-agent 2.0.4 → 2.0.5
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 +4 -4
- data/agent/config.rb +6 -6
- data/agent/dependencies/faraday-0.17.0/LICENSE.md +20 -0
- data/agent/dependencies/faraday-0.17.0/README.md +384 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday.rb +248 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter.rb +55 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/em_http.rb +243 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/em_synchrony.rb +106 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/em_synchrony/parallel_manager.rb +66 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/excon.rb +82 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/httpclient.rb +128 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/net_http.rb +152 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/net_http_persistent.rb +68 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/patron.rb +95 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/rack.rb +58 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/sl_em_http_ssl_patch.rb +56 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/test.rb +213 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/adapter/typhoeus.rb +12 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/autoload.rb +84 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/connection.rb +484 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/error.rb +66 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/middleware.rb +37 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/options.rb +373 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/parameters.rb +198 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/rack_builder.rb +237 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/request.rb +114 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/request/authorization.rb +41 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/request/basic_authentication.rb +13 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/request/instrumentation.rb +36 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/request/multipart.rb +68 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/request/retry.rb +212 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/request/token_authentication.rb +15 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/request/url_encoded.rb +36 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/response.rb +97 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/response/logger.rb +80 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/response/raise_error.rb +21 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/upload_io.rb +67 -0
- data/agent/dependencies/faraday-0.17.0/lib/faraday/utils.rb +326 -0
- data/agent/dependencies/jwt-2.2.1/AUTHORS +84 -0
- data/agent/dependencies/jwt-2.2.1/Appraisals +14 -0
- data/agent/dependencies/jwt-2.2.1/CHANGELOG.md +570 -0
- data/agent/dependencies/jwt-2.2.1/Gemfile +3 -0
- data/agent/dependencies/jwt-2.2.1/LICENSE +7 -0
- data/agent/dependencies/jwt-2.2.1/README.md +489 -0
- data/agent/dependencies/jwt-2.2.1/Rakefile +11 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt.rb +30 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/ecdsa.rb +35 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/eddsa.rb +23 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/hmac.rb +33 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/ps.rb +43 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/rsa.rb +19 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/algos/unsupported.rb +16 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/base64.rb +19 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/claims_validator.rb +33 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/decode.rb +100 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/default_options.rb +15 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/encode.rb +68 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/error.rb +20 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/json.rb +18 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/jwk.rb +31 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/jwk/key_finder.rb +57 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/jwk/rsa.rb +47 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/security_utils.rb +57 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/signature.rb +52 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/verify.rb +98 -0
- data/agent/dependencies/jwt-2.2.1/lib/jwt/version.rb +24 -0
- data/agent/dependencies/jwt-2.2.1/ruby-jwt.gemspec +34 -0
- data/agent/dependencies/multipart-post-2.1.1/Gemfile +6 -0
- data/agent/dependencies/multipart-post-2.1.1/History.txt +64 -0
- data/agent/dependencies/multipart-post-2.1.1/LICENSE +21 -0
- data/agent/dependencies/multipart-post-2.1.1/Manifest.txt +9 -0
- data/agent/dependencies/multipart-post-2.1.1/README.md +127 -0
- data/agent/dependencies/multipart-post-2.1.1/Rakefile +6 -0
- data/agent/dependencies/multipart-post-2.1.1/lib/composite_io.rb +108 -0
- data/agent/dependencies/multipart-post-2.1.1/lib/multipart_post.rb +9 -0
- data/agent/dependencies/multipart-post-2.1.1/lib/multipartable.rb +48 -0
- data/agent/dependencies/multipart-post-2.1.1/lib/net/http/post/multipart.rb +28 -0
- data/agent/dependencies/multipart-post-2.1.1/lib/parts.rb +126 -0
- data/agent/dependencies/multipart-post-2.1.1/multipart-post.gemspec +23 -0
- data/agent/http_client.rb +46 -0
- data/agent/listener.rb +1 -1
- data/agent/sealights-rspec-agent.rb +2 -2
- data/agent/tia.rb +5 -1
- metadata +80 -3
- data/agent/rest-client-wrapper.rb +0 -27
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
RSpec::Core::RakeTask.new(:test)
|
7
|
+
|
8
|
+
task default: :test
|
9
|
+
rescue LoadError
|
10
|
+
puts 'RSpec rake tasks not available. Please run "bundle install" to install missing dependencies.'
|
11
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'jwt/base64'
|
4
|
+
require_relative 'jwt/json'
|
5
|
+
require_relative 'jwt/decode'
|
6
|
+
require_relative 'jwt/default_options'
|
7
|
+
require_relative 'jwt/encode'
|
8
|
+
require_relative 'jwt/error'
|
9
|
+
require_relative 'jwt/jwk'
|
10
|
+
|
11
|
+
# JSON Web Token implementation
|
12
|
+
#
|
13
|
+
# Should be up to date with the latest spec:
|
14
|
+
# https://tools.ietf.org/html/rfc7519
|
15
|
+
module SL_JWT
|
16
|
+
include SL_JWT::DefaultOptions
|
17
|
+
|
18
|
+
module_function
|
19
|
+
|
20
|
+
def encode(payload, key, algorithm = 'HS256', header_fields = {})
|
21
|
+
Encode.new(payload: payload,
|
22
|
+
key: key,
|
23
|
+
algorithm: algorithm,
|
24
|
+
headers: header_fields).segments
|
25
|
+
end
|
26
|
+
|
27
|
+
def decode(jwt, key = nil, verify = true, options = {}, &keyfinder)
|
28
|
+
Decode.new(jwt, key, verify, DEFAULT_OPTIONS.merge(options), &keyfinder).decode_segments
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module SL_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
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module SL_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
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module SL_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
|
+
authenticator, padded_key = SecurityUtils.rbnacl_fixup(algorithm, key)
|
11
|
+
if authenticator && padded_key
|
12
|
+
authenticator.auth(padded_key, msg.encode('binary'))
|
13
|
+
else
|
14
|
+
OpenSSL::HMAC.digest(OpenSSL::Digest.new(algorithm.sub('HS', 'sha')), key, msg)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def verify(to_verify)
|
19
|
+
algorithm, public_key, signing_input, signature = to_verify.values
|
20
|
+
authenticator, padded_key = SecurityUtils.rbnacl_fixup(algorithm, public_key)
|
21
|
+
if authenticator && padded_key
|
22
|
+
begin
|
23
|
+
authenticator.verify(padded_key, signature.encode('binary'), signing_input.encode('binary'))
|
24
|
+
rescue RbNaCl::BadAuthenticatorError
|
25
|
+
false
|
26
|
+
end
|
27
|
+
else
|
28
|
+
SecurityUtils.secure_compare(signature, sign(SL_JWT::Signature::ToSign.new(algorithm, signing_input, public_key)))
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module SL_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 SL_JWT::RequiredDependencyError, "You currently have OpenSSL #{OpenSSL::VERSION}. PS support requires >= 2.1"
|
36
|
+
end
|
37
|
+
else
|
38
|
+
raise SL_JWT::RequiredDependencyError, 'PS signing requires OpenSSL +2.1'
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SL_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
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module SL_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 SL_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
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'base64'
|
4
|
+
|
5
|
+
module SL_JWT
|
6
|
+
# Base64 helpers
|
7
|
+
class Base64
|
8
|
+
class << self
|
9
|
+
def url_encode(str)
|
10
|
+
::Base64.encode64(str).tr('+/', '-_').gsub(/[\n=]/, '')
|
11
|
+
end
|
12
|
+
|
13
|
+
def url_decode(str)
|
14
|
+
str += '=' * (4 - str.length.modulo(4))
|
15
|
+
::Base64.decode64(str.tr('-_', '+/'))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require_relative './error'
|
2
|
+
|
3
|
+
module SL_JWT
|
4
|
+
class ClaimsValidator
|
5
|
+
INTEGER_CLAIMS = %i[
|
6
|
+
exp
|
7
|
+
iat
|
8
|
+
nbf
|
9
|
+
].freeze
|
10
|
+
|
11
|
+
def initialize(payload)
|
12
|
+
@payload = payload.each_with_object({}) { |(k, v), h| h[k.to_sym] = v }
|
13
|
+
end
|
14
|
+
|
15
|
+
def validate!
|
16
|
+
validate_int_claims
|
17
|
+
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def validate_int_claims
|
24
|
+
INTEGER_CLAIMS.each do |claim|
|
25
|
+
validate_is_int(claim) if @payload.key?(claim)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def validate_is_int(claim)
|
30
|
+
raise InvalidPayload, "#{claim} claim must be an Integer but it is a #{@payload[claim].class}" unless @payload[claim].is_a?(Integer)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
require_relative './signature'
|
6
|
+
require_relative './verify'
|
7
|
+
# JWT::Decode module
|
8
|
+
module SL_JWT
|
9
|
+
# Decoding logic for JWT
|
10
|
+
class Decode
|
11
|
+
def initialize(jwt, key, verify, options, &keyfinder)
|
12
|
+
raise(SL_JWT::DecodeError, 'Nil JSON web token') unless jwt
|
13
|
+
@jwt = jwt
|
14
|
+
@key = key
|
15
|
+
@options = options
|
16
|
+
@segments = jwt.split('.')
|
17
|
+
@verify = verify
|
18
|
+
@signature = ''
|
19
|
+
@keyfinder = keyfinder
|
20
|
+
end
|
21
|
+
|
22
|
+
def decode_segments
|
23
|
+
validate_segment_count!
|
24
|
+
if @verify
|
25
|
+
decode_crypto
|
26
|
+
verify_signature
|
27
|
+
verify_claims
|
28
|
+
end
|
29
|
+
raise(SL_JWT::DecodeError, 'Not enough or too many segments') unless header && payload
|
30
|
+
[payload, header]
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def verify_signature
|
36
|
+
@key = find_key(&@keyfinder) if @keyfinder
|
37
|
+
@key = ::SL_JWT::JWK::KeyFinder.new(jwks: @options[:jwks]).key_for(header['kid']) if @options[:jwks]
|
38
|
+
|
39
|
+
raise(SL_JWT::IncorrectAlgorithm, 'An algorithm must be specified') if allowed_algorithms.empty?
|
40
|
+
raise(SL_JWT::IncorrectAlgorithm, 'Expected a different algorithm') unless options_includes_algo_in_header?
|
41
|
+
|
42
|
+
Signature.verify(header['alg'], @key, signing_input, @signature)
|
43
|
+
end
|
44
|
+
|
45
|
+
def options_includes_algo_in_header?
|
46
|
+
allowed_algorithms.include? header['alg']
|
47
|
+
end
|
48
|
+
|
49
|
+
def allowed_algorithms
|
50
|
+
if @options.key?(:algorithm)
|
51
|
+
[@options[:algorithm]]
|
52
|
+
else
|
53
|
+
@options[:algorithms] || []
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def find_key(&keyfinder)
|
58
|
+
key = (keyfinder.arity == 2 ? yield(header, payload) : yield(header))
|
59
|
+
raise SL_JWT::DecodeError, 'No verification key available' unless key
|
60
|
+
key
|
61
|
+
end
|
62
|
+
|
63
|
+
def verify_claims
|
64
|
+
Verify.verify_claims(payload, @options)
|
65
|
+
end
|
66
|
+
|
67
|
+
def validate_segment_count!
|
68
|
+
return if segment_length == 3
|
69
|
+
return if !@verify && segment_length == 2 # If no verifying required, the signature is not needed
|
70
|
+
|
71
|
+
raise(SL_JWT::DecodeError, 'Not enough or too many segments')
|
72
|
+
end
|
73
|
+
|
74
|
+
def segment_length
|
75
|
+
@segments.count
|
76
|
+
end
|
77
|
+
|
78
|
+
def decode_crypto
|
79
|
+
@signature = SL_JWT::Base64.url_decode(@segments[2])
|
80
|
+
end
|
81
|
+
|
82
|
+
def header
|
83
|
+
@header ||= parse_and_decode @segments[0]
|
84
|
+
end
|
85
|
+
|
86
|
+
def payload
|
87
|
+
@payload ||= parse_and_decode @segments[1]
|
88
|
+
end
|
89
|
+
|
90
|
+
def signing_input
|
91
|
+
@segments.first(2).join('.')
|
92
|
+
end
|
93
|
+
|
94
|
+
def parse_and_decode(segment)
|
95
|
+
SL_JWT::JSON.parse(SL_JWT::Base64.url_decode(segment))
|
96
|
+
rescue ::JSON::ParserError
|
97
|
+
raise SL_JWT::DecodeError, 'Invalid segment encoding'
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module SL_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
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative './claims_validator'
|
4
|
+
|
5
|
+
# JWT::Encode module
|
6
|
+
module SL_JWT
|
7
|
+
# Encoding logic for JWT
|
8
|
+
class Encode
|
9
|
+
ALG_NONE = 'none'.freeze
|
10
|
+
ALG_KEY = 'alg'.freeze
|
11
|
+
|
12
|
+
def initialize(options)
|
13
|
+
@payload = options[:payload]
|
14
|
+
@key = options[:key]
|
15
|
+
@algorithm = options[:algorithm]
|
16
|
+
@headers = options[:headers].each_with_object({}) { |(key, value), headers| headers[key.to_s] = value }
|
17
|
+
end
|
18
|
+
|
19
|
+
def segments
|
20
|
+
@segments ||= combine(encoded_header_and_payload, encoded_signature)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def encoded_header
|
26
|
+
@encoded_header ||= encode_header
|
27
|
+
end
|
28
|
+
|
29
|
+
def encoded_payload
|
30
|
+
@encoded_payload ||= encode_payload
|
31
|
+
end
|
32
|
+
|
33
|
+
def encoded_signature
|
34
|
+
@encoded_signature ||= encode_signature
|
35
|
+
end
|
36
|
+
|
37
|
+
def encoded_header_and_payload
|
38
|
+
@encoded_header_and_payload ||= combine(encoded_header, encoded_payload)
|
39
|
+
end
|
40
|
+
|
41
|
+
def encode_header
|
42
|
+
@headers[ALG_KEY] = @algorithm
|
43
|
+
encode(@headers)
|
44
|
+
end
|
45
|
+
|
46
|
+
def encode_payload
|
47
|
+
if @payload && @payload.is_a?(Hash)
|
48
|
+
ClaimsValidator.new(@payload).validate!
|
49
|
+
end
|
50
|
+
|
51
|
+
encode(@payload)
|
52
|
+
end
|
53
|
+
|
54
|
+
def encode_signature
|
55
|
+
return '' if @algorithm == ALG_NONE
|
56
|
+
|
57
|
+
SL_JWT::Base64.url_encode(SL_JWT::Signature.sign(@algorithm, encoded_header_and_payload, @key))
|
58
|
+
end
|
59
|
+
|
60
|
+
def encode(data)
|
61
|
+
SL_JWT::Base64.url_encode(SL_JWT::JSON.generate(data))
|
62
|
+
end
|
63
|
+
|
64
|
+
def combine(*parts)
|
65
|
+
parts.join('.')
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|