diff --git a/big_tests/tests/login_SUITE.erl b/big_tests/tests/login_SUITE.erl index d8d4a934aec..00e8b7ccdb9 100644 --- a/big_tests/tests/login_SUITE.erl +++ b/big_tests/tests/login_SUITE.erl @@ -79,10 +79,10 @@ end_per_suite(Config) -> init_per_group(GroupName, Config) when GroupName == login_scram; GroupName == login_scram_store_plain -> - case get_store_type() of - external -> - {skip, "external store type requires plain password"}; - _ -> + case supports_password_type(scram) of + false -> + {skip, "scram password type not supported"}; + true -> config_password_format(GroupName), Config2 = escalus:create_users(Config, escalus:get_users([alice, bob])), assert_password_format(GroupName, Config2) @@ -96,14 +96,21 @@ end_per_group(login_scram, Config) -> end_per_group(_GroupName, Config) -> escalus:delete_users(Config, escalus:get_users([alice, bob])). -init_per_testcase(DigestOrScram, Config) when - DigestOrScram =:= log_one_digest; DigestOrScram =:= log_non_existent_digest; - DigestOrScram =:= log_one_scram; DigestOrScram =:= log_non_existent_scram -> - case get_store_type() of - external -> - {skip, "external store type requires plain password"}; - _ -> - escalus:init_per_testcase(DigestOrScram, Config) +init_per_testcase(CaseName, Config) when + CaseName =:= log_one_digest; CaseName =:= log_non_existent_digest -> + case supports_password_type(digest) of + false -> + {skip, "digest password type not supported"}; + true -> + escalus:init_per_testcase(CaseName, Config) + end; +init_per_testcase(CaseName, Config) when + CaseName =:= log_one_scram; CaseName =:= log_non_existent_scram -> + case supports_password_type(scram) of + false -> + {skip, "scram password type not supported"}; + true -> + escalus:init_per_testcase(CaseName, Config) end; init_per_testcase(message_zlib_limit, Config) -> Listeners = [Listener @@ -206,10 +213,10 @@ message_zlib_limit(Config) -> %% Helpers %%-------------------------------------------------------------------- -get_store_type() -> +supports_password_type(PasswordType) -> XMPPDomain = escalus_ejabberd:unify_str_arg( ct:get_config({hosts, mim, domain})), - rpc(mim(), ejabberd_auth, store_type, [XMPPDomain]). + rpc(mim(), ejabberd_auth, supports_password_type, [XMPPDomain, PasswordType]). set_store_password(Type) -> XMPPDomain = escalus_ejabberd:unify_str_arg( diff --git a/big_tests/tests/oauth_SUITE.erl b/big_tests/tests/oauth_SUITE.erl index bc327d9f3dd..7d508fbfea5 100644 --- a/big_tests/tests/oauth_SUITE.erl +++ b/big_tests/tests/oauth_SUITE.erl @@ -110,14 +110,9 @@ init_per_group(GroupName, Config0) -> commands -> ejabberd_node_utils:init(Config0); _ -> Config0 end, - case get_auth_method() of - external -> - {skip, "external authentication requires plain password"}; - _ -> - config_password_format(GroupName), - Config2 = escalus:create_users(Config, escalus:get_users([bob, alice])), - assert_password_format(GroupName, Config2) - end. + config_password_format(GroupName), + Config2 = escalus:create_users(Config, escalus:get_users([bob, alice])), + assert_password_format(GroupName, Config2). end_per_group(cleanup, Config) -> escalus:delete_users(Config, escalus:get_users([alice])); @@ -360,10 +355,6 @@ extract_tokens(#xmlel{name = <<"iq">>, children = [#xmlel{name = <<"items">>} = RTD = exml_query:path(Items, [{element, <<"refresh_token">>}, cdata]), {base64:decode(ATD), base64:decode(RTD)}. -get_auth_method() -> - XMPPDomain = escalus_ejabberd:unify_str_arg(ct:get_config({hosts, mim, domain})), - rpc(mim(), ejabberd_auth, store_type, [XMPPDomain]). - set_store_password(Type) -> XMPPDomain = escalus_ejabberd:unify_str_arg(ct:get_config({hosts, mim, domain})), AuthOpts = rpc(mim(), ejabberd_config, get_local_option, [{auth_opts, XMPPDomain}]), diff --git a/doc/Advanced-configuration.md b/doc/Advanced-configuration.md index 425bc003b10..f4ef728a234 100644 --- a/doc/Advanced-configuration.md +++ b/doc/Advanced-configuration.md @@ -185,9 +185,9 @@ Retaining the default layout is recommended so that the experienced MongooseIM u ### Authentication * **auth_method** (local) - * **Description:** Chooses an authentication module or a list of modules. Modules from a list are queried one after another until one of them replies positively. - * **Valid values:** `internal` (Mnesia), `rdbms`, `external`, `anonymous`, `ldap`, `jwt`, `riak`, `http` - * **Warning:** `external`, `jwt` and `ldap` work only with `PLAIN` SASL mechanism. + * **Description:** Chooses an authentication module or a list of modules. Modules from the list are queried one after another until one of them replies positively. + * **Valid values:** `internal` (Mnesia), `rdbms`, `external`, `anonymous`, `ldap`, `jwt`, `riak`, `http`, `pki` + * **Warning:** Authentication backends support only specific SASL mechanisms, see [auth backends capabilities](#authentication-backend-capabilities). * **Examples:** `rdbms`, `[internal, anonymous]` * **auth_opts** (local) @@ -213,7 +213,7 @@ Retaining the default layout is recommended so that the experienced MongooseIM u * **sasl_mechanisms** (local) * **Description:** Specifies a list of allowed SASL mechanisms. It affects the methods announced during stream negotiation and is enforced eventually (user can't pick mechanism not listed here but available in the source code). - * **Warning:** This list is still filtered by auth backends capabilities, e.g. LDAP authentication requires a password provided via SASL PLAIN. + * **Warning:** This list is still filtered by [auth backends capabilities](#authentication-backend-capabilities) * **Valid values:** `cyrsasl_plain, cyrsasl_digest, cyrsasl_scram, cyrsasl_anonymous, cyrsasl_oauth, cyrsasl_external` * **Default:** `[cyrsasl_plain, cyrsasl_digest, cyrsasl_scram, cyrsasl_anonymous, cyrsasl_oauth, cyrsasl_external]` * **Examples:** `[cyrsasl_plain]`, `[cyrsasl_anonymous, cyrsasl_scram]` @@ -223,6 +223,24 @@ Retaining the default layout is recommended so that the experienced MongooseIM u * **Syntax:** `{extauth_instances, Count}.` * **Default:** 1 +#### Authentication backend capabilities + +The table below shows the supported SASL mechanisms for each authentication backend module. + +| | cyrsasl
plain | cyrsasl
digest | cyrsasl
scram | cyrsasl
anonymous | cyrsasl
external | +|-----------|:----------------:|:-----------------:|:----------------:|:--------------------:|:-------------------:| +| internal | x | x | x | | | +| rdbms | x | x | x | | | +| external | x | | | | | +| anonymous | x | x | x | x | | +| ldap | x | | | | | +| jwt | x | | | | | +| riak | x | x | x | | | +| http | x | x | x | | | +| pki | | | | | x | + +`cyrsasl_oauth` does not use the auth backends at all and requires the `mod_auth_token` module enabled instead. + ### Outgoing connections setup * **outgoing_pools** (local) diff --git a/doc/authentication-methods/client-certificate.md b/doc/authentication-methods/client-certificate.md index 7c3aaf86f83..cb86e41d1a0 100644 --- a/doc/authentication-methods/client-certificate.md +++ b/doc/authentication-methods/client-certificate.md @@ -53,18 +53,6 @@ For the details please refer to [XEP-0178 Best Practices for Use of SASL EXTERNA Please modify [`auth_opts` option](../Advanced-configuration.md#authentication) in MongooseIM's config file to include proper item. Also, [`pki` backend](../authentication-backends/PKI-authentication-module.md) is recommended for `SASL EXTERNAL`. -### WARNING! - -Some authentication backends may enforce `plain` password storage format, which automatically disables `SASL EXTERNAL`. -Below you may find a list of backends that are safe to use with `cyrsasl_external` mechanism. - -* `pki` -* `anonymous` -* `http` **without** `{is_external, true}` option -* `internal` -* `rdbms` -* `riak` - ### Self-signed certificates By default MongooseIM doesn't accept self-signed certs for the SASL-EXTERNAL authentication. diff --git a/src/auth/ejabberd_auth.erl b/src/auth/ejabberd_auth.erl index ad460d5e6dd..1ed0cd30eb1 100644 --- a/src/auth/ejabberd_auth.erl +++ b/src/auth/ejabberd_auth.erl @@ -50,7 +50,7 @@ is_user_exists_in_other_modules/3, remove_user/2, remove_user/3, - store_type/1, + supports_password_type/2, entropy/1 ]). @@ -122,20 +122,9 @@ get_opt(Host, Opt, Default) -> get_opt(Host, Opt) -> get_opt(Host, Opt, undefined). -store_type(Server) -> - lists:foldl( - fun(_, external) -> - external; - (M, scram) -> - case M:store_type(Server) of - external -> - external; - _Else -> - scram - end; - (M, plain) -> - M:store_type(Server) - end, plain, auth_modules(Server)). +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(Server, PasswordType) -> + lists:any(fun(M) -> M:supports_password_type(Server, PasswordType) end, auth_modules(Server)). -spec authorize(mongoose_credentials:t()) -> {ok, mongoose_credentials:t()} | {error, any()}. diff --git a/src/auth/ejabberd_auth_anonymous.erl b/src/auth/ejabberd_auth_anonymous.erl index c2e4e6eb69d..0cbb41f7ad0 100644 --- a/src/auth/ejabberd_auth_anonymous.erl +++ b/src/auth/ejabberd_auth_anonymous.erl @@ -53,7 +53,7 @@ does_user_exist/2, remove_user/2, remove_user/3, - store_type/1, + supports_password_type/2, get_vh_registered_users/2, get_vh_registered_users_number/1, get_vh_registered_users_number/2, @@ -342,9 +342,11 @@ remove_user(_LUser, _LServer) -> remove_user(_LUser, _LServer, _Password) -> {error, not_allowed}. - -store_type(_) -> - plain. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, plain) -> true; +supports_password_type(_, scram) -> true; +supports_password_type(_, digest) -> true; +supports_password_type(_, _) -> false. get_vh_registered_users_number(_LServer) -> 0. @@ -352,3 +354,5 @@ get_vh_registered_users_number(_LServer, _Opts) -> 0. %% @doc gen_auth unimplemented callbacks get_password_s(_LUser, _LServer) -> erlang:error(not_implemented). + + diff --git a/src/auth/ejabberd_auth_external.erl b/src/auth/ejabberd_auth_external.erl index 3771630adc0..40dd720eca5 100644 --- a/src/auth/ejabberd_auth_external.erl +++ b/src/auth/ejabberd_auth_external.erl @@ -44,7 +44,7 @@ does_user_exist/2, remove_user/2, remove_user/3, - store_type/1 + supports_password_type/2 ]). %% Internal @@ -88,8 +88,8 @@ check_cache_last_options(Server) -> end end. -store_type(_) -> - external. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, Type) -> Type =:= plain. -spec authorize(mongoose_credentials:t()) -> {ok, mongoose_credentials:t()} | {error, any()}. diff --git a/src/auth/ejabberd_auth_http.erl b/src/auth/ejabberd_auth_http.erl index 1b879920540..8a452714dbf 100644 --- a/src/auth/ejabberd_auth_http.erl +++ b/src/auth/ejabberd_auth_http.erl @@ -25,7 +25,7 @@ does_user_exist/2, remove_user/2, remove_user/3, - store_type/1, + supports_password_type/2, stop/1]). %% Pre-mongoose_credentials API @@ -45,18 +45,11 @@ start(_Host) -> ok. --spec store_type(binary()) -> plain | external | scram. -store_type(Server) -> - case scram:enabled(Server) of - false -> - case ejabberd_auth:get_opt(Server, is_external) of - true -> - external; - _ -> - plain - end; - true -> scram - end. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, plain) -> true; +supports_password_type(_, scram) -> true; +supports_password_type(Host, digest) -> not scram:enabled(Host); +supports_password_type(_, _) -> false. -spec authorize(mongoose_credentials:t()) -> {ok, mongoose_credentials:t()} | {error, any()}. diff --git a/src/auth/ejabberd_auth_internal.erl b/src/auth/ejabberd_auth_internal.erl index f1fff529c8f..a954fd0cb23 100644 --- a/src/auth/ejabberd_auth_internal.erl +++ b/src/auth/ejabberd_auth_internal.erl @@ -44,7 +44,7 @@ does_user_exist/2, remove_user/2, remove_user/3, - store_type/1 + supports_password_type/2 ]). -export([scram_passwords/0]). @@ -103,11 +103,11 @@ update_reg_users_counter_table(Server) -> end, mnesia:sync_dirty(F). -store_type(Server) -> - case scram:enabled(Server) of - false -> plain; - true -> scram - end. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, plain) -> true; +supports_password_type(_, scram) -> true; +supports_password_type(Host, digest) -> not scram:enabled(Host); +supports_password_type(_, _) -> false. -spec authorize(mongoose_credentials:t()) -> {ok, mongoose_credentials:t()} | {error, any()}. diff --git a/src/auth/ejabberd_auth_jwt.erl b/src/auth/ejabberd_auth_jwt.erl index b4d8ff4f881..d08fb1ba800 100644 --- a/src/auth/ejabberd_auth_jwt.erl +++ b/src/auth/ejabberd_auth_jwt.erl @@ -46,7 +46,7 @@ does_user_exist/2, remove_user/2, remove_user/3, - store_type/1 + supports_password_type/2 ]). @@ -72,8 +72,8 @@ start(Host) -> stop(_Host) -> ok. -store_type(_Server) -> - external. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, PasswordType) -> PasswordType =:= plain. -spec authorize(mongoose_credentials:t()) -> {ok, mongoose_credentials:t()} | {error, any()}. diff --git a/src/auth/ejabberd_auth_ldap.erl b/src/auth/ejabberd_auth_ldap.erl index 673140a509d..ea52502a2df 100644 --- a/src/auth/ejabberd_auth_ldap.erl +++ b/src/auth/ejabberd_auth_ldap.erl @@ -50,7 +50,7 @@ does_user_exist/2, remove_user/2, remove_user/3, - store_type/1 + supports_password_type/2 ]). %% Internal @@ -134,7 +134,8 @@ init(Host) -> State#state.password, State#state.tls_options), {ok, State}. -store_type(_) -> external. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, PasswordType) -> PasswordType =:= plain. config_change(Acc, Host, ldap, _NewConfig) -> stop(Host), diff --git a/src/auth/ejabberd_auth_pki.erl b/src/auth/ejabberd_auth_pki.erl index 42f6019e870..898bc774f45 100644 --- a/src/auth/ejabberd_auth_pki.erl +++ b/src/auth/ejabberd_auth_pki.erl @@ -23,7 +23,7 @@ %% ejabberd_gen_auth API -export([start/1, stop/1, - store_type/1, + supports_password_type/2, set_password/3, authorize/1, try_register/3, @@ -48,8 +48,8 @@ start(_) -> ok. -spec stop(Host :: ejabberd:lserver()) -> ok. stop(_) -> ok. --spec store_type(Host :: ejabberd:lserver()) -> scram | plain | external. -store_type(_) -> scram. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, PasswordType) -> PasswordType =:= cert. -spec set_password( User :: ejabberd:luser(), Server :: ejabberd:lserver(), diff --git a/src/auth/ejabberd_auth_rdbms.erl b/src/auth/ejabberd_auth_rdbms.erl index d6c79a74765..0d899c7b04b 100644 --- a/src/auth/ejabberd_auth_rdbms.erl +++ b/src/auth/ejabberd_auth_rdbms.erl @@ -44,7 +44,7 @@ does_user_exist/2, remove_user/2, remove_user/3, - store_type/1 + supports_password_type/2 ]). %% Internal @@ -84,11 +84,11 @@ start(_Host) -> stop(_Host) -> ok. -store_type(Server) -> - case scram:enabled(Server) of - false -> plain; - true -> scram - end. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, plain) -> true; +supports_password_type(_, scram) -> true; +supports_password_type(Host, digest) -> not scram:enabled(Host); +supports_password_type(_, _) -> false. -spec authorize(mongoose_credentials:t()) -> {ok, mongoose_credentials:t()} | {error, any()}. diff --git a/src/auth/ejabberd_auth_riak.erl b/src/auth/ejabberd_auth_riak.erl index 2ad58c3d835..b97f211d0fe 100644 --- a/src/auth/ejabberd_auth_riak.erl +++ b/src/auth/ejabberd_auth_riak.erl @@ -23,7 +23,7 @@ %% API -export([start/1, stop/1, - store_type/1, + supports_password_type/2, set_password/3, authorize/1, try_register/3, @@ -53,12 +53,11 @@ start(_Host) -> stop(_Host) -> ok. --spec store_type(jid:lserver()) -> plain | scram. -store_type(Host) -> - case scram:enabled(Host) of - false -> plain; - true -> scram - end. +-spec supports_password_type(jid:lserver(), cyrsasl:password_type()) -> boolean(). +supports_password_type(_, plain) -> true; +supports_password_type(_, scram) -> true; +supports_password_type(Host, digest) -> not scram:enabled(Host); +supports_password_type(_, _) -> false. -spec set_password(jid:luser(), jid:lserver(), binary()) -> ok | {error, not_allowed | invalid_jid}. diff --git a/src/auth/ejabberd_gen_auth.erl b/src/auth/ejabberd_gen_auth.erl index fdf5a9177a5..da5d73a9055 100644 --- a/src/auth/ejabberd_gen_auth.erl +++ b/src/auth/ejabberd_gen_auth.erl @@ -11,7 +11,8 @@ -callback stop(Host :: jid:lserver()) -> ok. --callback store_type(Host :: jid:lserver()) -> scram | plain | external. +-callback supports_password_type(Host :: jid:lserver(), + PasswordType :: cyrsasl:password_type()) -> boolean(). -callback set_password(User :: jid:luser(), Server :: jid:lserver(), diff --git a/src/sasl/cyrsasl.erl b/src/sasl/cyrsasl.erl index a49b6c8c1ee..002e020aae3 100644 --- a/src/sasl/cyrsasl.erl +++ b/src/sasl/cyrsasl.erl @@ -110,28 +110,19 @@ check_credentials(_State, Creds) -> -spec listmech(jid:server()) -> [mechanism()]. listmech(Host) -> - Mechs = ets:select(sasl_mechanism, - [{#sasl_mechanism{mechanism = '$1', - password_type = '$2', - _ = '_'}, - case catch ejabberd_auth:store_type(Host) of - external -> - [{'==', '$2', plain}]; - scram -> - [{'/=', '$2', digest}]; - {'EXIT', {undef, [{Module, store_type, []} | _]}} -> - ?WARNING_MSG("~p doesn't implement the function store_type/0", - [Module]), - [{'/=','$2', cert}]; - _Else -> - [{'/=','$2', cert}] - end, - ['$1']}]), - filter_mechanisms(Host, Mechs, - [{<<"ANONYMOUS">>, - fun(H)-> ejabberd_auth_anonymous:is_sasl_anonymous_enabled(H) end}, - {<<"X-OAUTH">>, - fun(H) -> gen_mod:is_loaded(H, mod_auth_token) end}]). + ets:foldl(fun(Mech, MechAcc) -> + case is_mech_supported(Host, Mech) of + true -> [Mech#sasl_mechanism.mechanism | MechAcc]; + false -> MechAcc + end + end, [], sasl_mechanism). + +is_mech_supported(Host, #sasl_mechanism{mechanism = <<"ANONYMOUS">>}) -> + ejabberd_auth_anonymous:is_sasl_anonymous_enabled(Host); +is_mech_supported(Host, #sasl_mechanism{mechanism = <<"X-OAUTH">>}) -> + gen_mod:is_loaded(Host, mod_auth_token); +is_mech_supported(Host, #sasl_mechanism{password_type = PasswordType}) -> + ejabberd_auth:supports_password_type(Host, PasswordType). -spec server_new(Service :: binary(), ServerFQDN :: jid:server(), @@ -189,18 +180,6 @@ server_step(State, ClientIn) -> {error, Error} end. -%% @doc Remove the anonymous mechanism from the list if not enabled for the -%% given host --spec filter_mechanisms(jid:server(), [mechanism()], - [{mechanism(), fun()}]) -> [mechanism()]. -filter_mechanisms(Host, Mechanisms, UnwantedMechanisms) -> - lists:foldl(fun({Mechanism, FilterFun}, Acc) -> - case FilterFun(Host) of - true -> Acc; - false -> Acc -- [Mechanism] - end - end, Mechanisms, UnwantedMechanisms). - get_mechanisms() -> Default = [cyrsasl_plain, cyrsasl_digest, diff --git a/src/sasl/cyrsasl_external.erl b/src/sasl/cyrsasl_external.erl index 2c0eaec9a92..3072ac827d3 100644 --- a/src/sasl/cyrsasl_external.erl +++ b/src/sasl/cyrsasl_external.erl @@ -45,7 +45,7 @@ stop() -> -spec mech_new(Host :: ejabberd:server(), Creds :: mongoose_credentials:t()) -> {ok, sasl_external_state()}. -mech_new(Host, Creds) -> +mech_new(_Host, Creds) -> Cert = mongoose_credentials:get(Creds, client_cert, no_cert), maybe_extract_certs(Cert, Creds). diff --git a/test/auth_external_SUITE.erl b/test/auth_external_SUITE.erl index 12d5d68966c..32496be5d3c 100644 --- a/test/auth_external_SUITE.erl +++ b/test/auth_external_SUITE.erl @@ -20,7 +20,7 @@ all_tests() -> does_user_exist, get_password_returns_false_if_no_cache, get_password_s_returns_empty_bin_if_no_cache, - store_type_external + supported_password_types ]. init_per_suite(C) -> @@ -71,8 +71,9 @@ get_password_returns_false_if_no_cache(_C) -> get_password_s_returns_empty_bin_if_no_cache(_C) -> <<"">> = ?AUTH_MOD:get_password_s(random_binary(8), domain()). -store_type_external(_C) -> - external = ?AUTH_MOD:store_type(domain()). +supported_password_types(_C) -> + [true, false, false, false] = + [?AUTH_MOD:supports_password_type(domain(), PT) || PT <- [plain, digest, scram, cert]]. given_user_registered() -> {U, P} = UP = gen_user(), diff --git a/test/auth_http_SUITE.erl b/test/auth_http_SUITE.erl index 03f7e520923..59552da0d2e 100644 --- a/test/auth_http_SUITE.erl +++ b/test/auth_http_SUITE.erl @@ -45,7 +45,8 @@ all_tests() -> try_register, get_password, is_user_exists, - remove_user + remove_user, + supported_password_types ]. suite() -> @@ -171,6 +172,14 @@ remove_user(_Config) -> {error, not_exists} = ejabberd_auth_http:remove_user(<<"toremove3">>, ?DOMAIN1, <<"wrongpass">>). +supported_password_types(Config) -> + DigestSupported = case lists:keyfind(scram_group, 1, Config) of + {_, true} -> false; + _ -> true + end, + [true, DigestSupported, true, false] = + [ejabberd_auth_http:supports_password_type(?DOMAIN1, PT) || PT <- [plain, digest, scram, cert]]. + %%-------------------------------------------------------------------- %% Helpers %%-------------------------------------------------------------------- diff --git a/test/auth_jwt_SUITE.erl b/test/auth_jwt_SUITE.erl index 960324e7d74..94b5f0ce38a 100644 --- a/test/auth_jwt_SUITE.erl +++ b/test/auth_jwt_SUITE.erl @@ -33,7 +33,7 @@ generic_tests() -> remove_user, get_vh_registered_users_number, get_vh_registered_users, - store_type, + supported_password_types, dirty_get_registered_users ]. @@ -137,8 +137,9 @@ get_vh_registered_users_number(_C) -> get_vh_registered_users(_C) -> [] = ejabberd_auth_jwt:get_vh_registered_users(?DOMAIN1, []). -store_type(_C) -> - external = ejabberd_auth_jwt:store_type(?DOMAIN1). +supported_password_types(_C) -> + [true, false, false, false] = + [ejabberd_auth_jwt:supports_password_type(?DOMAIN1, PT) || PT <- [plain, digest, scram, cert]]. dirty_get_registered_users(_C) -> [] = ejabberd_auth_jwt:dirty_get_registered_users().