artemeff / jwt

Erlang JWT library
http://jwt.io/
MIT License
38 stars 39 forks source link

Bug - Unpadded JWTs not working #38

Open atrauzzi opened 4 years ago

atrauzzi commented 4 years ago

I believe at the following line: https://github.com/artemeff/jwt/blob/master/src/jwt.erl#L146

...an error is occurring when attempting to decode un-padded base64 values.

As per the spec,

Base64url Encoding
      Base64 encoding using the URL- and filename-safe character set
      defined in Section 5 of RFC 4648 [RFC4648], with all trailing '='
      characters omitted (as permitted by Section 3.2) and without the
      inclusion of any line breaks, whitespace, or other additional
      characters.  Note that the base64url encoding of the empty octet
      sequence is the empty string.  (See Appendix C for notes on
      implementing base64url encoding without padding.)

I think this library needs to allow for un-padded base64 encoded JWT parts?

atrauzzi commented 4 years ago

I suspect something like this is necessary:

unpadded_base64_decode(Base64) ->
    try base64:decode(Base64) catch
      error:_ -> try base64:decode(<<Base64/binary, "=">>) catch
        error:_ try base64:decode(<<Base64/binary, "==">>) catch
          error:_ -> error
        end
      end
    end.
artemeff commented 4 years ago

@atrauzzi thanks for the report! but there's better solution, length of base64 string with padding should be multiple of four, so I prefer write it like this:

unpadded_base64_decode(Base64) ->
  case rem(byte_size(Base64), 4) of
    0 -> base64:decode(Base64);
    N -> base64:decode(<<Base64, binary:copy(<<"=">>, N)>>)
  end.

alternatively, we can take base64 impl that doesn't require padding at the end of a string and just put it directly into library :)