diff --git a/apps/emqx/src/emqx_authentication.erl b/apps/emqx/src/emqx_authentication.erl index 017bc982d..ec8a1c113 100644 --- a/apps/emqx/src/emqx_authentication.erl +++ b/apps/emqx/src/emqx_authentication.erl @@ -661,7 +661,7 @@ do_authenticate( _ -> ok end, - {ok, Result} + {stop, Result} catch Class:Reason:Stacktrace -> ?TRACE_AUTHN(warning, "authenticator_error", #{ diff --git a/apps/emqx/test/emqx_authentication_SUITE.erl b/apps/emqx/test/emqx_authentication_SUITE.erl index 3588f1c8e..77789dedd 100644 --- a/apps/emqx/test/emqx_authentication_SUITE.erl +++ b/apps/emqx/test/emqx_authentication_SUITE.erl @@ -106,6 +106,10 @@ authenticate(#{username := <<"good">>}, _State) -> {ok, #{is_superuser => true}}; authenticate(#{username := <<"ignore">>}, _State) -> ignore; +authenticate(#{username := <<"emqx_authn_ignore_for_hook_good">>}, _State) -> + ignore; +authenticate(#{username := <<"emqx_authn_ignore_for_hook_bad">>}, _State) -> + ignore; authenticate(#{username := _}, _State) -> {error, bad_username_or_password}. @@ -117,6 +121,10 @@ hook_authenticate(#{username := <<"hook_user_finally_good">>}, _AuthResult) -> {stop, {ok, ?NOT_SUPERUSER}}; hook_authenticate(#{username := <<"hook_user_finally_bad">>}, _AuthResult) -> {stop, {error, invalid_username}}; +hook_authenticate(#{username := <<"emqx_authn_ignore_for_hook_good">>}, _AuthResult) -> + {ok, {ok, ?NOT_SUPERUSER}}; +hook_authenticate(#{username := <<"emqx_authn_ignore_for_hook_bad">>}, _AuthResult) -> + {stop, {error, invalid_username}}; hook_authenticate(_ClientId, AuthResult) -> {ok, AuthResult}. @@ -595,12 +603,17 @@ t_combine_authn_and_callback(Config) when is_list(Config) -> ?assertAuthFailureForUser(bad), ?assertAuthFailureForUser(ignore), - %% lower-priority hook can overrride auth result, - %% because emqx_authentication permits/denies with {ok, ...} - ?assertAuthSuccessForUser(hook_user_good), - ?assertAuthFailureForUser(hook_user_bad), - ?assertAuthSuccessForUser(hook_user_finally_good), + %% lower-priority hook can overrride emqx_authentication result + %% for ignored users + ?assertAuthSuccessForUser(emqx_authn_ignore_for_hook_good), + ?assertAuthFailureForUser(emqx_authn_ignore_for_hook_bad), + + %% lower-priority hook cannot overrride + %% successful/unsuccessful emqx_authentication result + ?assertAuthFailureForUser(hook_user_finally_good), ?assertAuthFailureForUser(hook_user_finally_bad), + ?assertAuthFailureForUser(hook_user_good), + ?assertAuthFailureForUser(hook_user_bad), ok = unhook(); t_combine_authn_and_callback({'end', Config}) -> diff --git a/changes/v5.0.15/fix-9785.en.md b/changes/v5.0.15/fix-9785.en.md new file mode 100644 index 000000000..8af14b1ed --- /dev/null +++ b/changes/v5.0.15/fix-9785.en.md @@ -0,0 +1 @@ +Stop authentication hook chain if `emqx_authentication` provides a definitive result. diff --git a/changes/v5.0.15/fix-9785.zh.md b/changes/v5.0.15/fix-9785.zh.md new file mode 100644 index 000000000..6aa84f755 --- /dev/null +++ b/changes/v5.0.15/fix-9785.zh.md @@ -0,0 +1 @@ +如果 `emqx_authentication` 提供了确定的结果,则停止认证钩子链。