summaryrefslogtreecommitdiff
path: root/src/jwtf/test/jwtf_tests.erl
diff options
context:
space:
mode:
Diffstat (limited to 'src/jwtf/test/jwtf_tests.erl')
-rw-r--r--src/jwtf/test/jwtf_tests.erl317
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.