Class: CyberSource::Authentication::Util::JWT::JWTUtility
- Inherits:
-
Object
- Object
- CyberSource::Authentication::Util::JWT::JWTUtility
- Defined in:
- lib/AuthenticationSDK/util/JWT/JWTUtility.rb
Overview
JWT Utility Class
Provides JWT parsing, verification, and JWK handling functionality.
Constant Summary collapse
- SUPPORTED_ALGORITHMS =
Supported JWT algorithms
%w[RS256 RS384 RS512].freeze
Class Method Summary collapse
-
.parse(jwt_token) ⇒ Hash
Parses a JWT token and extracts its header, payload, and signature components.
-
.verify_jwt(jwt_token, public_key) ⇒ void
Verifies a JWT token using an RSA public key.
Class Method Details
.parse(jwt_token) ⇒ Hash
Parses a JWT token and extracts its header, payload, and signature components
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/AuthenticationSDK/util/JWT/JWTUtility.rb', line 29 def parse(jwt_token) raise InvalidJwtException.new('JWT token is null or undefined') if jwt_token.to_s.empty? token_parts = jwt_token.split('.') if token_parts.length != 3 raise InvalidJwtException.new('Invalid JWT token format: expected 3 parts separated by dots') end if token_parts.any?(&:empty?) raise InvalidJwtException.new('Malformed JWT : JWT provided does not conform to the proper structure for JWT') end begin header = JSON.parse(::JWT::Base64.url_decode(token_parts[0])) payload = JSON.parse(::JWT::Base64.url_decode(token_parts[1])) signature = token_parts[2] { header: header, payload: payload, signature: signature, raw_header: token_parts[0], raw_payload: token_parts[1] } rescue StandardError => e raise InvalidJwtException.new("Malformed JWT cannot be parsed: #{e.message}", e) end end |
.verify_jwt(jwt_token, public_key) ⇒ void
This method returns an undefined value.
Verifies a JWT token using an RSA public key
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/AuthenticationSDK/util/JWT/JWTUtility.rb', line 68 def verify_jwt(jwt_token, public_key) raise JwtSignatureValidationException.new('No public key found') if public_key.to_s.empty? raise JwtSignatureValidationException.new('JWT token is null or undefined') if jwt_token.to_s.empty? parsed_token = parse(jwt_token) header = parsed_token[:header] if header['alg'].nil? || header['alg'].to_s.empty? raise JwtSignatureValidationException.new('JWT header missing algorithm (alg) field') end algorithm = header['alg'] unless SUPPORTED_ALGORITHMS.include?(algorithm) supported_algs = SUPPORTED_ALGORITHMS.join(', ') raise JwtSignatureValidationException.new( format('Unsupported JWT algorithm: %s. Supported algorithms: %s', algorithm, supported_algs) ) end jwk_key = validate_and_parse_jwk(public_key) jwk_key['alg'] ||= algorithm begin rsa_key = jwk_to_rsa_key(jwk_key) ::JWT.decode(jwt_token, rsa_key, true, { algorithm: algorithm }) rescue ::JWT::VerificationError => e raise JwtSignatureValidationException.new('JWT signature verification failed', e) rescue ::JWT::ExpiredSignature => e raise JwtSignatureValidationException.new('JWT has expired (exp claim)', e) rescue ::JWT::ImmatureSignature => e raise JwtSignatureValidationException.new('JWT not yet valid (nbf claim)', e) rescue ::JWT::DecodeError => e raise JwtSignatureValidationException.new("JWT verification failed: #{e.message}", e) rescue JwtSignatureValidationException, InvalidJwtException raise rescue StandardError => e raise JwtSignatureValidationException.new("JWT verification failed: #{e.message}", e) end end |