Skip to content

Commit

Permalink
Drop loose base64 decoding
Browse files Browse the repository at this point in the history
  • Loading branch information
anakinj committed Dec 28, 2024
1 parent f9fac27 commit 29633b1
Show file tree
Hide file tree
Showing 3 changed files with 7 additions and 45 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Drop support for the HS512256 algorithm [#650](https://github.com/jwt/ruby-jwt/pull/650) ([@anakinj](https://github.com/anakinj))
- Remove deprecated claim verification methods [#654](https://github.com/jwt/ruby-jwt/pull/654) ([@anakinj](https://github.com/anakinj))
- Remove dependency to rbnacl [#655](https://github.com/jwt/ruby-jwt/pull/655) ([@anakinj](https://github.com/anakinj))
- Support only stricter base64 decoding (RFC 4648) [#658](https://github.com/jwt/ruby-jwt/pull/658) ([@anakinj](https://github.com/anakinj))

Take a look at the [upgrade guide](UPGRADING.md) for more details.

Expand Down
11 changes: 1 addition & 10 deletions lib/jwt/base64.rb
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,13 @@ def url_encode(str)
end

# Decode a string with URL-safe Base64 complying with RFC 4648.
# Deprecated support for RFC 2045 remains for now. ("All line breaks or other characters not found in Table 1 must be ignored by decoding software")
# @api private
def url_decode(str)
::Base64.urlsafe_decode64(str)
rescue ArgumentError => e
raise unless e.message == 'invalid base64'
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', only_if_valid: true)
end
end

def loose_urlsafe_decode64(str)
str += '=' * (4 - str.length.modulo(4))
::Base64.decode64(str.tr('-_', '+/'))
raise Base64DecodeError, 'Invalid base64 encoding'
end
end
end
Expand Down
40 changes: 5 additions & 35 deletions spec/jwt/jwt_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -552,14 +552,14 @@
end

context 'a token with invalid Base64 segments' do
it 'raises JWT::DecodeError' do
expect { JWT.decode('hello.there.world') }.to raise_error(JWT::DecodeError, 'Invalid segment encoding')
it 'raises JWT::Base64DecodeError' do
expect { JWT.decode('hello.there.world') }.to raise_error(JWT::Base64DecodeError, 'Invalid base64 encoding')
end
end

context 'a token with two segments but does not require verifying' do
it 'raises something else than "Not enough or too many segments"' do
expect { JWT.decode('ThisIsNotAValidJWTToken.second', nil, false) }.to raise_error(JWT::DecodeError, 'Invalid segment encoding')
expect { JWT.decode('ThisIsNotAValidJWTToken.second', nil, false) }.to raise_error(JWT::Base64DecodeError, 'Invalid base64 encoding')
end
end

Expand Down Expand Up @@ -736,8 +736,8 @@

context 'when token ends with a newline char' do
let(:token) { "#{JWT.encode(payload, 'secret', 'HS256')}\n" }
it 'ignores the newline and decodes the token' do
expect(JWT.decode(token, 'secret', true, algorithm: 'HS256')).to include(payload)
it 'raises an error' do
expect { JWT.decode(token, 'secret', true, algorithm: 'HS256') }.to raise_error(JWT::Base64DecodeError, 'Invalid base64 encoding')
end
end

Expand Down Expand Up @@ -949,34 +949,4 @@ def verify(*)
end
end
end

context 'when invalid token is valid loose base64' do
it 'does not output deprecations warnings' do
expect do
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 and decoded with the correct key' do
it 'does outputs deprecation warning' do
expect { JWT.decode("#{JWT.encode('payload', 'key')} ", 'key') }.to output(/DEPRECATION/).to_stderr
end
end

context 'when valid token is invalid strict base64 and decoded with the incorrect key' do
it 'does not output deprecation warning, even when decoded with the correct key' do
token = JWT.encode('payload', 'key')
expect do
begin
JWT.decode("#{token} ", 'incorrect')
rescue JWT::VerificationError
nil
end
JWT.decode(token, 'key')
end.not_to output(/DEPRECATION/).to_stderr
end
end
end

0 comments on commit 29633b1

Please sign in to comment.