diff options
author | Robert Newson <rnewson@apache.org> | 2020-03-30 12:42:21 +0100 |
---|---|---|
committer | Robert Newson <rnewson@apache.org> | 2020-03-30 21:04:23 +0100 |
commit | 6b6ddf0f257eba27596b42bc8978551b7a53e59a (patch) | |
tree | 25f4031c3ddb3fc9f9d3a47f9398adf5738784b4 | |
parent | 1ab4ff362b08a09b2b95c08805c2f5027ffa7b59 (diff) | |
download | couchdb-6b6ddf0f257eba27596b42bc8978551b7a53e59a.tar.gz |
Verify all presented claimsjwt-controls-2
All claims in the header and payload are verified if present. The
required_claims config setting is now separate and only causes CouchDB
to reject JWT tokens without those claims.
-rw-r--r-- | rel/overlay/etc/default.ini | 2 | ||||
-rw-r--r-- | src/jwtf/src/jwtf.erl | 24 | ||||
-rw-r--r-- | src/jwtf/test/jwtf_tests.erl | 2 | ||||
-rw-r--r-- | test/elixir/test/jwtauth_test.exs | 18 |
4 files changed, 31 insertions, 15 deletions
diff --git a/rel/overlay/etc/default.ini b/rel/overlay/etc/default.ini index 24f504726..6fe2260b4 100644 --- a/rel/overlay/etc/default.ini +++ b/rel/overlay/etc/default.ini @@ -142,7 +142,7 @@ max_db_number_for_dbs_info_req = 100 ;[jwt_auth] ; List of claims to validate -; required_claims = exp +; required_claims = ; ; [jwt_keys] ; Configure at least one key here if using the JWT auth handler. diff --git a/src/jwtf/src/jwtf.erl b/src/jwtf/src/jwtf.erl index d7fb2e7d4..247f2b508 100644 --- a/src/jwtf/src/jwtf.erl +++ b/src/jwtf/src/jwtf.erl @@ -159,11 +159,11 @@ validate_typ(Props, Checks) -> Required = prop(typ, Checks), TYP = prop(<<"typ">>, Props), case {Required, TYP} of - {undefined, _} -> + {undefined, undefined} -> ok; {true, undefined} -> throw({bad_request, <<"Missing typ header parameter">>}); - {true, <<"JWT">>} -> + {_, <<"JWT">>} -> ok; {true, _} -> throw({bad_request, <<"Invalid typ header parameter">>}) @@ -174,11 +174,11 @@ validate_alg(Props, Checks) -> Required = prop(alg, Checks), Alg = prop(<<"alg">>, Props), case {Required, Alg} of - {undefined, _} -> + {undefined, undefined} -> ok; {true, undefined} -> throw({bad_request, <<"Missing alg header parameter">>}); - {true, Alg} -> + {_, Alg} -> case lists:member(Alg, valid_algorithms()) of true -> ok; @@ -202,9 +202,9 @@ validate_iss(Props, Checks) -> ActualISS = prop(<<"iss">>, Props), case {ExpectedISS, ActualISS} of - {undefined, _} -> + {undefined, undefined} -> ok; - {_ISS, undefined} -> + {ISS, undefined} when ISS /= undefined -> throw({bad_request, <<"Missing iss claim">>}); {ISS, ISS} -> ok; @@ -218,11 +218,11 @@ validate_iat(Props, Checks) -> IAT = prop(<<"iat">>, Props), case {Required, IAT} of - {undefined, _} -> + {undefined, undefined} -> ok; {true, undefined} -> throw({bad_request, <<"Missing iat claim">>}); - {true, IAT} when is_integer(IAT) -> + {_, IAT} when is_integer(IAT) -> ok; {true, _} -> throw({bad_request, <<"Invalid iat claim">>}) @@ -234,11 +234,11 @@ validate_nbf(Props, Checks) -> NBF = prop(<<"nbf">>, Props), case {Required, NBF} of - {undefined, _} -> + {undefined, undefined} -> ok; {true, undefined} -> throw({bad_request, <<"Missing nbf claim">>}); - {true, IAT} -> + {_, IAT} -> assert_past(<<"nbf">>, IAT) end. @@ -248,11 +248,11 @@ validate_exp(Props, Checks) -> EXP = prop(<<"exp">>, Props), case {Required, EXP} of - {undefined, _} -> + {undefined, undefined} -> ok; {true, undefined} -> throw({bad_request, <<"Missing exp claim">>}); - {true, EXP} -> + {_, EXP} -> assert_future(<<"exp">>, EXP) end. diff --git a/src/jwtf/test/jwtf_tests.erl b/src/jwtf/test/jwtf_tests.erl index 9f232241e..ba944f7c7 100644 --- a/src/jwtf/test/jwtf_tests.erl +++ b/src/jwtf/test/jwtf_tests.erl @@ -275,7 +275,7 @@ header(Alg) -> claims() -> - EpochSeconds = 1496205841, + EpochSeconds = os:system_time(second), {[ {<<"iat">>, EpochSeconds}, {<<"exp">>, EpochSeconds + 3600} diff --git a/test/elixir/test/jwtauth_test.exs b/test/elixir/test/jwtauth_test.exs index c50225cbd..2fb89c3af 100644 --- a/test/elixir/test/jwtauth_test.exs +++ b/test/elixir/test/jwtauth_test.exs @@ -103,7 +103,23 @@ defmodule JwtAuthTest do end def test_fun(alg, key) do - {:ok, token} = :jwtf.encode({[{"alg", alg}, {"typ", "JWT"}]}, {[{"sub", "couch@apache.org"}, {"_couchdb.roles", ["testing"]}]}, key) + now = DateTime.to_unix(DateTime.utc_now()) + {:ok, token} = :jwtf.encode( + { + [ + {"alg", alg}, + {"typ", "JWT"} + ] + }, + { + [ + {"nbf", now - 60}, + {"exp", now + 60}, + {"sub", "couch@apache.org"}, + {"_couchdb.roles", ["testing"] + } + ] + }, key) resp = Couch.get("/_session", headers: [authorization: "Bearer #{token}"] |