diff --git a/apps/emqx_auth_http/src/emqx_auth_http.app.src b/apps/emqx_auth_http/src/emqx_auth_http.app.src index c5ad881d1..4f625140b 100644 --- a/apps/emqx_auth_http/src/emqx_auth_http.app.src +++ b/apps/emqx_auth_http/src/emqx_auth_http.app.src @@ -1,7 +1,7 @@ %% -*- mode: erlang -*- {application, emqx_auth_http, [ {description, "EMQX External HTTP API Authentication and Authorization"}, - {vsn, "0.2.1"}, + {vsn, "0.2.2"}, {registered, []}, {mod, {emqx_auth_http_app, []}}, {applications, [ diff --git a/apps/emqx_auth_http/src/emqx_authz_http.erl b/apps/emqx_auth_http/src/emqx_authz_http.erl index ffc339393..49296f690 100644 --- a/apps/emqx_auth_http/src/emqx_authz_http.erl +++ b/apps/emqx_auth_http/src/emqx_authz_http.erl @@ -38,6 +38,10 @@ -compile(nowarn_export_all). -endif. +-define(VAR_ACCESS, "access"). +-define(LEGACY_SUBSCRIBE_ACTION, 1). +-define(LEGACY_PUBLISH_ACTION, 2). + -define(ALLOWED_VARS, [ ?VAR_USERNAME, ?VAR_CLIENTID, @@ -48,6 +52,7 @@ ?VAR_ACTION, ?VAR_CERT_SUBJECT, ?VAR_CERT_CN_NAME, + ?VAR_ACCESS, ?VAR_NS_CLIENT_ATTRS ]). @@ -214,7 +219,7 @@ generate_request( _ -> NPath = append_query(Path, Query), NBody = serialize_body( - proplists:get_value(<<"accept">>, Headers, <<"application/json">>), + proplists:get_value(<<"content-type">>, Headers, <<"application/json">>), Body ), {NPath, Headers, NBody} @@ -248,7 +253,14 @@ serialize_body(<<"application/x-www-form-urlencoded">>, Body) -> client_vars(Client, Action, Topic) -> Vars = emqx_authz_utils:vars_for_rule_query(Client, Action), - Vars#{topic => Topic}. + add_legacy_access_var(Vars#{topic => Topic}). + +add_legacy_access_var(#{action := subscribe} = Vars) -> + Vars#{access => ?LEGACY_SUBSCRIBE_ACTION}; +add_legacy_access_var(#{action := publish} = Vars) -> + Vars#{access => ?LEGACY_PUBLISH_ACTION}; +add_legacy_access_var(Vars) -> + Vars. to_list(A) when is_atom(A) -> atom_to_list(A); diff --git a/apps/emqx_auth_http/test/emqx_authz_http_SUITE.erl b/apps/emqx_auth_http/test/emqx_authz_http_SUITE.erl index 70fda514f..93990791d 100644 --- a/apps/emqx_auth_http/test/emqx_authz_http_SUITE.erl +++ b/apps/emqx_auth_http/test/emqx_authz_http_SUITE.erl @@ -199,6 +199,7 @@ t_query_params(_Config) -> mountpoint := <<"MOUNTPOINT">>, topic := <<"t/1">>, action := <<"publish">>, + access := <<"2">>, qos := <<"1">>, retain := <<"false">> } = cowboy_req:match_qs( @@ -210,6 +211,7 @@ t_query_params(_Config) -> mountpoint, topic, action, + access, qos, retain ], @@ -227,6 +229,7 @@ t_query_params(_Config) -> "mountpoint=${mountpoint}&" "topic=${topic}&" "action=${action}&" + "access=${access}&" "qos=${qos}&" "retain=${retain}" >> @@ -261,6 +264,7 @@ t_path(_Config) -> "MOUNTPOINT/" "t%2F1/" "publish/" + "2/" "1/" "false" >>, @@ -278,6 +282,7 @@ t_path(_Config) -> "${mountpoint}/" "${topic}/" "${action}/" + "${access}/" "${qos}/" "${retain}" >> @@ -318,6 +323,7 @@ t_json_body(_Config) -> <<"mountpoint">> := <<"MOUNTPOINT">>, <<"topic">> := <<"t">>, <<"action">> := <<"publish">>, + <<"access">> := <<"2">>, <<"qos">> := <<"1">>, <<"retain">> := <<"false">> }, @@ -335,6 +341,7 @@ t_json_body(_Config) -> <<"mountpoint">> => <<"${mountpoint}">>, <<"topic">> => <<"${topic}">>, <<"action">> => <<"${action}">>, + <<"access">> => <<"${access}">>, <<"qos">> => <<"${qos}">>, <<"retain">> => <<"${retain}">> } @@ -402,7 +409,7 @@ t_placeholder_and_body(_Config) -> cowboy_req:path(Req0) ), - {ok, [{PostVars, true}], Req1} = cowboy_req:read_urlencoded_body(Req0), + {ok, PostVars, Req1} = cowboy_req:read_urlencoded_body(Req0), ?assertMatch( #{ @@ -413,10 +420,11 @@ t_placeholder_and_body(_Config) -> <<"mountpoint">> := <<"MOUNTPOINT">>, <<"topic">> := <<"t">>, <<"action">> := <<"publish">>, + <<"access">> := <<"2">>, <<"CN">> := ?PH_CERT_CN_NAME, <<"CS">> := ?PH_CERT_SUBJECT }, - emqx_utils_json:decode(PostVars, [return_maps]) + maps:from_list(PostVars) ), {ok, ?AUTHZ_HTTP_RESP(allow, Req1), State} end, @@ -430,6 +438,7 @@ t_placeholder_and_body(_Config) -> <<"mountpoint">> => <<"${mountpoint}">>, <<"topic">> => <<"${topic}">>, <<"action">> => <<"${action}">>, + <<"access">> => <<"${access}">>, <<"CN">> => ?PH_CERT_CN_NAME, <<"CS">> => ?PH_CERT_SUBJECT }, diff --git a/changes/ce/fix-13164.en.md b/changes/ce/fix-13164.en.md new file mode 100644 index 000000000..c0ce937da --- /dev/null +++ b/changes/ce/fix-13164.en.md @@ -0,0 +1,6 @@ +Fix HTTP authorization request body encoding. + +Prior to this fix, the HTTP authorization request body encoding format was taken from the `accept` header. +The fix is to respect the `content-type` header instead. +Also added `access` templating variable for v4 compatibility. +The access code of SUBSCRIBE action is `1` and SUBSCRIBE action is `2`.