feat: extract attrs field from http and jwt auth response

This commit is contained in:
zmstone 2024-03-19 19:53:16 +01:00
parent f9d51484cc
commit cc4805b1ac
5 changed files with 29 additions and 13 deletions

View File

@ -1726,9 +1726,21 @@ do_authenticate(Credential, #channel{clientinfo = ClientInfo} = Channel) ->
{error, emqx_reason_codes:connack_error(Reason)} {error, emqx_reason_codes:connack_error(Reason)}
end. end.
merge_auth_result(ClientInfo, AuthResult) when is_map(ClientInfo) andalso is_map(AuthResult) -> %% Merge authentication result into ClientInfo
%% Authentication result may include:
%% 1. `is_superuser': The superuser flag from various backends
%% 2. `acl': ACL rules from JWT, HTTP auth backend
%% 3. `attrs': Extra client attributes from JWT, HTTP auth backend
merge_auth_result(ClientInfo, AuthResult0) when is_map(ClientInfo) andalso is_map(AuthResult0) ->
IsSuperuser = maps:get(is_superuser, AuthResult, false), IsSuperuser = maps:get(is_superuser, AuthResult, false),
maps:merge(ClientInfo, AuthResult#{is_superuser => IsSuperuser}). AuthResult = maps:without([attrs], AuthResult0),
Attrs0 = maps:get(attrs, ClientInfo, #{}),
Attrs1 = maps:get(attrs, AuthResult0, #{}),
Attrs = maps:merge(Attrs0, Attrs1),
maps:merge(
ClientInfo#{attrs => Attrs},
AuthResult#{is_superuser => IsSuperuser}
).
%%-------------------------------------------------------------------- %%--------------------------------------------------------------------
%% Process Topic Alias %% Process Topic Alias

View File

@ -197,9 +197,10 @@ handle_response(Headers, Body) ->
{ok, NBody} -> {ok, NBody} ->
case maps:get(<<"result">>, NBody, <<"ignore">>) of case maps:get(<<"result">>, NBody, <<"ignore">>) of
<<"allow">> -> <<"allow">> ->
Res = emqx_authn_utils:is_superuser(NBody), IsSuperuser = emqx_authn_utils:is_superuser(NBody),
%% TODO: Return by user property Attrs = maps:get(<<"attrs">>, NBody, #{}),
{ok, Res#{user_property => maps:get(<<"user_property">>, NBody, #{})}}; Result = maps:merge(IsSuperuser, Attrs),
{ok, Result};
<<"deny">> -> <<"deny">> ->
{error, not_authorized}; {error, not_authorized};
<<"ignore">> -> <<"ignore">> ->

View File

@ -533,7 +533,7 @@ samples() ->
{ok, Req, State} {ok, Req, State}
end, end,
config_params => #{}, config_params => #{},
result => {ok, #{is_superuser => false, user_property => #{}}} result => {ok, #{is_superuser => false, attrs => #{}}}
}, },
%% get request with json body response %% get request with json body response
@ -548,7 +548,7 @@ samples() ->
{ok, Req, State} {ok, Req, State}
end, end,
config_params => #{}, config_params => #{},
result => {ok, #{is_superuser => true, user_property => #{}}} result => {ok, #{is_superuser => true, attrs => #{}}}
}, },
%% get request with url-form-encoded body response %% get request with url-form-encoded body response
@ -566,7 +566,7 @@ samples() ->
{ok, Req, State} {ok, Req, State}
end, end,
config_params => #{}, config_params => #{},
result => {ok, #{is_superuser => true, user_property => #{}}} result => {ok, #{is_superuser => true, attrs => #{}}}
}, },
%% get request with response of unknown encoding %% get request with response of unknown encoding
@ -608,7 +608,7 @@ samples() ->
<<"method">> => <<"post">>, <<"method">> => <<"post">>,
<<"headers">> => #{<<"content-type">> => <<"application/json">>} <<"headers">> => #{<<"content-type">> => <<"application/json">>}
}, },
result => {ok, #{is_superuser => false, user_property => #{}}} result => {ok, #{is_superuser => false, attrs => #{}}}
}, },
%% simple post request, application/x-www-form-urlencoded %% simple post request, application/x-www-form-urlencoded
@ -634,7 +634,7 @@ samples() ->
<<"application/x-www-form-urlencoded">> <<"application/x-www-form-urlencoded">>
} }
}, },
result => {ok, #{is_superuser => false, user_property => #{}}} result => {ok, #{is_superuser => false, attrs => #{}}}
}, },
%% simple post request for placeholders, application/json %% simple post request for placeholders, application/json
@ -669,7 +669,7 @@ samples() ->
<<"cert_common_name">> => ?PH_CERT_CN_NAME <<"cert_common_name">> => ?PH_CERT_CN_NAME
} }
}, },
result => {ok, #{is_superuser => false, user_property => #{}}} result => {ok, #{is_superuser => false, attrs => #{}}}
}, },
%% custom headers %% custom headers

View File

@ -1,7 +1,7 @@
%% -*- mode: erlang -*- %% -*- mode: erlang -*-
{application, emqx_auth_jwt, [ {application, emqx_auth_jwt, [
{description, "EMQX JWT Authentication and Authorization"}, {description, "EMQX JWT Authentication and Authorization"},
{vsn, "0.2.0"}, {vsn, "0.3.0"},
{registered, []}, {registered, []},
{mod, {emqx_auth_jwt_app, []}}, {mod, {emqx_auth_jwt_app, []}},
{applications, [ {applications, [

View File

@ -220,7 +220,10 @@ verify(JWT, JWKs, VerifyClaims, AclClaimName) ->
case do_verify(JWT, JWKs, VerifyClaims) of case do_verify(JWT, JWKs, VerifyClaims) of
{ok, Extra} -> {ok, Extra} ->
try try
{ok, acl(Extra, AclClaimName)} ACL = acl(Extra, AclClaimName),
Attrs = maps:get(<<"attrs">>, Extra, #{}),
Result = maps:merge(Attrs, ACL),
{ok, Result}
catch catch
throw:{bad_acl_rule, Reason} -> throw:{bad_acl_rule, Reason} ->
%% it's a invalid token, so ok to log %% it's a invalid token, so ok to log