summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJay Doane <jaydoane@apache.org>2021-03-01 13:48:19 -0800
committerJay Doane <jay.s.doane@gmail.com>2021-03-01 14:40:02 -0800
commit331894a6acb4565c71d800f2e63206101dfbb48c (patch)
treeb866ed9a74d2283df7c624ac51c0e43ea04d07b7
parentc0ae0761ae673a2417f0e455cbbeef743cf7fd8e (diff)
downloadcouchdb-331894a6acb4565c71d800f2e63206101dfbb48c.tar.gz
Ignore unchecked JWT claims
Previously, if a JWT claim was present, it was validated regardless of whether it was required. However, according to the spec [1]: "all claims that are not understood by implementations MUST be ignored" which we interpret to mean that we should not attempt to validate claims we don't require. With this change, only claims listed in required checks are validated. [1] https://tools.ietf.org/html/rfc7519#section-4
-rw-r--r--src/jwtf/src/jwtf.erl36
1 files changed, 26 insertions, 10 deletions
diff --git a/src/jwtf/src/jwtf.erl b/src/jwtf/src/jwtf.erl
index 247f2b508..a0bbf1fc1 100644
--- a/src/jwtf/src/jwtf.erl
+++ b/src/jwtf/src/jwtf.erl
@@ -188,8 +188,7 @@ validate_alg(Props, Checks) ->
end.
-%% Not all these fields have to be present, but if they _are_ present
-%% they must be valid.
+%% Only validate required checks.
validate_payload(Props, Checks) ->
validate_iss(Props, Checks),
validate_iat(Props, Checks),
@@ -202,7 +201,7 @@ validate_iss(Props, Checks) ->
ActualISS = prop(<<"iss">>, Props),
case {ExpectedISS, ActualISS} of
- {undefined, undefined} ->
+ {undefined, _} -> % ignore unrequired check
ok;
{ISS, undefined} when ISS /= undefined ->
throw({bad_request, <<"Missing iss claim">>});
@@ -218,11 +217,11 @@ validate_iat(Props, Checks) ->
IAT = prop(<<"iat">>, Props),
case {Required, IAT} of
- {undefined, undefined} ->
+ {undefined, _} -> % ignore unrequired check
ok;
{true, undefined} ->
throw({bad_request, <<"Missing iat claim">>});
- {_, IAT} when is_integer(IAT) ->
+ {true, IAT} when is_integer(IAT) ->
ok;
{true, _} ->
throw({bad_request, <<"Invalid iat claim">>})
@@ -234,12 +233,12 @@ validate_nbf(Props, Checks) ->
NBF = prop(<<"nbf">>, Props),
case {Required, NBF} of
- {undefined, undefined} ->
+ {undefined, _} -> % ignore unrequired check
ok;
{true, undefined} ->
throw({bad_request, <<"Missing nbf claim">>});
- {_, IAT} ->
- assert_past(<<"nbf">>, IAT)
+ {true, NBF} ->
+ assert_past(<<"nbf">>, NBF)
end.
@@ -248,11 +247,11 @@ validate_exp(Props, Checks) ->
EXP = prop(<<"exp">>, Props),
case {Required, EXP} of
- {undefined, undefined} ->
+ {undefined, _} -> % ignore unrequired check
ok;
{true, undefined} ->
throw({bad_request, <<"Missing exp claim">>});
- {_, EXP} ->
+ {true, EXP} ->
assert_future(<<"exp">>, EXP)
end.
@@ -351,3 +350,20 @@ now_seconds() ->
prop(Prop, Props) ->
proplists:get_value(Prop, Props).
+
+
+-ifdef(TEST).
+-include_lib("eunit/include/eunit.hrl").
+
+validate_payload_ignore_unchecked_props_test() ->
+ ?assertEqual(ok, validate_payload(_Props = [], _Checks = [])),
+ BogusProps = [
+ {iss, bogus},
+ {iat, bogus},
+ {nbf, bogus},
+ {exp, bogus}
+ ],
+ ?assertEqual(ok, validate_payload(BogusProps, _Checks = [])),
+ ok.
+
+-endif.