summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Doane <jaydoane@apache.org>2020-03-11 11:58:56 -0700
committerJay Doane <jaydoane@apache.org>2020-03-11 11:58:56 -0700
commit1794e146c8b3283c77fb549f75afbc96a92d62be (patch)
tree37e28910ad17ac7563e05f830ae98f1cf6f2f9df
parentb00814e58ba601a83b676c336ce2f5d82744a535 (diff)
downloadcouchdb-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.erl24
-rw-r--r--test/jwtf_tests.erl24
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">>}},