diff --git a/.gitmodules b/.gitmodules index 8f98aac5..41ef7280 100644 --- a/.gitmodules +++ b/.gitmodules @@ -109,3 +109,6 @@ [submodule "gems/moji/1.6/_src"] path = gems/moji/1.6/_src url = https://github.com/gimite/moji.git +[submodule "gems/jwt/2.5/_src"] + path = gems/jwt/2.5/_src + url = https://github.com/jwt/ruby-jwt.git diff --git a/gems/jwt/2.5/_scripts/test b/gems/jwt/2.5/_scripts/test new file mode 100755 index 00000000..250859b1 --- /dev/null +++ b/gems/jwt/2.5/_scripts/test @@ -0,0 +1,19 @@ +#!/usr/bin/env bash + +# Exit command with non-zero status code, Output logs of every command executed, Treat unset variables as an error when substituting. +set -eou pipefail +# Internal Field Separator - Linux shell variable +IFS=$'\n\t' +# Print shell input lines +set -v + +# Set RBS_DIR variable to change directory to execute type checks using `steep check` +RBS_DIR=$(cd $(dirname $0)/..; pwd) +# Set REPO_DIR variable to validate RBS files added to the corresponding folder +REPO_DIR=$(cd $(dirname $0)/../../..; pwd) +# Validate RBS files, using the bundler environment present +bundle exec rbs --repo $REPO_DIR -r jwt:2.5 validate --silent + +cd ${RBS_DIR}/_test +# Run type checks +bundle exec steep check diff --git a/gems/jwt/2.5/_src b/gems/jwt/2.5/_src new file mode 160000 index 00000000..b4f9f1d4 --- /dev/null +++ b/gems/jwt/2.5/_src @@ -0,0 +1 @@ +Subproject commit b4f9f1d483086054e812dc6ce5655466b6de3858 diff --git a/gems/jwt/2.5/_test/Steepfile b/gems/jwt/2.5/_test/Steepfile new file mode 100644 index 00000000..8ed45c87 --- /dev/null +++ b/gems/jwt/2.5/_test/Steepfile @@ -0,0 +1,11 @@ +D = Steep::Diagnostic + +target :test do + check "." + signature '.' + + repo_path "../../../" + library "jwt" + + configure_code_diagnostics(D::Ruby.all_error) +end diff --git a/gems/jwt/2.5/_test/test.rb b/gems/jwt/2.5/_test/test.rb new file mode 100644 index 00000000..e12d3a08 --- /dev/null +++ b/gems/jwt/2.5/_test/test.rb @@ -0,0 +1,42 @@ +require "jwt" + +payload = { data: 'test' } +token = JWT.encode(payload, nil, 'none') +decoded, header = JWT.decode(token, nil, false) + +hmac_secret = 'my$ecretK3y' +token = JWT.encode(payload, hmac_secret, 'HS256') +decoded, header = JWT.decode(token, hmac_secret, true, algorithm: 'HS256') + +# Custom algorithm +class CustomAlgorithm + def alg + 'custom' + end + + def valid_alg?(alg_to_validate) + true + end + + def sign(data:, signing_key:) + 'sig' + end + + def verify(data:, signature:, verification_key:) + true + end +end + +alg = CustomAlgorithm.new + +begin + token = ::JWT.encode(payload, 'secret', alg) +rescue JWT::EncodeError => e + puts e.backtrace +end + +begin + decoded, header = ::JWT.decode(token, 'secret', true, algorithm: alg) +rescue JWT::DecodeError, JWT::VerificationError, JWT::ExpiredSignature, JWT::IncorrectAlgorithm, JWT::ImmatureSignature, JWT::InvalidIssuerError, JWT::InvalidIatError, JWT::InvalidAudError, JWT::InvalidSubError, JWT::InvalidJtiError, JWT::InvalidPayload, JWT::MissingRequiredClaim, JWT::JWKError => e + puts e.backtrace +end diff --git a/gems/jwt/2.5/_test/test.rbs b/gems/jwt/2.5/_test/test.rbs new file mode 100644 index 00000000..ce5822ff --- /dev/null +++ b/gems/jwt/2.5/_test/test.rbs @@ -0,0 +1,6 @@ +class CustomAlgorithm + def alg: () -> ::String + def sign: (data: ::String, signing_key: untyped) -> ::String + def valid_alg?: (String alg_to_validate) -> bool + def verify: (data: untyped, signature: ::String, verification_key: untyped) -> bool +end diff --git a/gems/jwt/2.5/jwt.rbs b/gems/jwt/2.5/jwt.rbs new file mode 100644 index 00000000..a635c717 --- /dev/null +++ b/gems/jwt/2.5/jwt.rbs @@ -0,0 +1,48 @@ +module JWT + interface _Algo + def alg: () -> ::String + def sign: (data: ::String, signing_key: untyped) -> ::String + def valid_alg?: (String alg_to_validate) -> boolish + def verify: (data: untyped, signature: ::String, verification_key: untyped) -> boolish + end + + def self?.encode: (untyped payload, untyped key, ?::String | _Algo algorithm, ?::Hash[::String | ::Symbol, untyped] header_fields) -> ::String + + def self?.decode: (String jwt, ?untyped? key, ?boolish verify, ?::Hash[Symbol, untyped] options) ?{ (Hash[::String, untyped] header, ?untyped payload) -> untyped } -> [untyped, Hash[::String, untyped]] + + + class EncodeError < StandardError + end + class DecodeError < StandardError + end + class RequiredDependencyError < StandardError + end + + class VerificationError < DecodeError + end + class ExpiredSignature < DecodeError + end + class IncorrectAlgorithm < DecodeError + end + class ImmatureSignature < DecodeError + end + class InvalidIssuerError < DecodeError + end + class UnsupportedEcdsaCurve < IncorrectAlgorithm + end + class InvalidIatError < DecodeError + end + class InvalidAudError < DecodeError + end + class InvalidSubError < DecodeError + end + class InvalidJtiError < DecodeError + end + class InvalidPayload < DecodeError + end + class MissingRequiredClaim < DecodeError + end + + class JWKError < DecodeError + end +end