From 8b45cb1a6cb35ac326cad9cb196ad8c987ff0586 Mon Sep 17 00:00:00 2001 From: Joakim Antman Date: Sun, 16 Jun 2024 22:40:26 +0300 Subject: [PATCH] Print deprecation warnings only if token validation succeeds --- CHANGELOG.md | 3 ++- lib/jwt.rb | 4 +++- lib/jwt/base64.rb | 2 +- lib/jwt/deprecations.rb | 29 ++++++++++++++++++++++++----- spec/jwt/jwt_spec.rb | 18 ++++++++++++++++++ 5 files changed, 48 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 40239a10..d3b86376 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,8 +10,9 @@ **Fixes and enhancements:** +- Print deprecation warnings only on when token decoding succeeds [#600](https://github.com/jwt/ruby-jwt/pull/600) ([@anakinj](https://github.com/anakinj)) - Your contribution here -- + ## [v2.8.1](https://github.com/jwt/ruby-jwt/tree/v2.8.1) (2024-02-29) [Full Changelog](https://github.com/jwt/ruby-jwt/compare/v2.8.0...v2.8.1) diff --git a/lib/jwt.rb b/lib/jwt.rb index 19b987ce..235d3a9f 100644 --- a/lib/jwt.rb +++ b/lib/jwt.rb @@ -27,6 +27,8 @@ def encode(payload, key, algorithm = 'HS256', header_fields = {}) end def decode(jwt, key = nil, verify = true, options = {}, &keyfinder) # rubocop:disable Style/OptionalBooleanParameter - Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments + Deprecations.context do + Decode.new(jwt, key, verify, configuration.decode.to_h.merge(options), &keyfinder).decode_segments + end end end diff --git a/lib/jwt/base64.rb b/lib/jwt/base64.rb index e6ee0622..20f56b6c 100644 --- a/lib/jwt/base64.rb +++ b/lib/jwt/base64.rb @@ -20,7 +20,7 @@ def url_decode(str) raise Base64DecodeError, 'Invalid base64 encoding' if JWT.configuration.strict_base64_decoding loose_urlsafe_decode64(str).tap do - Deprecations.warning('Invalid base64 input detected, could be because of invalid padding, trailing whitespaces or newline chars. Graceful handling of invalid input will be dropped in the next major version of ruby-jwt') + Deprecations.warning('Invalid base64 input detected, could be because of invalid padding, trailing whitespaces or newline chars. Graceful handling of invalid input will be dropped in the next major version of ruby-jwt', only_if_valid: true) end end diff --git a/lib/jwt/deprecations.rb b/lib/jwt/deprecations.rb index 92f0e6cf..b77540a1 100644 --- a/lib/jwt/deprecations.rb +++ b/lib/jwt/deprecations.rb @@ -4,15 +4,34 @@ module JWT # Deprecations module to handle deprecation warnings in the gem module Deprecations class << self - def warning(message) + def context + yield.tap { emit_warnings } + end + + def warning(message, only_if_valid: false) + method_name = only_if_valid ? :store : :warn case JWT.configuration.deprecation_warnings - when :warn - warn("[DEPRECATION WARNING] #{message}") when :once return if record_warned(message) - - warn("[DEPRECATION WARNING] #{message}") + when :warn + # noop + else + return end + + send(method_name, "[DEPRECATION WARNING] #{message}") + end + + def store(message) + (Thread.current[:jwt_warning_store] ||= []) << message + end + + def emit_warnings + return if Thread.current[:jwt_warning_store].nil? + + Thread.current[:jwt_warning_store].each { |warning| warn(warning) } + + Thread.current[:jwt_warning_store] = nil end private diff --git a/spec/jwt/jwt_spec.rb b/spec/jwt/jwt_spec.rb index 796dabb8..da1c01cd 100644 --- a/spec/jwt/jwt_spec.rb +++ b/spec/jwt/jwt_spec.rb @@ -944,4 +944,22 @@ def valid_alg?(alg) end end end + + context 'when invalid token is valid loose base64' do + it 'does not output deprecations warnings' do + expect { + begin + JWT.decode("#{JWT.encode('a', 'b')} 9", 'b') + rescue JWT::VerificationError + nil + end + }.not_to output(/DEPRECATION/).to_stderr + end + end + + context 'when valid token is invalid strict base64' do + it 'does outputs deprecation warning' do + expect { JWT.decode("#{JWT.encode('a', 'b')} ", 'b') }.to output(/DEPRECATION/).to_stderr + end + end end