diff options
author | Robert Newson <rnewson@apache.org> | 2020-03-30 12:04:38 +0100 |
---|---|---|
committer | Robert Newson <rnewson@apache.org> | 2020-03-30 21:04:19 +0100 |
commit | 1ab4ff362b08a09b2b95c08805c2f5027ffa7b59 (patch) | |
tree | 771c0b3bd7b16c2d874f82e1bd361aeedd88989f | |
parent | d291847c97576c28ed4996ad06e09bb0c905d036 (diff) | |
download | couchdb-1ab4ff362b08a09b2b95c08805c2f5027ffa7b59.tar.gz |
Enhance valid claims checks to detect binaries, etc
-rw-r--r-- | src/couch/src/couch_httpd_auth.erl | 8 | ||||
-rw-r--r-- | src/jwtf/src/jwtf.erl | 20 | ||||
-rw-r--r-- | src/jwtf/test/jwtf_tests.erl | 14 |
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 |