diff options
Diffstat (limited to 'src/jwtf/test/jwtf_tests.erl')
-rw-r--r-- | src/jwtf/test/jwtf_tests.erl | 317 |
1 files changed, 0 insertions, 317 deletions
diff --git a/src/jwtf/test/jwtf_tests.erl b/src/jwtf/test/jwtf_tests.erl deleted file mode 100644 index ba944f7c7..000000000 --- a/src/jwtf/test/jwtf_tests.erl +++ /dev/null @@ -1,317 +0,0 @@ -% Licensed under the Apache License, Version 2.0 (the "License"); you may not -% use this file except in compliance with the License. You may obtain a copy of -% the License at -% -% http://www.apache.org/licenses/LICENSE-2.0 -% -% Unless required by applicable law or agreed to in writing, software -% distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -% WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -% License for the specific language governing permissions and limitations under -% the License. - --module(jwtf_tests). - --include_lib("eunit/include/eunit.hrl"). --include_lib("public_key/include/public_key.hrl"). - -encode(Header0, Payload0) -> - Header1 = b64url:encode(jiffy:encode(Header0)), - Payload1 = b64url:encode(jiffy:encode(Payload0)), - Sig = b64url:encode(<<"bad">>), - <<Header1/binary, $., Payload1/binary, $., Sig/binary>>. - -valid_header() -> - {[{<<"typ">>, <<"JWT">>}, {<<"alg">>, <<"RS256">>}]}. - -jwt_io_pubkey() -> - PublicKeyPEM = <<"-----BEGIN PUBLIC KEY-----\n" - "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDdlatRjRjogo3WojgGH" - "FHYLugdUWAY9iR3fy4arWNA1KoS8kVw33cJibXr8bvwUAUparCwlvdbH6" - "dvEOfou0/gCFQsHUfQrSDv+MuSUMAe8jzKE4qW+jK+xQU9a03GUnKHkkl" - "e+Q0pX/g6jXZ7r1/xAK5Do2kQ+X5xK9cipRgEKwIDAQAB\n" - "-----END PUBLIC KEY-----\n">>, - [PEMEntry] = public_key:pem_decode(PublicKeyPEM), - 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">>}}, - jwtf:decode(Encoded, [typ], nil)). - - -invalid_typ_test() -> - Encoded = encode({[{<<"typ">>, <<"NOPE">>}]}, []), - ?assertEqual({error, {bad_request,<<"Invalid typ header parameter">>}}, - jwtf:decode(Encoded, [typ], nil)). - - -missing_alg_test() -> - Encoded = encode({[]}, []), - ?assertEqual({error, {bad_request,<<"Missing alg header parameter">>}}, - jwtf:decode(Encoded, [alg], nil)). - - -invalid_alg_test() -> - Encoded = encode({[{<<"alg">>, <<"NOPE">>}]}, []), - ?assertEqual({error, {bad_request,<<"Invalid alg header parameter">>}}, - jwtf:decode(Encoded, [alg], nil)). - - -missing_iss_test() -> - Encoded = encode(valid_header(), {[]}), - ?assertEqual({error, {bad_request,<<"Missing iss claim">>}}, - jwtf:decode(Encoded, [{iss, right}], nil)). - - -invalid_iss_test() -> - Encoded = encode(valid_header(), {[{<<"iss">>, <<"wrong">>}]}), - ?assertEqual({error, {bad_request,<<"Invalid iss claim">>}}, - jwtf:decode(Encoded, [{iss, right}], nil)). - - -missing_iat_test() -> - Encoded = encode(valid_header(), {[]}), - ?assertEqual({error, {bad_request,<<"Missing iat claim">>}}, - jwtf:decode(Encoded, [iat], nil)). - - -invalid_iat_test() -> - Encoded = encode(valid_header(), {[{<<"iat">>, <<"hello">>}]}), - ?assertEqual({error, {bad_request,<<"Invalid iat claim">>}}, - jwtf:decode(Encoded, [iat], nil)). - - -missing_nbf_test() -> - Encoded = encode(valid_header(), {[]}), - ?assertEqual({error, {bad_request,<<"Missing nbf claim">>}}, - jwtf:decode(Encoded, [nbf], nil)). - - -invalid_nbf_test() -> - Encoded = encode(valid_header(), {[{<<"nbf">>, 2 * now_seconds()}]}), - ?assertEqual({error, {unauthorized, <<"nbf not in past">>}}, - jwtf:decode(Encoded, [nbf], nil)). - - -missing_exp_test() -> - Encoded = encode(valid_header(), {[]}), - ?assertEqual({error, {bad_request, <<"Missing exp claim">>}}, - jwtf:decode(Encoded, [exp], nil)). - - -invalid_exp_test() -> - Encoded = encode(valid_header(), {[{<<"exp">>, 0}]}), - ?assertEqual({error, {unauthorized, <<"exp not in future">>}}, - jwtf:decode(Encoded, [exp], nil)). - - -missing_kid_test() -> - Encoded = encode({[]}, {[]}), - ?assertEqual({error, {bad_request, <<"Missing kid claim">>}}, - jwtf:decode(Encoded, [kid], nil)). - - -public_key_not_found_test() -> - Encoded = encode( - {[{<<"alg">>, <<"RS256">>}, {<<"kid">>, <<"1">>}]}, - {[]}), - KS = fun(_, _) -> throw(not_found) end, - Expected = {error, not_found}, - ?assertEqual(Expected, jwtf:decode(Encoded, [], KS)). - - -bad_rs256_sig_test() -> - Encoded = encode( - {[{<<"typ">>, <<"JWT">>}, {<<"alg">>, <<"RS256">>}]}, - {[]}), - KS = fun(<<"RS256">>, undefined) -> jwt_io_pubkey() end, - ?assertEqual({error, {bad_request, <<"Bad signature">>}}, - jwtf:decode(Encoded, [], KS)). - - -bad_hs256_sig_test() -> - Encoded = encode( - {[{<<"typ">>, <<"JWT">>}, {<<"alg">>, <<"HS256">>}]}, - {[]}), - KS = fun(<<"HS256">>, undefined) -> <<"bad">> end, - ?assertEqual({error, {bad_request, <<"Bad HMAC">>}}, - jwtf:decode(Encoded, [], KS)). - - -malformed_token_test() -> - ?assertEqual({error, {bad_request, <<"Malformed token">>}}, - jwtf:decode(<<"a.b.c.d">>, [], 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 -hs256_test() -> - EncodedToken = <<"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMzQ1Ni" - "J9.eyJpc3MiOiJodHRwczovL2Zvby5jb20iLCJpYXQiOjAsImV4cCI" - "6MTAwMDAwMDAwMDAwMDAsImtpZCI6ImJhciJ9.iS8AH11QHHlczkBn" - "Hl9X119BYLOZyZPllOVhSBZ4RZs">>, - KS = fun(<<"HS256">>, <<"123456">>) -> <<"secret">> end, - Checks = [{iss, <<"https://foo.com">>}, iat, exp, typ, alg, kid], - ?assertMatch({ok, _}, catch jwtf:decode(EncodedToken, Checks, KS)). - - -%% pip install PyJWT -%% > import jwt -%% > jwt.encode({'foo':'bar'}, 'secret', algorithm='HS384') -hs384_test() -> - EncodedToken = <<"eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYXIif" - "Q.2quwghs6I56GM3j7ZQbn-ASZ53xdBqzPzTDHm_CtVec32LUy-Ezy" - "L3JjIe7WjL93">>, - KS = fun(<<"HS384">>, _) -> <<"secret">> end, - ?assertMatch({ok, {[{<<"foo">>,<<"bar">>}]}}, - catch jwtf:decode(EncodedToken, [], KS)). - - -%% pip install PyJWT -%% > import jwt -%% > jwt.encode({'foo':'bar'}, 'secret', algorithm='HS512') -hs512_test() -> - EncodedToken = <<"eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJmb28iOiJiYX" - "IifQ.WePl7achkd0oGNB8XRF_LJwxlyiPZqpdNgdKpDboAjSTsW" - "q-aOGNynTp8TOv8KjonFym8vwFwppXOLoLXbkIaQ">>, - KS = fun(<<"HS512">>, _) -> <<"secret">> end, - ?assertMatch({ok, {[{<<"foo">>,<<"bar">>}]}}, - catch jwtf:decode(EncodedToken, [], KS)). - - -%% jwt.io generated -rs256_test() -> - EncodedToken = <<"eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0N" - "TY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.Ek" - "N-DOsnsuRjRO6BxXemmJDm3HbxrbRzXglbN2S4sOkopdU4IsDxTI8j" - "O19W_A4K8ZPJijNLis4EZsHeY559a4DFOd50_OqgHGuERTqYZyuhtF" - "39yxJPAjUESwxk2J5k_4zM3O-vtd1Ghyo4IbqKKSy6J9mTniYJPenn" - "5-HIirE">>, - - Checks = [sig, alg], - KS = fun(<<"RS256">>, undefined) -> jwt_io_pubkey() end, - - ExpectedPayload = {[ - {<<"sub">>, <<"1234567890">>}, - {<<"name">>, <<"John Doe">>}, - {<<"admin">>, true} - ]}, - - ?assertMatch({ok, ExpectedPayload}, jwtf:decode(EncodedToken, Checks, KS)). - - -encode_missing_alg_test() -> - ?assertEqual({error, {bad_request, <<"Missing alg header parameter">>}}, - jwtf:encode({[]}, {[]}, <<"foo">>)). - - -encode_invalid_alg_test() -> - ?assertEqual({error, {bad_request, <<"Invalid alg header parameter">>}}, - jwtf:encode({[{<<"alg">>, <<"BOGUS">>}]}, {[]}, <<"foo">>)). - - -encode_decode_test_() -> - [{Alg, encode_decode(Alg)} || Alg <- jwtf:valid_algorithms()]. - - -encode_decode(Alg) -> - {EncodeKey, DecodeKey} = case jwtf:verification_algorithm(Alg) of - {public_key, _Algorithm} -> - create_keypair(); - {hmac, _Algorithm} -> - Key = <<"a-super-secret-key">>, - {Key, Key} - end, - Claims = claims(), - {ok, Encoded} = jwtf:encode(header(Alg), Claims, EncodeKey), - KS = fun(_, _) -> DecodeKey end, - {ok, Decoded} = jwtf:decode(Encoded, [], KS), - ?_assertMatch(Claims, Decoded). - - -header(Alg) -> - {[ - {<<"typ">>, <<"JWT">>}, - {<<"alg">>, Alg}, - {<<"kid">>, <<"20170520-00:00:00">>} - ]}. - - -claims() -> - EpochSeconds = os:system_time(second), - {[ - {<<"iat">>, EpochSeconds}, - {<<"exp">>, EpochSeconds + 3600} - ]}. - -create_keypair() -> - %% https://tools.ietf.org/html/rfc7517#appendix-C - N = decode(<<"t6Q8PWSi1dkJj9hTP8hNYFlvadM7DflW9mWepOJhJ66w7nyoK1gPNqFMSQRy" - "O125Gp-TEkodhWr0iujjHVx7BcV0llS4w5ACGgPrcAd6ZcSR0-Iqom-QFcNP" - "8Sjg086MwoqQU_LYywlAGZ21WSdS_PERyGFiNnj3QQlO8Yns5jCtLCRwLHL0" - "Pb1fEv45AuRIuUfVcPySBWYnDyGxvjYGDSM-AqWS9zIQ2ZilgT-GqUmipg0X" - "OC0Cc20rgLe2ymLHjpHciCKVAbY5-L32-lSeZO-Os6U15_aXrk9Gw8cPUaX1" - "_I8sLGuSiVdt3C_Fn2PZ3Z8i744FPFGGcG1qs2Wz-Q">>), - E = decode(<<"AQAB">>), - D = decode(<<"GRtbIQmhOZtyszfgKdg4u_N-R_mZGU_9k7JQ_jn1DnfTuMdSNprTeaSTyWfS" - "NkuaAwnOEbIQVy1IQbWVV25NY3ybc_IhUJtfri7bAXYEReWaCl3hdlPKXy9U" - "vqPYGR0kIXTQRqns-dVJ7jahlI7LyckrpTmrM8dWBo4_PMaenNnPiQgO0xnu" - "ToxutRZJfJvG4Ox4ka3GORQd9CsCZ2vsUDmsXOfUENOyMqADC6p1M3h33tsu" - "rY15k9qMSpG9OX_IJAXmxzAh_tWiZOwk2K4yxH9tS3Lq1yX8C1EWmeRDkK2a" - "hecG85-oLKQt5VEpWHKmjOi_gJSdSgqcN96X52esAQ">>), - RSAPrivateKey = #'RSAPrivateKey'{ - modulus = N, - publicExponent = E, - privateExponent = D - }, - RSAPublicKey = #'RSAPublicKey'{ - modulus = N, - publicExponent = E - }, - {RSAPrivateKey, RSAPublicKey}. - - -decode(Goop) -> - crypto:bytes_to_integer(b64url:decode(Goop)). - - -now_seconds() -> - {MegaSecs, Secs, _MicroSecs} = os:timestamp(), - MegaSecs * 1000000 + Secs. |