1: -module(auth_jwt_SUITE). 2: -compile([export_all, nowarn_export_all]). 3: 4: -include_lib("common_test/include/ct.hrl"). 5: 6: -define(DOMAIN, <<"localhost">>). 7: -define(HOST_TYPE, <<"test host type">>). 8: -define(USERNAME, <<"10857839">>). 9: -define(WRONG_USERNAME, <<"alice">>). 10: -define(JWT_KEY, <<"testtesttest">>). 11: %%-------------------------------------------------------------------- 12: %% Suite configuration 13: %%-------------------------------------------------------------------- 14: 15: all() -> 16: [{group, generic}, {group, public_key}]. 17: 18: groups() -> 19: [ 20: {generic, [parallel], generic_tests()}, 21: {public_key, [], public_key_tests()} 22: ]. 23: 24: generic_tests() -> 25: [ 26: check_password_succeeds_for_correct_token, 27: check_password_fails_for_wrong_token, 28: check_password_fails_for_correct_token_but_wrong_username, 29: authorize, 30: does_user_exist, 31: supported_sasl_mechanisms 32: ]. 33: 34: public_key_tests() -> 35: [ 36: check_password_succeeds_for_pubkey_signed_token 37: ]. 38: 39: suite() -> 40: []. 41: 42: %%-------------------------------------------------------------------- 43: %% Init & teardown 44: %%-------------------------------------------------------------------- 45: 46: init_per_suite(Config) -> 47: application:ensure_all_started(jid), 48: Config. 49: 50: end_per_suite(Config) -> 51: unset_auth_opts(), 52: Config. 53: 54: init_per_group(public_key, Config) -> 55: Root = small_path_helper:repo_dir(Config), 56: PrivkeyPath = filename:join([Root, "tools", "ssl", "mongooseim", "privkey.pem"]), 57: PubkeyPath = filename:join([Root, "tools", "ssl", "mongooseim", "pubkey.pem"]), 58: {ok, PrivKey} = file:read_file(PrivkeyPath), 59: set_auth_opts({file, PubkeyPath}, "RS256", bookingNumber), 60: ok = ejabberd_auth_jwt:start(?HOST_TYPE), 61: [{priv_key, PrivKey} | Config]; 62: init_per_group(_, Config) -> 63: set_auth_opts({value, ?JWT_KEY}, "HS256", bookingNumber), 64: ok = ejabberd_auth_jwt:start(?HOST_TYPE), 65: Config. 66: 67: end_per_group(_, Config) -> 68: ok = ejabberd_auth_jwt:stop(?HOST_TYPE), 69: Config. 70: 71: 72: init_per_testcase(_CaseName, Config) -> 73: Config. 74: 75: end_per_testcase(_CaseName, Config) -> 76: Config. 77: 78: %%-------------------------------------------------------------------- 79: %% Authentication tests 80: %%-------------------------------------------------------------------- 81: 82: check_password_succeeds_for_correct_token(_Config) -> 83: true = ejabberd_auth_jwt:check_password(?HOST_TYPE, ?USERNAME, ?DOMAIN, 84: generate_token(hs256, 0, ?JWT_KEY)). 85: 86: check_password_fails_for_wrong_token(_C) -> 87: false = ejabberd_auth_jwt:check_password(?HOST_TYPE, ?USERNAME, ?DOMAIN, 88: generate_token(hs256, 60, ?JWT_KEY)). 89: 90: check_password_fails_for_correct_token_but_wrong_username(_C) -> 91: false = ejabberd_auth_jwt:check_password(?HOST_TYPE, ?WRONG_USERNAME, ?DOMAIN, 92: generate_token(hs256, 0, ?JWT_KEY)). 93: 94: authorize(_C) -> 95: Creds0 = mongoose_credentials:new(?DOMAIN, ?HOST_TYPE), 96: Creds = mongoose_credentials:extend(Creds0, [{username, ?USERNAME}, 97: {password, generate_token(hs256, 0, ?JWT_KEY)}, 98: {digest, fake}, 99: {digest_gen, fun(A) -> A end}]), 100: {ok, Creds2} = ejabberd_auth_jwt:authorize(Creds), 101: ejabberd_auth_jwt = mongoose_credentials:get(Creds2, auth_module). 102: 103: does_user_exist(_Config) -> 104: true = ejabberd_auth_jwt:does_user_exist(?HOST_TYPE, <<"madhatter">>, ?DOMAIN). 105: 106: supported_sasl_mechanisms(_C) -> 107: Modules = [cyrsasl_plain, cyrsasl_digest, cyrsasl_external, 108: cyrsasl_scram_sha1, cyrsasl_scram_sha224, cyrsasl_scram_sha256, 109: cyrsasl_scram_sha384, cyrsasl_scram_sha512], 110: [true, false, false, false, false, false, false, false] = 111: [ejabberd_auth_jwt:supports_sasl_module(?DOMAIN, Mod) || Mod <- Modules]. 112: 113: check_password_succeeds_for_pubkey_signed_token(C) -> 114: Key = proplists:get_value(priv_key, C), 115: true = ejabberd_auth_jwt:check_password(?HOST_TYPE, ?USERNAME, ?DOMAIN, 116: generate_token(rs256, 0, Key)). 117: 118: %%-------------------------------------------------------------------- 119: %% Helpers 120: %%-------------------------------------------------------------------- 121: 122: set_auth_opts(Secret, Algorithm, Key) -> 123: mongoose_config:set_opt({auth, ?HOST_TYPE}, #{jwt => #{secret => Secret, 124: algorithm => Algorithm, 125: username_key => Key}}). 126: 127: unset_auth_opts() -> 128: mongoose_config:unset_opt({auth, ?HOST_TYPE}). 129: 130: generate_token(Alg, NbfDelta, Key) -> 131: Now = erlang:system_time(second), 132: Data = #{bookingNumber => ?USERNAME, 133: exp => Now + 60, 134: nbf => Now + NbfDelta, 135: iat => Now}, 136: jwerl:sign(Data, Alg, Key).