diff options
author | Jay Doane <jaydoane@apache.org> | 2020-03-11 11:58:56 -0700 |
---|---|---|
committer | Jay Doane <jaydoane@apache.org> | 2020-03-11 11:58:56 -0700 |
commit | 1794e146c8b3283c77fb549f75afbc96a92d62be (patch) | |
tree | 37e28910ad17ac7563e05f830ae98f1cf6f2f9df | |
parent | b00814e58ba601a83b676c336ce2f5d82744a535 (diff) | |
download | couchdb-1794e146c8b3283c77fb549f75afbc96a92d62be.tar.gz |
Handle malformed tokens with jiffy 1.x
Recent changes in how `jiffy:decode/1` handles malformed JSON has caused
`jwtf:decode/3` to fail to properly return a bad request 400 response
for some malformed tokens.
First, this changes the name of the function to `decode_b64url_json/1`,
indicating that it decodes something that has been first been JSON
encoded, and then base64url encoded.
More substantially, it wraps both the base64url and jiffy decoding in a
try/catch block, since both can throw errors, while the former can also
return an error tuple. Tests have been added to ensure all code paths
are covered.
-rw-r--r-- | src/jwtf.erl | 24 | ||||
-rw-r--r-- | test/jwtf_tests.erl | 24 |
2 files changed, 39 insertions, 9 deletions
diff --git a/src/jwtf.erl b/src/jwtf.erl index c6cc78433..8e58e0897 100644 --- a/src/jwtf.erl +++ b/src/jwtf.erl @@ -74,7 +74,7 @@ decode(EncodedToken, Checks, KS) -> try [Header, Payload, Signature] = split(EncodedToken), validate(Header, Payload, Signature, Checks, KS), - {ok, decode_json(Payload)} + {ok, decode_b64url_json(Payload)} catch throw:Error -> {error, Error} @@ -102,10 +102,10 @@ verification_algorithm(Alg) -> validate(Header0, Payload0, Signature, Checks, KS) -> - Header1 = props(decode_json(Header0)), + Header1 = props(decode_b64url_json(Header0)), validate_header(Header1, Checks), - Payload1 = props(decode_json(Payload0)), + Payload1 = props(decode_b64url_json(Payload0)), validate_payload(Payload1, Checks), Alg = prop(<<"alg">>, Header1), @@ -269,14 +269,20 @@ split(EncodedToken) -> end. -decode_json(Encoded) -> - case b64url:decode(Encoded) of - {error, Reason} -> - throw({bad_request, Reason}); - Decoded -> - jiffy:decode(Decoded) +decode_b64url_json(B64UrlEncoded) -> + try + case b64url:decode(B64UrlEncoded) of + {error, Reason} -> + throw({bad_request, Reason}); + JsonEncoded -> + jiffy:decode(JsonEncoded) + end + catch + error:Error -> + throw({bad_request, Error}) end. + props({Props}) -> Props; diff --git a/test/jwtf_tests.erl b/test/jwtf_tests.erl index 527bc327f..dcebe5f40 100644 --- a/test/jwtf_tests.erl +++ b/test/jwtf_tests.erl @@ -35,6 +35,30 @@ jwt_io_pubkey() -> public_key:pem_entry_decode(PEMEntry). +b64_badarg_test() -> + Encoded = <<"0.0.0">>, + ?assertEqual({error, {bad_request,badarg}}, + jwtf:decode(Encoded, [], nil)). + + +b64_bad_block_test() -> + Encoded = <<" aGVsbG8. aGVsbG8. aGVsbG8">>, + ?assertEqual({error, {bad_request,{bad_block,0}}}, + jwtf:decode(Encoded, [], nil)). + + +invalid_json_test() -> + Encoded = <<"fQ.fQ.fQ">>, + ?assertEqual({error, {bad_request,{1,invalid_json}}}, + jwtf:decode(Encoded, [], nil)). + + +truncated_json_test() -> + Encoded = <<"ew.ew.ew">>, + ?assertEqual({error, {bad_request,{2,truncated_json}}}, + jwtf:decode(Encoded, [], nil)). + + missing_typ_test() -> Encoded = encode({[]}, []), ?assertEqual({error, {bad_request,<<"Missing typ header parameter">>}}, |