summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Newson <rnewson@apache.org>2020-03-30 12:04:38 +0100
committerRobert Newson <rnewson@apache.org>2020-03-30 21:04:19 +0100
commit1ab4ff362b08a09b2b95c08805c2f5027ffa7b59 (patch)
tree771c0b3bd7b16c2d874f82e1bd361aeedd88989f
parentd291847c97576c28ed4996ad06e09bb0c905d036 (diff)
downloadcouchdb-1ab4ff362b08a09b2b95c08805c2f5027ffa7b59.tar.gz
Enhance valid claims checks to detect binaries, etc
-rw-r--r--src/couch/src/couch_httpd_auth.erl8
-rw-r--r--src/jwtf/src/jwtf.erl20
-rw-r--r--src/jwtf/test/jwtf_tests.erl14
3 files changed, 37 insertions, 5 deletions
diff --git a/src/couch/src/couch_httpd_auth.erl b/src/couch/src/couch_httpd_auth.erl
index 4f19728e9..2383be798 100644
--- a/src/couch/src/couch_httpd_auth.erl
+++ b/src/couch/src/couch_httpd_auth.erl
@@ -208,7 +208,13 @@ jwt_authentication_handler(Req) ->
end.
get_configured_claims() ->
- re:split(config:get("jwt_auth", "required_claims", ""), "\s*,\s*", [{return, binary}]).
+ Claims = config:get("jwt_auth", "required_claims", ""),
+ case re:split(Claims, "\s*,\s*", [{return, list}]) of
+ [[]] ->
+ []; %% if required_claims is the empty string.
+ List ->
+ [list_to_existing_atom(C) || C <- List]
+ end.
cookie_authentication_handler(Req) ->
cookie_authentication_handler(Req, couch_auth_cache).
diff --git a/src/jwtf/src/jwtf.erl b/src/jwtf/src/jwtf.erl
index 098a41d24..d7fb2e7d4 100644
--- a/src/jwtf/src/jwtf.erl
+++ b/src/jwtf/src/jwtf.erl
@@ -123,8 +123,15 @@ validate(Header0, Payload0, Signature, Checks, KS) ->
Key = key(Header1, Checks, KS),
verify(Alg, Header0, Payload0, Signature, Key).
+
validate_checks(Checks) when is_list(Checks) ->
- UnknownChecks = proplists:get_keys(Checks) -- ?CHECKS,
+ case {lists:usort(Checks), lists:sort(Checks)} of
+ {L, L} ->
+ ok;
+ {L1, L2} ->
+ error({duplicate_checks, L2 -- L1})
+ end,
+ {_, UnknownChecks} = lists:partition(fun valid_check/1, Checks),
case UnknownChecks of
[] ->
ok;
@@ -132,6 +139,17 @@ validate_checks(Checks) when is_list(Checks) ->
error({unknown_checks, UnknownChecks})
end.
+
+valid_check(Check) when is_atom(Check) ->
+ lists:member(Check, ?CHECKS);
+
+valid_check({Check, _}) when is_atom(Check) ->
+ lists:member(Check, ?CHECKS);
+
+valid_check(_) ->
+ false.
+
+
validate_header(Props, Checks) ->
validate_typ(Props, Checks),
validate_alg(Props, Checks).
diff --git a/src/jwtf/test/jwtf_tests.erl b/src/jwtf/test/jwtf_tests.erl
index df3866f23..9f232241e 100644
--- a/src/jwtf/test/jwtf_tests.erl
+++ b/src/jwtf/test/jwtf_tests.erl
@@ -168,9 +168,17 @@ malformed_token_test() ->
?assertEqual({error, {bad_request, <<"Malformed token">>}},
jwtf:decode(<<"a.b.c.d">>, [], nil)).
-unknown_check_test() ->
- ?assertError({unknown_checks, [bar, foo]},
- jwtf:decode(<<"a.b.c">>, [exp, foo, iss, bar, exp], nil)).
+unknown_atom_check_test() ->
+ ?assertError({unknown_checks, [foo, bar]},
+ jwtf:decode(<<"a.b.c">>, [exp, foo, iss, bar], nil)).
+
+unknown_binary_check_test() ->
+ ?assertError({unknown_checks, [<<"bar">>]},
+ jwtf:decode(<<"a.b.c">>, [exp, iss, <<"bar">>], nil)).
+
+duplicate_check_test() ->
+ ?assertError({duplicate_checks, [exp]},
+ jwtf:decode(<<"a.b.c">>, [exp, exp], nil)).
%% jwt.io generated